Skip to content

feat(web): add modular theme library - #5226

Merged
juliusmarminge merged 118 commits into
pingdotgg:mainfrom
StiensWout:t3code/modular-theme-system
Aug 7, 2026
Merged

feat(web): add modular theme library#5226
juliusmarminge merged 118 commits into
pingdotgg:mainfrom
StiensWout:t3code/modular-theme-system

Conversation

@StiensWout

@StiensWout StiensWout commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a token-based theme system to the web client and desktop app: 57 semantic color roles, applied before React mounts so there is no flash of the wrong theme.

  • Color scheme first — the Appearance section leads with three wide tiles (System, Light, Dark), each a miniature of the app painted in the currently picked palettes; the System tile splits to show both halves.
  • Mix light and dark from different themes — every theme card shows its light and dark balls; clicking one assigns that theme to that half of the mix (marked with a ring and a sun/moon badge), and System flips between the two picks with the OS. Picks persist, apply live, and resolve in the boot splash — parity between the inline boot script and the runtime is CI-enforced by tests that derive from the real palette definitions.
  • Six built-in themes — T3 Code (default), T3 Chat (anchored to the official t3.chat palette), Grove, Ocean, Ember, and Iris. Each maintainer theme pairs its accent with a companion action color that drives every solid control, while the accent handles surfaces, selection, and focus.
  • Personal themes — guided creation from two colors (an OKLCH generator derives a readable palette from the exact seeds), an advanced editor for every role, and JSON import/export. The editor opens as a draggable panel above the router that applies its draft to the running app, and starts from the theme you already use.
  • VS Code themes convert on import — the drop box takes T3 Code and VS Code theme files (several at once), maps the workbench colors it finds onto a contrast-solved palette, flattens alpha overlays and wide-gamut color() values, and pairs a family's light and dark files into one dual-mode theme. Re-importing an installed theme asks whether to update it or keep both.
  • Full-surface coverage — sidebar, composer, chat timeline (including code blocks in replies), diffs and their gutters, terminals, file previews, the typography previews from feat(web): configurable fonts and sizes under Settings → Appearance #5103, toolbars, status colors, and the browser chrome color.

Closes #418
Closes #233
Closes #4302

Supersedes #5258

Screenshots

Light half active Dark half active
Appearance with the scheme picker, T3 Chat picked for light Appearance with the scheme picker, Grove picked for dark

Both shots show the same mix — T3 Chat in light, Grove in dark — from either side of the System toggle.

Theme editor Importing themes
The floating theme editor in advanced mode, filtering color roles The import dialog: a drop row above the JSON editor

The editor floats above the app and paints its draft on the live interface, so a color is judged by browsing the app rather than a miniature; it drags anywhere and survives navigation. Advanced mode lists one role per row behind a filter.

Themed typography previews
Typography previews following the active theme

Built with GPT-5.6-Luna and Claude Fable 5 in T3 Code.


Note

Medium Risk
Large UI and boot-time localStorage theming surface with many touchpoints; failures generally degrade to fallbacks rather than affecting auth or data, but bad stored theme shapes or boot/runtime drift could cause flash or inconsistent colors on load.

Overview
Introduces a modular theme system that replaces the simple system/light/dark dropdown with a ThemeLibrary in appearance settings: built-in palettes, per-appearance theme halves (mix light and dark from different themes), custom themes in storage, and restore-defaults logic that resets theme preference, follow-system mode, and mix independently.

A floating theme editor (ThemeEditorHost / ThemeEditorPanel, ThemeColorPicker) applies drafts on the live app; it opens from mod+alt+shift+t and a new command-palette action. Desktop gains pickThemeFiles IPC (multi JSON picker, defaulting to ~/.vscode/extensions, 256 KB read cap) wired through preload.

index.html boot script is expanded to mirror runtime theme resolution—custom themes, legacy IDs, halves, and splash CSS variables—so the first paint matches the selected palette before React mounts.

Across the web UI, styling shifts from ad-hoc muted-foreground opacity classes to semantic tokens (secondary-label, icon-muted, placeholder, message / message-action, error / warning / update, --code-background for diffs). Diffs, terminals, font previews, and composer primary actions are updated to follow those tokens; stage artwork is removed from the send button in favor of message-action colors.

Smaller fixes bundled in the same pass: workspace titlebar control inset so toggling the right panel does not jump controls, and sidebar header z-index so stage backdrop does not bleed over search outlines.

Reviewed by Cursor Bugbot for commit 71db00e. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add modular theme library with editor, import, and per-appearance theme halves support

  • Introduces themePalette.ts as the core theme module, defining built-in themes (T3 Chat, Grove, Ocean, Ember, Iris), storage keys, color role types, and custom theme CRUD with subscriptions.
  • Adds a full theme editor (ThemeEditorPanel.tsx, ThemeEditorHost.tsx) supporting live preview, managed/advanced color editing, and save/update/remove of custom themes; toggled via mod+alt+shift+t.
  • Adds a theme import dialog (ThemeImportDialog.tsx) with drag-and-drop, syntax-highlighted JSON editor, 256 KB file size guard, and collision resolution; also supports importing VS Code color themes via vscodeThemeImport.ts.
  • Replaces the appearance settings dropdown with a full ThemeLibrary UI for browsing, activating, mixing light/dark halves, editing, duplicating, exporting, and deleting themes.
  • Expands useTheme to expose appearanceMode, followSystem, and themeHalves, and updates boot-time theming in index.html to resolve custom/built-in themes and mixed halves before app mount.
  • Adds a pickThemeFiles IPC channel on desktop that opens a multi-file JSON picker defaulting to the VS Code extensions directory.
  • Migrates numerous UI components from opacity-based muted-foreground tokens to semantic tokens (secondary-label, icon-muted, placeholder, message-action, error, warning, update).
  • Risk: Boot-time theme resolution script in index.html is substantially more complex and reads multiple localStorage keys; failures fall back gracefully but the script is harder to audit.

Macroscope summarized 71db00e.

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Improve theme comfort and cohesion (light and dark) Themes and UI cusomization Unmatched Contrast Levels

4 participants