Skip to content

Conversation

@kylecarbs
Copy link
Member

Implements a light theme for mux with a keyboard shortcut to toggle between light and dark themes.

Implementation

Theme System

  • Uses CSS variables approach with [data-theme="light"] selector for light theme overrides
  • Default theme remains dark (existing users unaffected)
  • Theme preference persists in localStorage (global, not per-workspace)
  • Applied via data-theme attribute on root HTML element

Changes

  • CSS: Add ~180 lines of light theme color overrides in globals.css
  • State Management: Add theme state in App.tsx using usePersistedState
  • Command Palette: Add "Toggle Theme" command with Cmd+Option+T (macOS) / Ctrl+Alt+T (Windows/Linux) keybind
  • Shiki: Update syntax highlighting to use min-light theme for light mode, min-dark for dark mode
  • Mermaid: Re-initialize diagrams with current theme on render (uses default theme for light, dark theme for dark mode)

Color Strategy

Light theme inverts the semantic meaning while maintaining contrast ratios:

  • Background: near-white (hsl(0 0% 98%))
  • Foreground: dark gray (hsl(0 0% 15%))
  • Mode colors maintain hue, adjusted lightness for readability on light backgrounds
  • Code blocks use light gray backgrounds instead of near-black

Testing

  • ✅ Typecheck passes
  • ✅ Lint passes
  • Manual verification needed for:
    • Theme toggle via keyboard shortcut
    • Theme persistence across reloads
    • All major views in both themes (chat, code blocks, diffs, mermaid, modals)

Net LoC

+230 lines (180 for light theme CSS, 50 for state management and dynamic theme application)

Generated with mux

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

void highlight();
return () => {
cancelled = true;
};
}, [code, language]);

P1 Badge Re-run code block highlighting when theme changes

The CodeBlock effect renders Shiki HTML once and only depends on [code, language]. When App toggles the data-theme attribute, existing code blocks keep the colors from the previous theme because the effect never re‑executes to call getShikiTheme() again. Users who switch to light mode (or reload with light mode persisted) will still see dark-theme code blocks until the message is re-rendered, which defeats the new theme toggle for a common UI element.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Implement a light theme for mux with keyboard shortcut to toggle between light and dark themes.

Changes:
- Add light theme CSS variables in globals.css using [data-theme='light'] selector
- Add theme state management in App.tsx using usePersistedState (global, not per-workspace)
- Add 'Toggle Theme' command in command palette with Cmd+Option+T / Ctrl+Alt+T keybind
- Update Shiki syntax highlighting to dynamically use theme-appropriate colors (min-light vs min-dark)
- Update Mermaid diagrams to re-initialize with current theme on render
- Add THEME_KEY constant to storage.ts for theme persistence
- Default theme remains dark for existing users

The theme preference persists across reloads via localStorage and applies to all code blocks, diffs, and mermaid diagrams.

_Generated with `mux`_
- Remove Cmd+Option+T / Ctrl+Alt+T keybind for theme toggle
- Keep theme toggle as command palette action only
- Add Storybook global theme switcher in toolbar
- All stories now support both light and dark theme preview
- Theme switcher appears as sun/moon icons in Storybook toolbar
@kylecarbs kylecarbs force-pushed the light-theme-implementation branch from 731d241 to 0a0d979 Compare November 16, 2025 14:49
Tailwind CSS v4's @theme directive doesn't support nested selectors.
Use standard CSS selector [data-theme='light'] { } instead.
The original @theme block was missing its closing brace before the light theme block was added, causing the light theme to be nested inside @theme.
- Apply theme to both document.documentElement and document.body
- Wrap Story in div with data-theme attribute and background/foreground colors
- Ensures theme persists and doesn't flash back to dark
- Create ThemeContext with useTheme hook for cleaner theme access
- Remove duplicate theme logic from App.tsx
- Simplify Storybook decorator to just apply data-theme attribute
- Components can now use useTheme() instead of reading document.documentElement
- Centralize all theme logic in one place
@kylecarbs kylecarbs closed this Nov 16, 2025
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