feat(web): add modular theme library - #5226
Merged
juliusmarminge merged 118 commits intoAug 7, 2026
Merged
Conversation
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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()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.Closes #418
Closes #233
Closes #4302
Supersedes #5258
Screenshots
Both shots show the same mix — T3 Chat in light, Grove in dark — from either side of the System toggle.
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.
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 frommod+alt+shift+tand a new command-palette action. Desktop gainspickThemeFilesIPC (multi JSON picker, defaulting to~/.vscode/extensions, 256 KB read cap) wired through preload.index.htmlboot 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-foregroundopacity classes to semantic tokens (secondary-label,icon-muted,placeholder,message/message-action,error/warning/update,--code-backgroundfor 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 ofmessage-actioncolors.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
themePalette.tsas 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.ThemeEditorPanel.tsx,ThemeEditorHost.tsx) supporting live preview, managed/advanced color editing, and save/update/remove of custom themes; toggled viamod+alt+shift+t.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 viavscodeThemeImport.ts.ThemeLibraryUI for browsing, activating, mixing light/dark halves, editing, duplicating, exporting, and deleting themes.useThemeto exposeappearanceMode,followSystem, andthemeHalves, and updates boot-time theming inindex.htmlto resolve custom/built-in themes and mixed halves before app mount.pickThemeFilesIPC channel on desktop that opens a multi-file JSON picker defaulting to the VS Code extensions directory.muted-foregroundtokens to semantic tokens (secondary-label,icon-muted,placeholder,message-action,error,warning,update).index.htmlis substantially more complex and reads multiple localStorage keys; failures fall back gracefully but the script is harder to audit.Macroscope summarized 71db00e.