feat(viewer): UI-02 visual foundation, top bar and album info
V01+V02 (Task 2 of the UI-02 viewer redesign plan): - viewer-tokens.css: UI-02 §3.1 design tokens scoped to .viewer-shell (never :root), so embed routes consume none of them - App.vue: normal routes get a sticky white top bar (PhotoLive brand + compact locale switcher + lightweight "..." menu holding the reduce-motion toggle); global 16px content padding removed so banner and photos run edge-to-edge; embed shell branch untouched - LocaleSwitcher: compact "EN/中文 + caret" trigger with a proper menu (current language checked), 44px touch target, Escape/outside close - AlbumHeader (new): banner (2.4:1 mobile, 320px desktop cap, object-fit contain, collapses on missing/failed), 2-line expandable title + share button (clipboard copy with selectable-text fallback), 3-line expandable pre-line description, meta row (Intl-formatted view count with em-dash fallback for unknown, album-timezone dates with full range on title, venue), Latest/Popular 44px tabs and category pills from the API with horizontal scroll + overflow fade - ActivityPage: delegates the info area to AlbumHeader; sequence reset/sort-lock/category-by-id semantics unchanged; desktop content capped at 1120px - i18n: viewer.* strings (brand/share/views/readMore/latest/popular/ allCategories/noPhotos/newPhotos/reduceMotion/settings) in zh-CN+en - tests: viewer-shell (token source + normal/embed isolation) and album-header (8 cases) specs; activity/i18n specs updated for the menu switcher and the em-dash unknown view count; e2e selectors refreshed Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -28,15 +28,27 @@ describe('viewer i18n', () => {
|
||||
expect(wrapper.text()).toContain('打开相册链接即可观看');
|
||||
expect(document.title).toBe('现场相册');
|
||||
|
||||
await wrapper.find('button.locale-switcher').trigger('click');
|
||||
// UI-02 V01 紧凑语言控件:展开菜单 → 选择 English。
|
||||
await wrapper.find('.locale-trigger').trigger('click');
|
||||
await nextTick();
|
||||
const english = wrapper.findAll('.locale-option').find((btn) => btn.text() === 'English');
|
||||
expect(english).toBeDefined();
|
||||
await english!.trigger('click');
|
||||
await nextTick();
|
||||
expect(wrapper.text()).toContain('Open an album link to start viewing');
|
||||
expect(document.title).toBe('Live Gallery');
|
||||
expect(document.documentElement.getAttribute('lang')).toBe('en');
|
||||
expect(localStorage.getItem(LOCALE_STORAGE_KEY)).toBe('en');
|
||||
|
||||
// 切回 zh-CN 同样生效
|
||||
await wrapper.find('button.locale-switcher').trigger('click');
|
||||
// 切回 zh-CN 同样生效(菜单内当前语言 English 为勾选态)。
|
||||
await wrapper.find('.locale-trigger').trigger('click');
|
||||
await nextTick();
|
||||
const options = wrapper.findAll('.locale-option');
|
||||
const englishNow = options.find((btn) => btn.text() === 'English');
|
||||
expect(englishNow!.attributes('aria-checked')).toBe('true');
|
||||
const chinese = options.find((btn) => btn.text() === '中文');
|
||||
expect(chinese!.attributes('aria-checked')).toBe('false');
|
||||
await chinese!.trigger('click');
|
||||
await nextTick();
|
||||
expect(wrapper.text()).toContain('打开相册链接即可观看');
|
||||
expect(localStorage.getItem(LOCALE_STORAGE_KEY)).toBe('zh-CN');
|
||||
|
||||
Reference in New Issue
Block a user