Skip to content

feat: light theme with runtime Light/Dark toggle - #11

Merged
Fyfar merged 1 commit into
mainfrom
feat/light-theme
Oct 15, 2026
Merged

Fyfar merged 1 commit into
mainfrom
feat/light-theme

Conversation

@Fyfar

@Fyfar Fyfar commented Oct 15, 2026

Copy link
Copy Markdown
Owner

Summary

Adds a light theme. The header's ⋮ button didn't do anything; it's now a text toggle that switches themes at runtime, with no page reload.

  • The label names the theme a click switches to: Light while dark, Dark while light.
  • Only neutral colors change (backgrounds, panels, borders, text, chart axes/grid/tooltip). Green/red (start/stop, pass/fail), the blue accent and amber stay the same in both themes.
  • Switching leaves the connection, recording, recorded data, current view and settings untouched.
  • The choice persists (localStorage key multimeter-live:theme). An inline pre-paint script in layout.tsx applies it, so a stored light theme never flashes dark. Defaults to dark; the OS color-scheme preference is not followed. If storage is blocked, it falls back to dark and the toggle still works for the session.
  • Version 2.0.3 → 2.1.0.

How

  • app/globals.css: :root[data-theme="light"] redefines the 6 neutral @theme tokens. Tailwind v4 utilities resolve via var(--color-*), so every component restyles without edits. color-scheme follows the theme, which covers native inputs, selects and scrollbars.
  • app/page.tsx: theme state plus toggleTheme; the AppHeader button replaces MoreVertical.
  • components/RealtimeChart.tsx: canvas neutrals come from a per-theme CHART_NEUTRALS palette. theme recreates the chart and is also a redraw dependency, so the chart repaints while disconnected.

Testing

  • npm run lint, npx tsc --noEmit, npm run check, npm run build, npm run fallow: all pass; fallow reports no new findings.
  • Headless Chrome against the static build passed checks for: label/theme flip on click, Enter and Space; no reload; unchanged semantic colors; persistence across reload with the theme set before DOMContentLoaded; storage-blocked fallback; no hydration warnings.
  • Hardware (ZOYI ZT703s): checked every view, the no-data warning, toggling during a live recording, and charts with data in both themes.

Known trade-off

Green/amber text on white has low contrast (#22c55e ≈ 2.3:1). It's kept on purpose, so start/stop colors stay identical across themes. The PWA theme_color also stays dark.

Replace the header's no-op "..." button with a text toggle that names the
theme a click switches to ("Light" while dark, "Dark" while light). The
switch is in place: no reload, and the connection, recording, data and
view are untouched.

Only the neutral tokens (canvas/panel/surface/border/fg/muted) change, via
:root[data-theme="light"] in globals.css; success/danger (start/stop),
accent and amber are identical in both themes. color-scheme follows the
theme so native inputs and scrollbars match.

The choice persists under multimeter-live:theme and is applied by an
inline pre-paint script in layout.tsx, so a stored light theme never
flashes dark. Defaults to dark; storage errors fall back to dark.

The chart's canvas neutrals (axes, grid, tooltip) come from a per-theme
palette; theme recreates the chart and is also a redraw dep so it repaints
while disconnected. Bump version to 2.1.0.
@Fyfar
Fyfar merged commit a8afb5b into main Oct 15, 2026
2 checks passed
@Fyfar
Fyfar deleted the feat/light-theme branch October 15, 2026 11:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant