Skip to content

feat: add dynamic theme changes#3

Merged
loeck merged 5 commits intomainfrom
feat/dynamic-theme-changes
Apr 7, 2026
Merged

feat: add dynamic theme changes#3
loeck merged 5 commits intomainfrom
feat/dynamic-theme-changes

Conversation

@loeck
Copy link
Copy Markdown

@loeck loeck commented Apr 7, 2026

Summary

  • Add ghostty_terminal_set_colors WASM export that updates terminal colors at runtime and forces a full redraw
  • Wire up terminal.options.theme = newTheme to merge partial themes, update the renderer, and sync WASM terminal colors
  • Existing content re-renders instantly — cells with ANSI palette/default colors pick up the new theme; explicit RGB cells remain unchanged
  • Support partial theme updates that accumulate (e.g. setting only background preserves all other colors)

Usage

// Full theme swap
terminal.options.theme = { background: '#000', foreground: '#fff', red: '#ff0000' };

// Partial update — only changes background, keeps everything else
terminal.options.theme = { background: '#1a1a2e' };

// Reset to defaults
terminal.options.theme = {};

Changes

File Change
patches/ghostty-wasm-api.patch New setColors() Zig function, force_full_redraw flag on TerminalWrapper, render state reset on color change
ghostty-vt.wasm Rebuilt with ghostty_terminal_set_colors export
lib/types.ts Added ghostty_terminal_set_colors to WASM exports interface
lib/ghostty.ts Added setColors() method to GhosttyTerminal class
lib/terminal.ts handleOptionChange('theme') now merges, updates renderer + WASM; added currentTheme accumulator and buildThemeColorsConfig() helper
lib/terminal.test.ts 12 new tests covering full/partial/reset/accumulation/ANSI re-resolution/RGB unchanged/redraw trigger

Test plan

  • Full theme change updates renderer and WASM colors
  • Partial theme updates preserve previous customizations
  • Successive partial updates accumulate correctly
  • Reset to null/undefined/{} restores defaults
  • Theme set before open() is applied correctly
  • ANSI palette color cells re-resolve after theme change
  • Explicit RGB color cells remain unchanged
  • Theme change triggers full redraw (needsFullRedraw() returns true)
  • Invalid color values do not crash
  • Default fg/bg cells update after theme change
  • bun run typecheck && bun test pass (343 tests, 0 failures)

Ported from coder/ghostty-web#144

brianegan and others added 5 commits March 26, 2026 16:40
Enable runtime theme changes via `terminal.options.theme = newTheme`
without restarting the terminal. All existing content re-renders
instantly with the new colors.

- Add `ghostty_terminal_set_colors` WASM export that updates terminal
  colors and forces a full redraw
- Wire up `handleOptionChange('theme')` to merge partial themes,
  update the renderer, and sync WASM terminal colors
- Support partial theme updates that accumulate (e.g. setting only
  background preserves all other colors)
- Cells with ANSI palette/default colors re-resolve; explicit RGB
  cells remain unchanged

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add struct layout comment in ghostty.ts to document GhosttyTerminalConfig field offsets and warn about Zig/TS drift
- Expose renderer.theme as a public getter on CanvasRenderer to eliminate @ts-ignore in Dynamic Theme Changes tests
- Remove trailing whitespace in renderStateUpdate section of ghostty-wasm-api.patch
- Extract buildThemePalette() helper in terminal.ts; used by both buildWasmConfig() and buildThemeColorsConfig()
- Extract writeConfigToPtr() helper in ghostty.ts; used by constructor and setColors()
- Remove double initialization of currentTheme (class field default was immediately overwritten in constructor)
- setTheme() now accepts Required<ITheme> and assigns directly, removing redundant spread against DEFAULT_THEME
Update patch index hashes and hunk line numbers to match updated Ghostty submodule from main.
The @@ -0,0 +1,1168 @@ header was off by 5 — actual content is 1163 lines.
Rebuilt ghostty-vt.wasm against updated submodule.
@loeck loeck merged commit 2b2446d into main Apr 7, 2026
5 checks passed
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.

2 participants