🎨 fix(web): align UI and charts with theme tokens and presets

Improve theme switching fidelity (including system preference), extend design tokens so color presets tint real surfaces—not only primary/chrome—and refactor shared badges, tables, and dashboard visuals to semantic colors. Wire VChart series colors to `--chart-*` with safe fallbacks.

**Changes**

- **Theme runtime** (`theme-provider.tsx`): Validate stored theme cookie; keep `resolvedTheme` in sync with DOM + `(prefers-color-scheme)`; `resetTheme` respects `defaultTheme`; memoized context value.
- **Tokens** (`theme.css`): Add `--success|warning|info|neutral` (+ foregrounds) and map them under `@theme inline` for Tailwind utilities.
- **Presets** (`theme-presets.css`): For non-`default` presets, derive `card`, `popover`, `muted`, `accent`, `border`, `input`, and sidebar tokens from `--primary`/`--background`; map semantic status colors to preset chart variables.
- **Components**: `status-badge`, `colors` (avatars, announcements), `copy-button`, `group-badge`, `data-table` row styles, `sidebar` outline shadow (fix `var(--sidebar-border)` usage), ai-elements tool/web-preview status colors.
- **Dashboard**: Latency/API helpers and overview fragments use semantic tokens; `charts.ts` reads `--chart-1`…`--chart-5` from computed styles with fallbacks; `processChartData` / `processUserChartData` accept optional `themeKey` for preset churn; chart components pass `customization.preset` and bump `VChart` keys.

**Verification**

- `bun run typecheck`
This commit is contained in:
t0ng7u
2026-05-07 11:20:43 +08:00
parent 415d21d071
commit a7475a1e67
19 changed files with 315 additions and 172 deletions
+24
View File
@@ -25,6 +25,14 @@
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-destructive-foreground: var(--destructive-foreground);
--color-success: var(--success);
--color-success-foreground: var(--success-foreground);
--color-warning: var(--warning);
--color-warning-foreground: var(--warning-foreground);
--color-info: var(--info);
--color-info-foreground: var(--info-foreground);
--color-neutral: var(--neutral);
--color-neutral-foreground: var(--neutral-foreground);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
@@ -70,6 +78,14 @@
--accent-foreground: oklch(0.145 0 0);
--destructive: oklch(0.577 0.245 27.325);
--destructive-foreground: oklch(0.985 0 0);
--success: oklch(0.596 0.145 163.225);
--success-foreground: oklch(0.985 0 0);
--warning: oklch(0.681 0.162 75.834);
--warning-foreground: oklch(0.145 0 0);
--info: oklch(0.588 0.158 241.966);
--info-foreground: oklch(0.985 0 0);
--neutral: oklch(0.708 0 0);
--neutral-foreground: oklch(0.145 0 0);
--border: oklch(0.93 0 0);
--input: oklch(0.93 0 0);
--ring: oklch(0.708 0 0);
@@ -108,6 +124,14 @@
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.704 0.191 22.216);
--destructive-foreground: oklch(0.985 0 0);
--success: oklch(0.696 0.17 162.48);
--success-foreground: oklch(0.145 0 0);
--warning: oklch(0.769 0.188 70.08);
--warning-foreground: oklch(0.145 0 0);
--info: oklch(0.68 0.17 237.323);
--info-foreground: oklch(0.145 0 0);
--neutral: oklch(0.76 0 0);
--neutral-foreground: oklch(0.145 0 0);
--border: oklch(1 0 0 / 9%);
--input: oklch(1 0 0 / 16%);
--ring: oklch(0.68 0 0);