Files
Tom Huang fd1c0ecb93 Feat/optimize style (#3624)
* Refactor ChatComposer and DesignBrowserPanel components for improved functionality and localization

- Introduced new functions in ChatComposer for managing attachment orders and appending staged attachments, enhancing user experience during file uploads.
- Updated ChatPane to clarify the search button's aria-label for better accessibility.
- Enhanced DesignBrowserPanel with new localization keys for browser use inputs and actions, improving clarity across multiple languages.
- Adjusted styles in various components for better layout and user interaction, including updates to the chat input and staged context elements.

* Update AvatarMenu and Chat components for improved functionality and localization

- Modified AvatarMenu to include an optional section parameter for the onOpenSettings callback, enhancing flexibility in opening settings.
- Updated tests for AvatarMenu to verify the correct section is passed when opening settings.
- Adjusted styles in various components, including the ChatComposer and FileViewer, to improve layout and user interaction.
- Enhanced localization strings across multiple languages to reflect changes in chat mode terminology from 'Chat' to 'Ask', improving clarity for users.
2026-06-04 10:22:39 +00:00

51 lines
1.9 KiB
TypeScript

import { readFileSync } from 'node:fs';
import { describe, expect, it } from 'vitest';
const entryLayoutCss = readFileSync(new URL('../../src/styles/home/entry-layout.css', import.meta.url), 'utf8');
function cssDeclarations(selector: string): string {
const blocks: string[] = [];
const rulePattern = /([^{}]+)\{([^}]*)\}/g;
let match: RegExpExecArray | null;
while ((match = rulePattern.exec(entryLayoutCss)) !== null) {
const selectors = (match[1] ?? '').split(',').map((item) => item.trim());
if (selectors.includes(selector)) blocks.push(match[2] ?? '');
}
if (blocks.length === 0) throw new Error(`Missing CSS block for ${selector}`);
return blocks.join('\n');
}
function ruleValue(block: string, property: string): string {
const matches = [...block.matchAll(new RegExp(`(?:^|[;\\n])\\s*${property}:\\s*([^;]+);`, 'g'))];
const match = matches.at(-1);
if (!match) throw new Error(`Missing CSS property ${property}`);
return match[1]!.trim();
}
describe('InlineModelSwitcher styles', () => {
it('clips long model labels inside the compact chip', () => {
const chip = cssDeclarations('.inline-switcher__chip');
expect(ruleValue(chip, 'overflow')).toBe('hidden');
for (const selector of [
'.inline-switcher__chip-mode',
'.inline-switcher__chip-primary',
'.inline-switcher__chip-model',
]) {
const block = cssDeclarations(selector);
expect(ruleValue(block, 'min-width'), selector).toBe('0');
expect(ruleValue(block, 'overflow'), selector).toBe('hidden');
expect(ruleValue(block, 'text-overflow'), selector).toBe('ellipsis');
expect(ruleValue(block, 'white-space'), selector).toBe('nowrap');
}
});
it('hides the long status text in compact hero placement', () => {
const compactText = cssDeclarations(
'.inline-switcher--compact .inline-switcher__chip-text',
);
expect(ruleValue(compactText, 'display')).toBe('none');
});
});