Skip to content

Add light mode + collapsible Settings cards + Appearance section#8

Merged
bootuz merged 2 commits into
mainfrom
feat/light-mode
May 24, 2026
Merged

Add light mode + collapsible Settings cards + Appearance section#8
bootuz merged 2 commits into
mainfrom
feat/light-mode

Conversation

@bootuz
Copy link
Copy Markdown
Owner

@bootuz bootuz commented May 24, 2026

Summary

Settings panel grows an Appearance card at the top with a segmented Light / Dark / System theme picker, and the existing API integration sections (App Store Connect, Apple Search Ads) become collapsible cards with a green checkmark on the Connected status. The whole app picks up a light theme (dark stays the default).

Demo

Dark stays the default; switch to Light from Settings → Appearance. System follows the OS live via prefers-color-scheme (test it by toggling macOS appearance — the page flips without you touching anything).

What changed

New: theme infrastructure

  • web/src/lib/theme.ts — localStorage-backed Theme store (light/dark/system), idempotent matchMedia listener for live OS-preference following.
  • web/src/components/ThemePicker.svelte — controlled segmented picker with sun/moon/laptop SVG icons.
  • web/index.html — inline <script> in <head> applies the saved theme class before first paint (module scripts can't avoid FOUC because they're deferred).
  • web/src/main.ts — calls initTheme() before mount for runtime listener setup.
  • web/src/app.css — light scrollbar by default, dark scoped via html.dark.

Settings panel UX

  • New Appearance card at the top.
  • ASC and ASA sections wrapped in collapsible cards with a clickable header (chevron + title + status badge).
  • Smart default: auto-opens on load when not yet configured; collapsed when Connected.
  • transition:slide (200ms) on expand/collapse; aria-expanded + aria-controls wired in for screen readers.
  • Green checkmark SVG next to the "Connected" status label.

Component sweep — 20 .svelte files

Existing dark-only color classes paired with light-mode counterparts using Tailwind's dark: variant (darkMode: 'class' was already configured but never used). Mapping recipe:

Dark-only Paired form
bg-zinc-950 bg-white dark:bg-zinc-950
bg-zinc-900/800/700 bg-zinc-50/100/200 dark:bg-zinc-900/800/700
text-zinc-100/200/300/400 text-zinc-900/800/700/600 dark:text-zinc-100/200/300/400
text-zinc-500 unchanged (middle gray reads on both)
Accent text-emerald/amber/red/blue-400 deepened to -600 in light mode for contrast
Inverted emphasis (bg-zinc-100, text-zinc-950) flipped pair-wise

UI fixes surfaced during the migration

Symptom Fix
Dashboard unread-chart badge (bg-amber-500) had near-white text in light mode Kept text-zinc-950 in both modes — yellow needs dark text
Country combobox checkmarks had same yellow-contrast bug Same fix
Chart notifications banner body (text-blue-200) invisible on bg-blue-50 Paired with text-blue-700
"Back to Keywords" + AddAppModal submit buttons disappeared on hover in light mode (hover:bg-white on light bg) Mirrored to hover:bg-black dark:hover:bg-white
DotsIndicator empty dots (bg-zinc-700) looked like filled dark dots on white Paired with bg-zinc-300 for the figure/ground recede

Verification

  • npm run check — 0 errors / 0 warnings across 146 files
  • Manual: switched between Light / Dark / System; flipped OS preference while on System and the page followed; hard-reloaded on Light → no FOUC; hovered every CTA in both modes
  • Toggle the API section cards open/closed; auto-open on first load when Not connected

Relationship to #7

#7 (the ASA docs-link copy edit) was branched off the same main and is still open. The two PRs both touch SettingsPanel.svelte but at different lines:

Whichever merges first, the other rebases cleanly. (I verified by stashing this work onto fresh main and getting only a one-line content overlap on the <code> element, which I kept aligned with main's text.)

bootuz and others added 2 commits May 24, 2026 15:11
Settings panel grows an 'Appearance' card at the top with a segmented
Light / Dark / System theme picker. Dark stays the default (and survives
hard reloads via an inline boot script that prevents FOUC); 'System'
follows OS preference live via prefers-color-scheme.

The API integrations (App Store Connect, Apple Search Ads) now live in
collapsible cards that open automatically when not yet configured and
collapse once Connected, with a green checkmark next to the status.

Theme plumbing:
- lib/theme.ts: localStorage-backed Theme store (light/dark/system),
  idempotent matchMedia listener, FOUC-free initTheme() called from main.ts
- components/ThemePicker.svelte: controlled segmented control with
  sun/moon/laptop SVG icons
- index.html: inline <script> in <head> applies the saved theme class
  before first paint so module scripts can't introduce a flash
- app.css: light-mode scrollbar via html.dark scoping

Components (20 .svelte files) get light-mode counterparts paired with
the existing dark classes (bg-zinc-950 → bg-white dark:bg-zinc-950, etc.).
zinc-500 left untouched where it reads on both backgrounds. Accent text
(emerald/amber/red/blue -400) deepened in light mode for contrast.

UI fixes surfaced by the migration:
- Dashboard unread chart badge: kept text-zinc-950 on bg-amber-500 in
  both modes (yellow needs dark text)
- CountryMultiCombobox/CountrySelect checkbox indicators: same fix
- ChartsPage notification banner: text-blue-200 was unreadable on
  bg-blue-50, paired with text-blue-700
- Charts 'Back to Keywords' + AddAppModal submit: hover:bg-white in
  light mode made buttons disappear; mirrored to hover:bg-black
- DotsIndicator empty dots: bg-zinc-700 was too dark on white;
  paired with bg-zinc-300 for figure/ground contrast in light mode
@bootuz bootuz merged commit 2afb318 into main May 24, 2026
3 checks passed
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