fix: improve Today mobile environment layout
This commit is contained in:
@@ -89,10 +89,24 @@ describe('TodayEnvironmentStrip', () => {
|
||||
expect(host.querySelectorAll('.today-environment__refreshing')).toHaveLength(0)
|
||||
})
|
||||
|
||||
it('keeps refresh announcements out of the visual row layout', () => {
|
||||
it('renders compact mobile date copy while preserving desktop and gold date semantics', async () => {
|
||||
const host = await mountStrip({ environment })
|
||||
expect(host.querySelector('.today-environment__calendar-main--desktop')?.textContent).toBe('2026年9月16日 星期三')
|
||||
expect(host.querySelector('.today-environment__calendar-main--mobile')?.textContent).toBe('9月16日 周三')
|
||||
const goldDate = host.querySelector('.today-environment__gold-date--mobile')
|
||||
expect(goldDate?.textContent).toBe('09-15')
|
||||
expect(goldDate?.getAttribute('title')).toBe('市场日期 2026-09-15')
|
||||
expect(goldDate?.getAttribute('aria-label')).toBe('市场日期 2026-09-15')
|
||||
})
|
||||
|
||||
it('keeps mobile content to a horizontal calendar row and two stacked source columns', () => {
|
||||
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__item{display:flex;gap:4px;overflow:hidden}')
|
||||
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__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%}')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -45,6 +45,23 @@ const calendar = computed<CalendarValue | null>(() => {
|
||||
const value = props.environment?.date
|
||||
return value ? { solar_date: value.solar_date, weekday: value.weekday, lunar_date: value.lunar } : null
|
||||
})
|
||||
const mobileCalendarDate = computed(() => {
|
||||
const value = calendar.value
|
||||
if (!value) return ''
|
||||
const chineseDate = value.solar_date.match(/^\d{4}年(\d{1,2})月(\d{1,2})日$/)
|
||||
const isoDate = value.solar_date.match(/^\d{4}-(\d{2})-(\d{2})$/)
|
||||
const date = chineseDate
|
||||
? `${Number(chineseDate[1])}月${Number(chineseDate[2])}日`
|
||||
: isoDate
|
||||
? `${Number(isoDate[1])}月${Number(isoDate[2])}日`
|
||||
: value.solar_date
|
||||
return `${date} ${value.weekday.replace(/^星期/, '周')}`
|
||||
})
|
||||
const goldMarketDate = computed(() => props.environment?.gold?.market_date || '')
|
||||
const mobileGoldMarketDate = computed(() => {
|
||||
const match = goldMarketDate.value.match(/^\d{4}-(\d{2})-(\d{2})$/)
|
||||
return match ? `${match[1]}-${match[2]}` : goldMarketDate.value
|
||||
})
|
||||
const weatherStatus = computed<EnvironmentStatus>(() => {
|
||||
if (!props.environment?.weather) return 'unavailable'
|
||||
return props.environment.weather.status ?? (props.environment.weather.stale ? 'stale' : 'fresh')
|
||||
@@ -88,7 +105,8 @@ const weatherObservation = computed(() => {
|
||||
<span v-else-if="!environment" class="today-environment__state today-environment__status" role="status" aria-live="polite">环境信息暂不可用</span>
|
||||
<template v-else>
|
||||
<span v-if="calendar" class="today-environment__item today-environment__calendar">
|
||||
<strong>{{ calendar.solar_date }} {{ calendar.weekday }}</strong>
|
||||
<strong class="today-environment__calendar-main--desktop">{{ calendar.solar_date }} {{ calendar.weekday }}</strong>
|
||||
<strong class="today-environment__calendar-main--mobile" :aria-label="`${calendar.solar_date} ${calendar.weekday}`">{{ mobileCalendarDate }}</strong>
|
||||
<small>{{ calendar.lunar_date }}</small>
|
||||
</span>
|
||||
<span class="today-environment__item today-environment__weather" :class="`is-${weatherStatus}`">
|
||||
@@ -99,7 +117,7 @@ const weatherObservation = computed(() => {
|
||||
<span class="today-environment__item today-environment__gold" :class="`is-${goldStatus}`">
|
||||
<strong v-if="goldStatus !== 'unavailable' && goldPrice">{{ environment.gold?.symbol || environment.gold?.contract || 'Au99.99' }} ¥{{ goldPrice }}/g</strong>
|
||||
<strong v-else>Au99.99 暂不可用</strong>
|
||||
<small><template v-if="goldStatus !== 'unavailable'">上金所延时<template v-if="environment.gold?.market_date"> · {{ environment.gold.market_date }}</template></template><template v-if="goldStatus === 'stale'"> · 缓存</template></small>
|
||||
<small><template v-if="goldStatus !== 'unavailable'">上金所延时<template v-if="goldMarketDate"> · <span class="today-environment__gold-date today-environment__gold-date--desktop">{{ goldMarketDate }}</span><span class="today-environment__gold-date today-environment__gold-date--mobile" :title="`市场日期 ${goldMarketDate}`" :aria-label="`市场日期 ${goldMarketDate}`">{{ mobileGoldMarketDate }}</span></template></template><template v-if="goldStatus === 'stale'"> · 缓存</template></small>
|
||||
</span>
|
||||
<span class="today-environment__status" role="status" aria-live="polite"><template v-if="loading">更新中…</template><template v-else-if="failed">更新失败,显示上次信息</template></span>
|
||||
</template>
|
||||
|
||||
@@ -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}@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}.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__status{grid-column:1/-1;grid-row:1;justify-self:end;max-width:42%;margin-left:0;overflow:hidden;text-overflow:ellipsis}.today-environment__calendar{padding-right:42%}.today-environment__item{display:flex;gap:4px;overflow:hidden}.today-environment__item strong{font-size:12px}.today-environment__item small{font-size:10px}}
|
||||
.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}}
|
||||
|
||||
/* 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)}
|
||||
|
||||
Reference in New Issue
Block a user