Skip to content

Commit 9f25b56

Browse files
committed
Centralize the theme picker.
1 parent 0dc5a58 commit 9f25b56

8 files changed

Lines changed: 178 additions & 561 deletions

File tree

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ The primary job of a spec is to be an accurate reference for the current state o
3333
- **`docs/specs/layout.md`** — Tiling layout, pane/door containers, dockview configuration, modes (passthrough/command), keyboard shortcuts, selection overlay, spatial navigation, detach/reattach, inline rename, session lifecycle, session persistence, and theming. Read this when touching: `Pond.tsx`, `Baseboard.tsx`, `Door.tsx`, `TerminalPane.tsx`, `spatial-nav.ts`, `layout-snapshot.ts`, `terminal-registry.ts`, `session-save.ts`, `session-restore.ts`, `reconnect.ts`, `index.css`, `theme.css`, or any keyboard/navigation/mode behavior.
3434
- **`docs/specs/alarm.md`** — Activity monitoring state machine, alarm trigger/clearing rules, attention model, TODO lifecycle (soft/hard), bell button visual states and interaction, door alarm indicators, and hardening (a11y, motion, i18n, overflow). Read this when touching: `activity-monitor.ts`, `alarm-manager.ts`, the alarm bell or TODO pill in `Pond.tsx` (TerminalPaneHeader), alarm indicators in `Door.tsx`, or the `a`/`t` keyboard shortcuts. Layout.md defers to this spec for all alarm/TODO behavior.
3535
- **`docs/specs/vscode.md`** — VS Code extension architecture: hosting modes (WebviewView + WebviewPanel), PTY lifecycle and buffering, message protocol between webview and extension host, session persistence flow, reconnection protocol, theme integration, CSP, build pipeline, and invariants (save-before-kill ordering, PTY ownership, alarm state merging). Read this when touching: `extension.ts`, `webview-view-provider.ts`, `message-router.ts`, `message-types.ts`, `pty-manager.ts`, `pty-host.js`, `session-state.ts`, `webview-html.ts`, `vscode-adapter.ts`, or `pty-core.js`.
36-
- **`docs/specs/tutorial.md`** — Playground tutorial on the website: 3-pane initial layout, `tut` command and TutorialShell, 6-step progressive tutorial with detection logic, theme picker, FakePtyAdapter extensions, and Pond event hooks. Read this when touching: `website/src/pages/Playground.tsx`, `website/src/lib/tutorial-shell.ts`, `website/src/lib/tutorial-detection.ts`, `website/src/components/ThemePicker.tsx`, `website/src/lib/playground-themes.ts`, `lib/src/lib/platform/fake-scenarios.ts` (tutorial scenarios), or the `onApiReady`/`onEvent`/`initialPaneIds` props on Pond.
36+
- **`docs/specs/tutorial.md`** — Playground tutorial on the website: 3-pane initial layout, `tut` command and TutorialShell, 6-step progressive tutorial with detection logic, theme picker, FakePtyAdapter extensions, and Pond event hooks. Read this when touching: `website/src/pages/Playground.tsx`, `website/src/lib/tutorial-shell.ts`, `website/src/lib/tutorial-detection.ts`, `lib/src/components/ThemePicker.tsx`, `website/src/lib/playground-themes.ts`, `lib/src/lib/platform/fake-scenarios.ts` (tutorial scenarios), or the `onApiReady`/`onEvent`/`initialPaneIds` props on Pond.
3737

3838
When updating code covered by a spec, update the spec to match. When the two specs overlap (e.g. pane header elements appear in both), layout.md documents placement and sizing while alarm.md documents behavior and visual states.
3939

docs/specs/theme.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -136,22 +136,23 @@ The store module provides:
136136
- `getActiveThemeId()` / `setActiveThemeId(id)` — persists choice across sessions
137137
- `addInstalledTheme(theme)` / `removeInstalledTheme(id)` — manages user-installed themes
138138

139-
## Website playground picker
139+
## Shared theme picker
140140

141-
The website renders the theme picker only on `/playground`. `Playground.tsx` passes it through `SiteHeader`'s playground-only `controls` slot and enables `themeAware`, so the same active `--vscode-*` variables style the header background, border, text, banner, Pond, Dockview, and terminals.
141+
`lib/src/components/ThemePicker.tsx` exports a shared `ThemePicker` with two variants:
142142

143-
The picker is labeled `Theme:` and uses a custom dropdown rather than a native `<select>` because installed themes need an inline delete action. The dropdown lists bundled themes first, then installed themes. Installed theme rows show an `X`; deletion requires browser confirmation and removes that single theme from `mouseterm:installed-themes`. If the active installed theme is deleted, the picker applies the first remaining theme immediately and persists it as `mouseterm:active-theme`.
143+
- `playground-header` — used only on `/playground`, passed through `SiteHeader`'s `controls` slot. It renders a visible `Theme:` label and uses a mobile fixed dropdown so the menu stays inside the viewport.
144+
- `standalone-appbar` — used only by the Tauri standalone `AppBar`. It uses a compact trigger for the 30px AppBar and an anchored dropdown.
144145

145-
The dropdown footer is always `Install theme from OpenVSX`; it opens the runtime installer dialog. The picker is not mounted on non-playground routes.
146+
Both variants use the same state and behavior: restore the persisted active theme on mount, list bundled themes first, append installed themes, persist selected themes to `mouseterm:active-theme`, apply selections immediately, show an `X` for installed themes, confirm before deletion, and fall back to the first remaining theme when deleting the active installed theme. The dropdown footer is always `Install theme from OpenVSX`; it opens the shared runtime installer dialog.
147+
148+
The picker is mounted only by the website playground page and the standalone AppBar. It is not mounted on non-playground website routes, and it is not mounted from `mouseterm-lib/App`, `Pond`, or any VS Code extension entry point.
146149

147150
## Standalone AppBar picker
148151

149-
The standalone Tauri app renders its theme picker in `AppBar`, not in `mouseterm-lib/App` or `Pond`, so the VS Code extension entry point does not mount it. On macOS it sits in the right-side AppBar action group next to the shell dropdown; on Windows/Linux it sits before the native window controls. The AppBar already uses `bg-surface-alt`, `text-foreground`, and related theme tokens, so changing the active theme updates the AppBar chrome as well as Dockview and terminals.
152+
The standalone Tauri app renders the shared theme picker in `AppBar`, not in `mouseterm-lib/App` or `Pond`, so the VS Code extension entry point does not mount it. On macOS it sits in the right-side AppBar action group next to the shell dropdown; on Windows/Linux it sits before the native window controls. The AppBar already uses `bg-surface-alt`, `text-foreground`, and related theme tokens, so changing the active theme updates the AppBar chrome as well as Dockview and terminals.
150153

151154
`standalone/src/main.tsx` restores the persisted active theme before reconnecting/restoring Pond. This prevents the first terminal render from briefly using fallback colors. The picker itself also restores and refreshes theme state on mount.
152155

153-
The standalone picker has the same core behavior as the playground picker: it lists bundled and installed themes, persists selection to `mouseterm:active-theme`, applies the theme immediately, shows an `X` for installed themes, confirms deletion, falls back to the first remaining theme if the active installed theme is deleted, and exposes `Install theme from OpenVSX` as the dropdown footer action.
154-
155156
## Runtime OpenVSX installer
156157

157158
Users can browse and install themes from OpenVSX directly in the app.
@@ -202,9 +203,8 @@ user searches OpenVSX
202203
| [`scripts/bundle-themes.mjs`](../../scripts/bundle-themes.mjs) | Build-time script to download and convert themes from OpenVSX |
203204
| [`lib/src/theme.css`](../../lib/src/theme.css) | `@theme` tokens with `var(--vscode-*, fallback)` + light mode overrides |
204205
| [`lib/src/lib/terminal-registry.ts`](../../lib/src/lib/terminal-registry.ts) | MutationObserver + `getTerminalTheme()` — no changes needed |
205-
| [`website/src/components/ThemePicker.tsx`](../../website/src/components/ThemePicker.tsx) | Playground-only header dropdown for selecting, installing, and deleting themes |
206+
| [`lib/src/components/ThemePicker.tsx`](../../lib/src/components/ThemePicker.tsx) | Shared website/standalone dropdown and OpenVSX dialog for selecting, installing, and deleting themes |
206207
| [`website/src/components/SiteHeader.tsx`](../../website/src/components/SiteHeader.tsx) | Shared site header; playground enables `themeAware` so header chrome follows the active theme |
207-
| [`standalone/src/StandaloneThemePicker.tsx`](../../standalone/src/StandaloneThemePicker.tsx) | Standalone-only AppBar dropdown and OpenVSX dialog |
208208
| [`standalone/src/AppBar.tsx`](../../standalone/src/AppBar.tsx) | Mounts the standalone theme picker in the Tauri AppBar, outside the VS Code extension path |
209209
| [`standalone/src/main.tsx`](../../standalone/src/main.tsx) | Restores the persisted standalone theme before Pond reconnects |
210210

docs/specs/tutorial.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ At the `/playground` route on the website. **Status: Implemented** (Epics 14, 15
1212

1313
- `website/src/pages/Playground.tsx` — Page component. Dynamically imports Pond (SSR-safe). Initializes `FakePtyAdapter`, `TutorialShell`, and `TutorialDetector`. Passes `onApiReady` to set up the 3-pane layout and `onEvent` for step detection.
1414
- `website/src/components/SiteHeader.tsx` — Shared header. Accepts an optional playground-only `controls` slot and a `themeAware` mode that reads the active VSCode theme variables.
15-
- `website/src/components/ThemePicker.tsx`Header dropdown for bundled and installed themes. The footer action opens the OpenVSX installer.
15+
- `mouseterm-lib/components/ThemePicker`Shared header dropdown for bundled and installed themes. The playground passes `variant="playground-header"` and the footer action opens the OpenVSX installer.
1616
- `website/vite.config.ts` — Vite alias `mouseterm-lib``../lib/src` for workspace imports.
1717

1818
## Initial State
@@ -125,7 +125,7 @@ The sandbox stays fully functional after completion. Running `tut` shows "Tutori
125125

126126
## Theme Picker
127127

128-
Implemented in `mouseterm-lib/lib/themes` and `website/src/components/ThemePicker.tsx`.
128+
Implemented in `mouseterm-lib/lib/themes` and `mouseterm-lib/components/ThemePicker`.
129129

130130
Bundled themes are provided by `mouseterm-lib/lib/themes` and include Dark+, Light+, GitHub variants, and Dracula variants. Users can install additional themes from OpenVSX through the dropdown footer action.
131131

0 commit comments

Comments
 (0)