Skip to content

[feature] Add useTheme hook with runtime theme switching support #3751

Description

@pixeltannu

What problem does this solve?

TermUI supports theming, but it's not clear there's a way to switch themes
at runtime — e.g. a user pressing a keybinding to toggle between light/dark
mode, or an app cycling through multiple theme presets while running. Most
CLI tools that support theming also let users change it live without
restarting, and this is currently either missing or undocumented in TermUI.

Proposed solution

Add a useTheme hook to @termuijs/jsx paired with a ThemeProvider
context, so components can read and update the active theme reactively.

import { useTheme, useKeymap, Box, Text } from '@termuijs/jsx'

function App() {
  const { theme, setTheme, availableThemes } = useTheme()

  useKeymap([
    {
      key: 't',
      ctrl: true,
      action: () => {
        const idx = availableThemes.indexOf(theme.name)
        const next = availableThemes[(idx + 1) % availableThemes.length]
        setTheme(next)
      },
    },
  ])

  return (
    <Box background={theme.colors.background} padding={1}>
      <Text color={theme.colors.text}>Current theme: {theme.name}</Text>
      <Text dim>Press ctrl+t to cycle themes</Text>
    </Box>
  )
}
  • useTheme() returns { theme, setTheme, availableThemes }
  • Changing the theme should trigger a re-render of all subscribed widgets
    automatically (similar to how @termuijs/store handles selector-based
    subscriptions)
  • Should support both built-in presets and custom user-defined themes
    registered at app startup

Alternatives considered

  • Theme fixed at app init only (possible current state) — simplest, but
    forces a restart for any visual change, which is poor UX for long-running
    TUI apps (dashboards, monitors, etc.)
  • Storing theme in @termuijs/store directly instead of a dedicated hook —
    works, but a purpose-built useTheme hook gives a cleaner, more
    discoverable API consistent with other TermUI hooks

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    staleNo activity in 14 days.type:feature+10 pts. New feature.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions