Skip to content

Commit 35cbf4f

Browse files
upsetbitclaude
andcommitted
docs(panel): document the theme system and preferences
Update screens.md (theme picker, /settings/theme), components.md (token coverage, --on-accent, agent hues on light backgrounds), and architecture/panel.md (PreferencesService, server-rendered data-theme). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 53c1670 commit 35cbf4f

3 files changed

Lines changed: 55 additions & 18 deletions

File tree

docs/architecture/panel.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -277,9 +277,16 @@ POST forms (`/logout`, `/cli/authorize/approve`, and device actions).
277277
## Talking to the server
278278

279279
`internal/panel/rpc/client.go` builds Connect clients for
280-
`SessionsService`, `DevicesService`, `AuthService`, `AnalyticsService`.
281-
Each call sends `Authorization: Admin <PROSA_ADMIN_TOKEN>` so the server
282-
treats the panel as the owner.
280+
`SessionsService`, `DevicesService`, `AuthService`, `AnalyticsService`,
281+
`PreferencesService`. Each call sends `Authorization: Admin
282+
<PROSA_ADMIN_TOKEN>` so the server treats the panel as the owner.
283+
284+
`PreferencesService` stores panel UI preferences (currently the chosen
285+
theme) in the `panel_preferences` Postgres table, keyed by owner email.
286+
The panel resolves the owner's theme on every full-page render — cached
287+
in-process, invalidated on write — and stamps it onto `<html data-theme>`
288+
server-side, so the first paint is correct with no flash. The Settings
289+
picker POSTs to `/settings/theme`, which calls `PreferencesService.Set`.
283290

284291
The `/events` route is a proxy: the panel opens an SSE stream to the
285292
server's `/sse/events` and re-emits the bytes to the browser. This

docs/panel/components.md

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ see [screens.md](screens.md). For visual direction see the
1111
CSS vars defined in `internal/panel/templates/assets/css/tokens.css`. All
1212
other layers reference these vars — never a literal value.
1313

14-
### Dark palette
14+
### Default palette — Colorblind (Okabe–Ito)
1515

1616
```
1717
--bg #0f1117
@@ -20,10 +20,11 @@ other layers reference these vars — never a literal value.
2020
--text-1 #e8eaf0
2121
--text-2 #aab0bf
2222
--text-3 #6b7186
23-
--accent #6b7afc
24-
--accent-soft #6b7afc33
25-
--ok #4ade80
26-
--danger #f04a5c
23+
--accent #56b4e9
24+
--accent-soft #56b4e933
25+
--ok #1fb894
26+
--danger #ef6c1a
27+
--warn #e69f00
2728
--divider #232733
2829
--chart-grid #20242f
2930
```
@@ -32,9 +33,23 @@ other layers reference these vars — never a literal value.
3233
it sits quieter than `--divider`, which separates surfaces (light value:
3334
`#e7ebf1`).
3435

35-
Light mode: `tokens.css` re-defines every palette var under
36-
`[data-theme="light"]`, and under `[data-theme="system"]` when the OS
37-
reports `prefers-color-scheme: light`.
36+
Themes: the colorblind (Okabe–Ito) palette above lives in `:root` as the
37+
default. Each alternate overrides the color tokens under its own
38+
`[data-theme="<id>"]` block — `light`, `nord`, `solarized-dark`,
39+
`solarized-light`, `dracula`, `gruvbox`, `high-contrast` — and `system`
40+
follows the OS via `prefers-color-scheme`. The panel stamps the owner's
41+
saved `data-theme` on `<html>` server-side; `charts-init.js` recolors
42+
charts on the flip.
43+
44+
Every color the panel paints is a token, so no theme leaves anything
45+
unthemed: surfaces, text, `--accent` plus `--on-accent` (the text/icon
46+
color that rides on the accent — dark on a light accent, light on a dark
47+
one), status (`--ok`/`--danger`/`--warn`), `--divider`, the `--chart-*`
48+
palette, and the `--agent-*` identity hues. Agent hues keep their
49+
identity across themes; on light backgrounds (`light`, `solarized-light`,
50+
`system` under OS-light) they darken for contrast. The only literals left
51+
in CSS are drop shadows and the modal scrim — neutral black on purpose,
52+
correct against any palette.
3853

3954
### Typography
4055

docs/panel/screens.md

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -561,24 +561,39 @@ Devices
561561

562562
## Settings `/settings`
563563

564-
Single-card surface for the logged-in owner. Spartan by design.
564+
Two cards for the logged-in owner: identity and appearance.
565565

566566
```
567567
Settings
568568
569569
+---------------------------------------------------+
570-
| Signed in as |
570+
| Logged in as |
571571
| hi@caian.org |
572-
| |
573-
| [ logout ] |
572+
| [ log out ] |
573+
+---------------------------------------------------+
574+
+---------------------------------------------------+
575+
| Appearance |
576+
| (o) Colorblind ( ) Light ( ) Nord |
577+
| ( ) Solar. Dark ( ) Solar. Light( ) Dracula |
578+
| ( ) Gruvbox ( ) High Contr. ( ) System |
574579
+---------------------------------------------------+
575580
```
576581

577-
- One card, no tabs, no preferences sub-pages.
578582
- Email comes from the session cookie (`p.cookie.FromRequest(r)`).
579583
- Logout button posts to `/logout` (same as the topbar form).
580-
- No SSE, no Alpine, no charts. If a future setting earns its place,
581-
it joins this card.
584+
- The theme picker is a swatch grid of nine options: the colorblind
585+
(Okabe–Ito) default, seven alternates (`light`, `nord`,
586+
`solarized-dark`, `solarized-light`, `dracula`, `gruvbox`,
587+
`high-contrast`), and `system`. Picking one sets `data-theme` on
588+
`<html>` immediately — recoloring chrome and charts — and POSTs to
589+
`/settings/theme`.
590+
- `/settings/theme` persists the choice server-side via
591+
`PreferencesService.Set`, keyed by owner email. The panel renders
592+
`data-theme` from the stored value on first paint, so the theme
593+
follows the owner across browsers with no flash.
594+
- The catalog is `panel.Themes`: the picker renders from it and the
595+
handler validates the submitted value against it, so the two never
596+
drift.
582597

583598
---
584599

0 commit comments

Comments
 (0)