From f1e3f4bd20a514b359891b6a0f4144c50cf828a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E9=98=BF=E6=B1=9F=28Relakkes?= =?UTF-8?q?=29?= Date: Wed, 13 May 2026 18:48:00 +0800 Subject: [PATCH] Preserve activity stats contrast across desktop themes The activity heatmap was reusing broad primary and inverse tokens whose meaning changes by theme. The usage tooltip became unreadable in dark mode, and nearby status badges referenced semantic container tokens that were not available in every theme. This introduces activity-specific theme tokens and locks the token surface with focused regression coverage. Constraint: Desktop supports light, white, and dark themes from globals.css Rejected: Change global primary or inverse tokens | broader blast radius across unrelated controls Confidence: high Scope-risk: narrow Directive: Keep activity heatmap colors behind activity-specific tokens before changing palette behavior Tested: cd desktop && bun run test ActivitySettings.test.tsx globals.test.ts Tested: bun run check:desktop Tested: Browser smoke on dark Token usage tooltip at http://127.0.0.1:5179 Not-tested: Native packaged app visual smoke --- desktop/src/pages/ActivitySettings.test.tsx | 3 ++ desktop/src/pages/ActivitySettings.tsx | 22 ++++----- desktop/src/theme/globals.css | 52 +++++++++++++++++++ desktop/src/theme/globals.test.ts | 55 +++++++++++++++++++++ 4 files changed, 121 insertions(+), 11 deletions(-) create mode 100644 desktop/src/theme/globals.test.ts diff --git a/desktop/src/pages/ActivitySettings.test.tsx b/desktop/src/pages/ActivitySettings.test.tsx index a21bbbca..dc8e5baf 100644 --- a/desktop/src/pages/ActivitySettings.test.tsx +++ b/desktop/src/pages/ActivitySettings.test.tsx @@ -112,6 +112,9 @@ describe('ActivitySettings', () => { expect(tooltip).toHaveTextContent('May 9, 2026') expect(tooltip).toHaveTextContent('4 sessions · 128K tokens') expect(tooltip).not.toHaveTextContent(/messages|tools/i) + expect(tooltip.className).toContain('--color-activity-tooltip-surface') + expect(tooltip.className).toContain('--color-activity-tooltip-border') + expect(todayCell.className).toContain('--color-activity-cell-border') expect(screen.queryByText('Selected day')).not.toBeInTheDocument() }) }) diff --git a/desktop/src/pages/ActivitySettings.tsx b/desktop/src/pages/ActivitySettings.tsx index 88d0c594..bf71931b 100644 --- a/desktop/src/pages/ActivitySettings.tsx +++ b/desktop/src/pages/ActivitySettings.tsx @@ -30,11 +30,11 @@ const HEAT_CELL_MIN = 6 const HEAT_CELL_MAX = 22 const TOOLTIP_WIDTH = 172 const HEAT_COLORS = [ - 'var(--color-surface-container)', - 'var(--color-primary-fixed)', - 'var(--color-primary-fixed-dim)', - 'var(--color-primary-container)', - 'var(--color-primary)', + 'var(--color-activity-heat-0)', + 'var(--color-activity-heat-1)', + 'var(--color-activity-heat-2)', + 'var(--color-activity-heat-3)', + 'var(--color-activity-heat-4)', ] const DATE_LOCALES: Record = { en: 'en-US', @@ -380,8 +380,8 @@ export function ActivitySettings() { aria-describedby={activeTooltipDate === day.date ? tooltipId : undefined} className={`rounded-[3px] border transition-[border-color,transform] hover:scale-110 focus:outline-none focus:ring-2 focus:ring-[var(--color-brand)] focus:ring-offset-2 focus:ring-offset-[var(--color-surface)] ${ isSelected - ? 'border-[var(--color-text-primary)]' - : 'border-[var(--color-border)]/30 hover:border-[var(--color-text-secondary)]' + ? 'border-[var(--color-activity-cell-border-active)]' + : 'border-[var(--color-activity-cell-border)] hover:border-[var(--color-activity-cell-border-hover)]' }`} style={{ width: heatCellSize, @@ -401,11 +401,11 @@ export function ActivitySettings() {