Files
kandev/docs/plans/terminal-theme-rendering/plan.md
T
2026-08-26 09:04:23 +00:00

104 lines
5.2 KiB
Markdown

---
created: 2026-08-25
status: complete
requirements:
- REQ-UI-TERMINAL-RENDERING-001
system_design:
- ../../specs/ui/system-design/terminal-rendering.md
legacy_specs: []
---
# Implementation Plan: Terminal Theme Rendering
## Overview
The current renderer combines a light background with a dark-only ANSI palette. It also captures theme values only when xterm starts. This plan adds red regression evidence first, then implements one shared adaptive theme contract for all xterm constructors.
## Scope
### In scope
- Add separate light and dark ANSI palettes.
- Enforce a 4.5:1 minimum contrast ratio through xterm.
- Update open adaptive terminals when the resolved theme changes.
- Keep fixed-dark terminals on the shared dark palette.
- Cover desktop and phone task terminals with Playwright, and document the
shared rendering path used by tablet task terminals.
### Out of scope
- Change terminal transport, PTY lifecycle, output buffering, or shell configuration.
- Add user-defined palettes or new appearance settings.
- Change terminal layout, mobile composition, keyboard controls, or scrolling.
- Change the visual design of Quick Terminal or agent-login dialogs.
## Technical approach
### Shared palette
Update `apps/web/lib/theme/terminal-theme.ts` to select an ANSI palette from an explicit `ResolvedTheme`. Export one minimum contrast value for every xterm constructor.
Use the shared fixed-dark result in `PtyTerminalView`. Remove its isolated background-only xterm theme.
### Reactive application
Add `apps/web/components/task/use-terminal-theme.ts`. The hook receives the xterm reference, host reference, readiness state, and resolved theme.
The hook updates `terminal.options.theme` after the root theme class commits. It cancels pending work during cleanup and never reconstructs the terminal.
`AppThemeProvider` applies the initial root theme class in a layout effect, so
descendant terminal construction effects read CSS variables for the resolved
theme on the first render.
Pass `resolvedTheme` through `ShellTerminal` and `PassthroughTerminal`. Keep their current connection, resize, input, search, and mobile behavior.
### Browser evidence
Extend the existing xterm test bridge with a read-only theme snapshot. Clear the snapshot function with the other bridge functions during cleanup.
Add desktop and mobile terminal theme specs. The desktop flow changes theme while the terminal stays mounted. The mobile flow uses the existing Pixel 5 terminal surface in light mode.
## Tests
| Acceptance criterion | Evidence |
| --- | --- |
| `AC-UI-TERMINAL-RENDERING-001.1` | `terminal-theme.test.ts` selects the initial light and dark palettes. |
| `AC-UI-TERMINAL-RENDERING-001.2` | `terminal-theme.test.ts` checks the shared contrast setting. Desktop and mobile specs inspect the live xterm value. |
| `AC-UI-TERMINAL-RENDERING-001.3` | `terminal-theme.spec.ts` changes the application theme and observes the live xterm theme. |
| `AC-UI-TERMINAL-RENDERING-001.4` | `terminal-theme.spec.ts` keeps buffer content, focus, scroll position, and a running command while accepting new shell output after the theme change. |
| `AC-UI-TERMINAL-RENDERING-001.5` | Desktop and `mobile-terminal-theme.spec.ts` check the same light-theme contract. |
| `AC-UI-TERMINAL-RENDERING-001.6` | `terminal-theme.test.ts` checks the shared fixed-dark theme. |
The first work order must fail against the current implementation. The expected unit failure is `uses a readable ANSI palette in light mode`. The expected desktop failure is `updates an open terminal when the application theme changes`.
## E2E tests
- `apps/web/e2e/tests/terminal/terminal-theme.spec.ts` uses the `chromium` project for `AC-UI-TERMINAL-RENDERING-001.1` through `.4`.
- `apps/web/e2e/tests/terminal/mobile-terminal-theme.spec.ts` uses the `mobile-chrome` Pixel 5 project for `AC-UI-TERMINAL-RENDERING-001.2` and `.5`.
- Tablet task terminals use the same `PassthroughTerminal` and
`useTerminalTheme` path as the desktop and phone surfaces. The shared-path
evidence covers tablet rendering without adding a separate viewport test.
## Work orders
- [x] [Task 01: Add terminal theme regressions](task-01-add-terminal-theme-regressions.md)
- [x] [Task 02: Implement adaptive terminal themes](task-02-implement-adaptive-terminal-themes.md)
## Verification results
Passed on 2026-08-25:
- `cd apps/web && pnpm test -- lib/theme/terminal-theme.test.ts`
- `cd apps/web && pnpm test -- components/task/use-terminal-theme.test.ts components/theme/app-theme.test.tsx`
- `cd apps/web && pnpm run typecheck`
- Targeted ESLint for all changed terminal, theme, bridge, and E2E files with zero warnings.
- `cd apps/web && pnpm e2e:run tests/terminal/terminal-theme.spec.ts`
- `cd apps/web && pnpm e2e:run --project mobile-chrome tests/terminal/mobile-terminal-theme.spec.ts`
## Risks
- A theme effect can read old CSS variables before the root theme class changes. The browser test must change theme through Kandev UI.
- Reconstructing xterm can clear the buffer or reconnect the shell. The implementation must mutate `terminal.options.theme` only.
- WebGL and canvas renderers use the same xterm theme contract. The mobile path keeps WebGL disabled for its existing scaling rule.
- The test bridge must remain read-only and must remove every added function during cleanup.