Skip to content

Complete desktop surfaces; add appearance modes and accent colors - #2

Merged
kartikmanimuthu merged 1 commit into
mainfrom
refactoring
Sep 21, 2026
Merged

kartikmanimuthu merged 1 commit into
mainfrom
refactoring

Conversation

@kartikmanimuthu

Copy link
Copy Markdown
Collaborator

What this is

This branch lands the desktop work that was still uncommitted in the worktree (rounds 3–4 of the app spec) together with the new appearance controls. It is one commit because the two bodies of work overlap in the same files (index.css, App.tsx, wire.ts, schemas.test.ts, README.md), so they cannot be split into commits that each build.

Surfaces

  • Files / Workspace page: tree, read, edit, save, new file, reveal, drag-and-drop attachments staged into workspace/uploads/.
  • Memory browser: notes list, search, Markdown view/edit, rename, delete with confirmation.
  • Skills browser: list/preview, create, rename, delete with directory pruning.
  • Threads: search, rename, delete.
  • Providers: CRUD, per-provider model discovery, connection validation, default selection, clear-key.
  • Setup and lock: first-run wizard (identity / provider / optional PIN) and a PIN lock with attempt backoff, idle auto-lock and a menu Lock Now (⌘L).
  • Diagnostics: About card, rotating file log with a renderer→main bridge, transcript export, workspace reveal.
  • New IPC namespaces (files, memory, skills, providers, threads) behind Zod-validated handlers, a shared errors module, an app settings store over sqlite, and per-surface live test scripts.

Appearance: modes and accent colors

  • System / Light / Dark is unchanged. On top of it, Neutral / Blue / Violet / Emerald / Amber / Rose repaint --primary, --primary-foreground and --ring, so buttons, the selected sidebar row, the logo tile and focus rings take the hue in both modes.
  • Both axes are painted from one path (theme.ts) onto <html> as dark + data-accent, and are re-applied by the prefers-color-scheme listener so a live OS switch keeps the chosen accent.
  • Persisted as settings.theme + settings.accent; an unrecognised stored accent reads back as neutral (same fallback shape as an unknown theme reading as system). The settings schema rejects unknown accents at the IPC edge.
  • Palette is contrast-checked: every accent holds ≥4.9:1 between its fill and its foreground text in both modes, and that same ratio against its own mode's background for accent text (variant="link").

Test plan

Check Result
npm run typecheck clean (node + web projects)
npm run test:unit 12 files / 142 tests pass, incl. new theme.test.ts (mode resolution, accent painting, OS-flip repaint keeping the accent) and accent coverage in schemas.test.ts
npm run settings:test green on an isolated HOME: accent round-trips through the sqlite row, survives an unrelated save, and a row hand-edited to nonsense falls back to neutral/system
npm run build green; the built renderer bundle was driven in headless Chromium with a stubbed bridge — all 12 mode × accent combinations match their tokens exactly (nav row background == hsl(--primary), foreground == hsl(--primary-foreground)), system follows an emulated prefers-color-scheme flip with no settings write, and saved payloads carry theme + accent together

Notes for review

  • The Chromium drive used an ad-hoc stub for window.hermes; it is not committed. Say the word and I will make it a permanent scripts/renderer-ui-test.ts (stub + static server + the CDP assertions).
  • nativeTheme.themeSource is not wired, so the title bar still follows the OS while the window itself follows the setting. Out of scope here; flagging it since it is the one place mode and OS can visibly disagree.

Lands this worktree's outstanding desktop work together with the new
appearance controls, in one commit because the two bodies of work overlap
in the same files (index.css, App.tsx, wire.ts, schemas.test.ts, README).

Surfaces: Files/Workspace page (tree, read, edit, save, new file, reveal,
attachment staging), Memory browser (search, Markdown edit, rename,
delete), Skills browser (create/rename/delete), thread
search/rename/delete, provider CRUD with model discovery and validation,
first-run setup wizard, PIN lock with idle auto-lock, application menu with
Lock Now, About/diagnostics card, transcript export, and the renderer->main
log bridge. New IPC namespaces (files, memory, skills, providers, threads)
behind Zod-validated handlers, plus a shared errors module, an app settings
store over sqlite, and per-surface live test scripts.

Appearance: System / Light / Dark stays, and Neutral / Blue / Violet /
Emerald / Amber / Rose accents repaint `--primary`, `--primary-foreground`
and `--ring`, so buttons, the selected sidebar row, the logo tile and focus
rings take the hue in both modes. Mode and accent are applied to <html> as
`dark` + `data-accent` from one paint path that the OS-scheme listener
re-runs, and are persisted as `settings.theme` + `settings.accent`; an
unrecognised stored accent reads back as neutral. Every accent holds at
least 4.9:1 contrast between its fill and its foreground text in both
modes, and that same ratio against its own mode's background for accent
text.

Verification:
- `npm run typecheck` clean.
- `npm run test:unit`: 12 files / 142 tests, including the new
  `theme.test.ts` (mode resolution, accent painting, OS-flip repaint
  keeping the accent) and accent coverage in `schemas.test.ts`.
- `npm run settings:test` green on an isolated HOME: accent round-trips
  through the sqlite row, survives an unrelated save, and a row edited to
  nonsense falls back to neutral/system.
- `npm run build` green; the built renderer bundle was driven in headless
  Chromium with a stubbed bridge — all 12 mode x accent combinations match
  their tokens exactly (nav row background == hsl(--primary), foreground ==
  hsl(--primary-foreground)), and system mode follows a live
  prefers-color-scheme flip without a settings write.
@kartikmanimuthu
kartikmanimuthu merged commit 3a78dcc into main Sep 21, 2026
1 check 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