Skip to main content
BM

ThemeSwitcher

Light, Dark or one of the visitor's own themes for the whole site: it starts from the visitor's OS setting, and a choice is remembered.

View source on GitHub

ThemeSwitcherExample.tsx
import { ThemeSwitcher } from "@/components/ThemeSwitcher";

export function ThemeSwitcherExample() {
  return <ThemeSwitcher />;
}

Examples

Looks (each changes the whole site, not this panel)

Label (changes the whole site, not this panel)

Announced as: “Theme, menu button, collapsed”

Placement (changes the whole site, not this panel)

Props

Any native prop not listed here goes to the root element unchanged.

ThemeSwitcher props
PropTypeDefaultDescription
variant"primary" | "secondary" | "ghost""ghost"Emphasis: one primary action per view, secondary for the rest, ghost for toolbars.
size"sm" | "md""sm"32px or 40px tall.
showLabelbooleanauto: from 30em upShows the visible "Theme" label; the accessible name always says the theme in effect.
nameTooltipbooleantrueWhile "Theme" isn't displayed, shows the accessible name as a tooltip.
side"bottom" | "top""bottom"The side of the trigger it opens on. It still flips when it doesn't fit.
align"start" | "end""end"The trigger edge it lines up with. It still shifts to stay in the viewport.

Component tokens

None of its own: it's a Menu with a Button trigger, so it uses their tokens.

Accessibility

  • The trigger is named by the theme in effect, e.g. "Theme: Dark" or "Theme: Ocean", with a matching icon: a sun, a moon, or a palette for a custom theme.
  • Custom themes made in the theme creator follow Light and Dark, by name, in the same radio group. After a separator, a link item ("Create a theme…", or "Edit themes…" once one exists) opens the theme creator.
  • Until the visitor chooses, it shows and follows their OS color scheme, live.
  • The choice applies before first paint on every page, and follows other tabs.
  • Without JavaScript it's hidden and the system theme applies.
  • The chevron shows sighted users that the trigger opens a menu. Screen readers announce a menu button with its state, collapsed or expanded.
  • A visible "Theme" label is the start of the accessible name, so voice control can use the word on screen.
  • Hide the label (showLabel={false}) only where the icons make the purpose clear. Its name ("Theme: Dark") then shows as a tooltip on hover and keyboard focus, but voice control users still have to discover the word "Theme" before they can say it.
  • Space applies a theme and closes the menu, as Enter does.
  • The icon and name report the site's theme, even inside a preview panel set to another theme.
  • The “Announced as” caption gives the trigger's accessible name, role and state. Exact wording varies by screen reader.
ThemeSwitcher keyboard
KeyAction
Enter / Space / clickOn the trigger: opens, focusing the checked item or the first.
Down Arrow / Up ArrowOn the trigger: opens on the first or last item. In the menu: next or previous item, wrapping.
Home / EndFirst or last item.
A to ZNext item starting with that letter.
Enter / SpaceIn the menu: applies the theme, closes, and returns focus to the trigger.
EscapeCloses and returns focus to the trigger.
TabCloses and moves focus on as usual.