From 6f38190c921bf018fa7414232bc381c4265890c0 Mon Sep 17 00:00:00 2001 From: bboysoul Date: Wed, 16 Sep 2026 14:47:02 +0800 Subject: [PATCH] style: refine Today environment header --- frontend/src/TodayEnvironment.test.ts | 4 +- .../components/TodayEnvironmentStrip.test.ts | 51 ++++++++++++++++--- .../src/components/TodayEnvironmentStrip.vue | 33 +++++++++--- frontend/src/style.css | 2 +- 4 files changed, 73 insertions(+), 17 deletions(-) diff --git a/frontend/src/TodayEnvironment.test.ts b/frontend/src/TodayEnvironment.test.ts index 9665968..21a0f9a 100644 --- a/frontend/src/TodayEnvironment.test.ts +++ b/frontend/src/TodayEnvironment.test.ts @@ -39,8 +39,8 @@ describe('Today environment integration', () => { }) it('keeps mobile environment copy to two rows including refresh states', () => { - expect(css).toMatch(/@container\(max-width:559px\)\{\.today-environment\{[^}]*grid-template-rows:repeat\(2,minmax\(0,auto\)\)/) - expect(css).toMatch(/\.today-environment__status\{[^}]*grid-row:1/) + expect(css).toMatch(/@container\(max-width:559px\)\{\.today-environment\{[^}]*grid-template-rows:auto auto/) + expect(css).toMatch(/\.today-environment__status\{[^}]*grid-column:auto;grid-row:auto/) expect(css).not.toContain('.today-environment__refreshing') }) diff --git a/frontend/src/components/TodayEnvironmentStrip.test.ts b/frontend/src/components/TodayEnvironmentStrip.test.ts index 0a6a1d4..a2e9437 100644 --- a/frontend/src/components/TodayEnvironmentStrip.test.ts +++ b/frontend/src/components/TodayEnvironmentStrip.test.ts @@ -99,14 +99,53 @@ describe('TodayEnvironmentStrip', () => { expect(goldDate?.getAttribute('aria-label')).toBe('市场日期 2026-09-15') }) - it('keeps mobile content to a horizontal calendar row and two stacked source columns', () => { + it('shows edit-line state only when attention is required', async () => { + const fresh = await mountStrip({ environment: { ...environment, gold: { ...environment.gold!, status: 'fresh' } } }) + expect(fresh.querySelector('.today-environment')?.classList.contains('has-attention')).toBe(false) + expect(fresh.querySelector('.today-environment__status')?.textContent).toBe('') + + const refreshing = await mountStrip({ environment, loading: true }) + expect(refreshing.querySelector('.today-environment')?.classList.contains('is-refreshing')).toBe(true) + expect(refreshing.querySelector('.today-environment__status')?.textContent).toContain('更新中') + + const failed = await mountStrip({ environment, failed: true }) + expect(failed.querySelector('.today-environment')?.classList.contains('has-attention')).toBe(true) + expect(failed.querySelector('.today-environment__status')?.textContent).toContain('更新失败 · 上次信息') + }) + + it('renders unavailable sources as two-line placeholders without adding a status row', async () => { + const host = await mountStrip({ environment: { + calendar: environment.calendar, + weather: { status: 'unavailable' }, + gold: { status: 'unavailable' }, + } }) + expect(host.querySelectorAll('.today-environment__skeleton')).toHaveLength(4) + expect(host.querySelectorAll('.today-environment__weather > .today-environment__skeleton')).toHaveLength(2) + expect(host.querySelectorAll('.today-environment__gold > .today-environment__skeleton')).toHaveLength(2) + }) + + it('uses the approved cream edit-line typography and separators', () => { const css = readFileSync(resolve(process.cwd(), 'src/style.css'), 'utf8') - expect(css).toContain('.today-environment__status:not(.today-environment__state){position:absolute;width:1px;height:1px;') - expect(css).toContain('@container(max-width:559px){.today-environment{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);') - expect(css).toContain('.today-environment__calendar{grid-column:1/-1;grid-row:1;display:flex;flex-direction:row;padding-right:0}') - expect(css).toContain('.today-environment__weather,.today-environment__gold{display:flex;flex-direction:column;align-items:flex-start;gap:2px}') + expect(css).toContain('.today-environment{grid-column:1/-1;position:relative;min-width:0;min-height:40px;') + expect(css).toContain('color:#302a24;font-size:14px;font-weight:650') + expect(css).toContain('color:#655b50;font-size:12px;font-weight:450') + expect(css).toContain('color:#8b8275;font-size:11px;font-weight:400') + expect(css).toContain('.today-environment:after{content:"";position:absolute;left:10px;right:10px;bottom:0;height:1px;background:#e4d5c0}') + expect(css).toContain('.today-environment.has-attention:before{content:"";width:2px;height:14px;background:#f15a29') + expect(css).not.toContain('border-left:1px solid var(--border-cream)') + expect(css).not.toMatch(/\.today-environment[^}]*gradient|\.today-environment[^}]*box-shadow|\.today-environment[^}]*backdrop-filter/) + }) + + it('keeps mobile content to exactly two parent rows with stacked source columns', () => { + const css = readFileSync(resolve(process.cwd(), 'src/style.css'), 'utf8') + expect(css).toContain('@container(max-width:559px){.today-environment{min-height:68px;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);grid-template-rows:auto auto;column-gap:14px;') + expect(css).toContain('.today-environment__calendar{grid-column:1/-1;grid-row:1;display:flex;flex-direction:row;') + expect(css).toContain('.today-environment__weather,.today-environment__gold{display:flex;flex-direction:column;align-items:flex-start;gap:2px;overflow:visible}') + expect(css).toContain('.today-environment__gold{grid-column:2;grid-row:2;padding-left:14px}') + expect(css).toContain('.today-environment__gold:before{content:"";position:absolute;left:0;top:4px;width:1px;height:14px;background:#e4d5c0}') expect(css).toContain('.today-environment__calendar-main--desktop,.today-environment__gold-date--desktop{display:none}') expect(css).toContain('.today-environment__calendar-main--mobile,.today-environment__gold-date--mobile{display:inline}') - expect(css).not.toContain('.today-environment__calendar{padding-right:42%}') + const mobileBlock = css.slice(css.indexOf('@container(max-width:559px){.today-environment'), css.indexOf('/* Solid cream material system')) + expect(mobileBlock).not.toContain('text-overflow:ellipsis') }) }) diff --git a/frontend/src/components/TodayEnvironmentStrip.vue b/frontend/src/components/TodayEnvironmentStrip.vue index 189ac59..39bb8ac 100644 --- a/frontend/src/components/TodayEnvironmentStrip.vue +++ b/frontend/src/components/TodayEnvironmentStrip.vue @@ -100,7 +100,12 @@ const weatherObservation = computed(() => { diff --git a/frontend/src/style.css b/frontend/src/style.css index 716b48f..2ec21b5 100644 --- a/frontend/src/style.css +++ b/frontend/src/style.css @@ -49,7 +49,7 @@ main{container-type:inline-size;min-width:0;padding:27px 34px 50px;overflow:auto .task-row.just-completed,.habit-row.just-completed{animation:completion-row-settle .34s cubic-bezier(.2,.85,.3,1)}.task-row.just-completed .task-check-mark,.habit-row.just-completed .task-check-mark{animation:completion-check-pop .38s cubic-bezier(.2,1.4,.35,1)}.task-row.completion-exiting,.habit-row.completion-exiting{pointer-events:none;overflow:hidden;animation:completion-slide-out .32s cubic-bezier(.4,0,.8,.2) forwards}@keyframes completion-slide-out{0%{opacity:1;transform:translate(var(--swipe-x),var(--reorder-y,0px));max-height:180px}68%{opacity:0;transform:translate(calc(100% + 24px),var(--reorder-y,0px));max-height:180px}100%{opacity:0;transform:translate(calc(100% + 24px),var(--reorder-y,0px));max-height:0;min-height:0;padding-top:0;padding-bottom:0;border-width:0}}@keyframes completion-row-settle{0%{background:rgba(113,133,107,.16);transform:translate(var(--swipe-x),var(--reorder-y,0px)) scale(1)}45%{background:rgba(113,133,107,.1);transform:translate(var(--swipe-x),var(--reorder-y,0px)) scale(.992)}100%{transform:translate(var(--swipe-x),var(--reorder-y,0px)) scale(1)}}@keyframes completion-check-pop{0%{transform:scale(.72);box-shadow:0 0 0 0 rgba(113,133,107,.28)}58%{transform:scale(1.18);box-shadow:0 0 0 7px rgba(113,133,107,0)}100%{transform:scale(1);box-shadow:none}}@media(prefers-reduced-motion:reduce){.task-row.just-completed,.habit-row.just-completed,.task-row.just-completed .task-check-mark,.habit-row.just-completed .task-check-mark{animation:none}.task-row.completion-exiting,.habit-row.completion-exiting{animation:none}} /* Today environment information strip. */ -.today-environment{grid-column:1/-1;min-width:0;display:flex;align-items:center;gap:12px;padding:0 0 12px;border-bottom:1px solid var(--border-cream);color:var(--text-secondary)}.today-environment__item{min-width:0;display:flex;align-items:baseline;gap:6px;white-space:nowrap;overflow:hidden}.today-environment__item strong,.today-environment__item small{overflow:hidden;text-overflow:ellipsis}.today-environment__item strong{color:var(--text-primary);font-size:13px}.today-environment__item small,.today-environment__status,.today-environment__state{color:var(--muted);font-size:11px}.today-environment__status:not(.today-environment__state){position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.today-environment__item+.today-environment__item{padding-left:12px;border-left:1px solid var(--border-cream)}.today-environment__item.is-stale small{color:#9a704c}.today-environment__status{margin-left:auto;white-space:nowrap}.today-environment__status:empty{display:none}.today-environment__state{min-height:22px;display:flex;align-items:center}.today-environment__calendar-main--mobile,.today-environment__gold-date--mobile{display:none}@container(min-width:560px){.today-environment{flex-wrap:nowrap}.today-environment__calendar{flex:1}.today-environment__weather,.today-environment__gold{flex:0 1 auto}}@container(max-width:559px){.today-environment{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);grid-template-rows:repeat(2,minmax(0,auto));gap:7px 10px}.today-environment__calendar{grid-column:1/-1;grid-row:1;display:flex;flex-direction:row;padding-right:0}.today-environment__item+.today-environment__item{padding-left:0;border-left:0}.today-environment__weather{grid-column:1;grid-row:2}.today-environment__gold{grid-column:2;grid-row:2}.today-environment__weather,.today-environment__gold{display:flex;flex-direction:column;align-items:flex-start;gap:2px}.today-environment__status{grid-column:1/-1;grid-row:1;margin-left:0}.today-environment__calendar-main--desktop,.today-environment__gold-date--desktop{display:none}.today-environment__calendar-main--mobile,.today-environment__gold-date--mobile{display:inline}.today-environment__item{overflow:hidden}.today-environment__item strong{max-width:100%;font-size:12px}.today-environment__item small{max-width:100%;font-size:10px}} +.today-environment{grid-column:1/-1;position:relative;min-width:0;min-height:40px;display:flex;align-items:center;gap:14px;padding:0 10px 1px;color:#655b50;font-variant-numeric:tabular-nums}.today-environment:after{content:"";position:absolute;left:10px;right:10px;bottom:0;height:1px;background:#e4d5c0}.today-environment.has-attention:before{content:"";width:2px;height:14px;background:#f15a29;border-radius:1px;flex:0 0 2px}.today-environment__item{position:relative;min-width:0;display:flex;align-items:baseline;gap:6px;white-space:nowrap}.today-environment__calendar strong{color:#302a24;font-size:14px;font-weight:650}.today-environment__calendar small{color:#655b50;font-size:12px;font-weight:450}.today-environment__weather strong,.today-environment__gold strong{color:#302a24;font-size:13px;font-weight:600}.today-environment__item small,.today-environment__status,.today-environment__state{color:#8b8275;font-size:11px;font-weight:400}.today-environment__item+.today-environment__item:before{content:"·";position:absolute;left:-9px;color:#b7aa98}.today-environment__item.is-stale small{color:#8b8275}.today-environment__status{color:#f15a29;margin-left:2px;white-space:nowrap}.today-environment__status:empty{display:none}.today-environment__state{min-height:22px;display:flex;align-items:center}.today-environment__skeleton{display:block;width:104px;height:8px;background:#eadfce;border-radius:2px}.today-environment__skeleton--short{width:72px;height:6px}.today-environment__calendar-main--mobile,.today-environment__gold-date--mobile{display:none}@container(min-width:560px){.today-environment{flex-wrap:nowrap}.today-environment__calendar{flex:1}.today-environment__weather,.today-environment__gold{flex:0 1 auto}}@container(max-width:559px){.today-environment{min-height:68px;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);grid-template-rows:auto auto;column-gap:14px;row-gap:3px;padding:2px 10px 3px}.today-environment.has-attention:before{position:absolute;left:0;top:8px}.today-environment__calendar{grid-column:1/-1;grid-row:1;display:flex;flex-direction:row;align-items:baseline;gap:6px}.today-environment__status:not(:empty):before{content:"";display:inline-block;width:4px;height:4px;margin-right:4px;border-radius:50%;background:#f15a29;vertical-align:middle}.today-environment__item+.today-environment__item:before{content:none}.today-environment__weather{grid-column:1;grid-row:2}.today-environment__gold{grid-column:2;grid-row:2;padding-left:14px}.today-environment__gold:before{content:"";position:absolute;left:0;top:4px;width:1px;height:14px;background:#e4d5c0}.today-environment__weather,.today-environment__gold{display:flex;flex-direction:column;align-items:flex-start;gap:2px;overflow:visible}.today-environment__status{grid-column:auto;grid-row:auto;margin-left:2px}.today-environment__calendar-main--desktop,.today-environment__gold-date--desktop{display:none}.today-environment__calendar-main--mobile,.today-environment__gold-date--mobile{display:inline}.today-environment__weather strong,.today-environment__gold strong{font-size:13px}.today-environment__item small{font-size:11px}} /* Solid cream material system: opaque surfaces, warm edges, quiet depth. */ :root{--surface-canvas:#f3ecdf;--surface-base:#fdfaf3;--surface-raised:#fffdf8;--text-primary:#302a24;--text-secondary:#655b50;--border-cream:#e4d5c0;--highlight-inner:inset 0 1px 0 #fff;--shadow-soft:0 4px 14px rgba(88,67,42,.08);--shadow-raised:0 12px 30px rgba(88,67,42,.12);--focus-ring:rgba(180,66,30,.34);--success:#687e61;--scrim:rgba(45,38,31,.38);--radius-control:11px;--radius-card:14px;--radius-list:15px;--radius-panel:20px;--paper:var(--surface-raised);--sidebar:var(--surface-canvas);--line:var(--border-cream);--muted:var(--text-secondary);--shadow:var(--shadow-raised);--sheet-radius:20px;--sheet-scrim:var(--scrim)}