mirror of
https://github.com/nexu-io/open-design.git
synced 2026-09-20 06:15:06 +08:00
fd1c0ecb93
* 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.
51 lines
1.9 KiB
TypeScript
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');
|
|
});
|
|
});
|