Skip to content

feat: add pi theme JSON system with theme picker - #384

Open
Kabochar wants to merge 1 commit into
agegr:mainfrom
Kabochar:feat/theme-system-upstream
Open

feat: add pi theme JSON system with theme picker#384
Kabochar wants to merge 1 commit into
agegr:mainfrom
Kabochar:feat/theme-system-upstream

Conversation

@Kabochar

@Kabochar Kabochar commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Add a theme system that loads pi CLI theme JSON files from ~/.pi/agent/themes/ and applies them to the whole UI: a top-bar theme picker lists every installed theme set (e.g. gruvbox, solarized, each with dark/light variants).

Changes

Core

  • lib/theme.ts: parser/resolver for pi CLI theme JSON — vars references, 256-color indices, brightness-based dark/light inference, base-dark.json/base-light.json set pairing, 51-token -> CSS variable mapping
  • lib/prism-theme.ts: syntax highlighting bound to theme CSS variables, so code colors follow the active theme without re-render lag
  • app/api/themes routes: theme set discovery + per-variant resolution
  • hooks/useTheme.ts: themeName state, setTheme, CSS variable application with localStorage persistence and old-value (light/dark) migration
  • app/layout.tsx: bootstrap pre-sets data-theme to avoid flash of unstyled content

UI

  • Top-bar theme picker panel reusing the existing top-panel mechanism

Web adaptation (mapping layer only, theme JSON files untouched)

  • WCAG contrast guarantees: text/muted >= 4.5:1, dim >= 3:1, accent family >= 4.5:1, border >= 3:1 (hue preserved, lightness adjusted only)
  • Sidebar surface color (--bg-sidebar), user bubble differentiation, accent-tinted selected state
  • --composer-focus-bg derived from theme surface
  • Hardcoded blue accents (message bubble border, explorer dot, image border) replaced with theme variables

Tests

  • lib/theme.test.mjs: 9 node:test cases — set aggregation, variant pairing, single-file fallback, contrast guarantees across all four variants

Compatibility

  • Default theme (no selection) is unchanged: globals.css fallbacks cover all new variables
  • Theme JSON format is the pi CLI standard, so existing terminal themes work out of the box

Verification

  • node --test lib/theme.test.mjs (9/9 pass)
  • tsc --noEmit, npm run lint clean
  • Manually verified theme switching, syntax highlighting and focus state across light/dark

- Add lib/theme.ts parser that resolves pi CLI theme JSON (~/.pi/agent/themes/)
  into CSS variables with WCAG contrast guarantees for text, accent and border
- Add /api/themes discovery and /api/themes/[name] resolution routes
- Extend useTheme with themeName state, setTheme and CSS variable application
- Add top-bar theme picker panel listing all available theme sets
- Add prism-theme.ts so syntax highlighting follows theme CSS variables
- Derive --composer-focus-bg from theme surface colors (Kabochar-specific)
- Differentiate sidebar, user bubbles, selected state and borders per theme
- Add node:test suite (9 tests) covering parsing, pairing and contrast levels
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