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.
On this page
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.
| Prop | Type | Default | Description |
|---|---|---|---|
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. |
showLabel | boolean | auto: from 30em up | Shows the visible "Theme" label; the accessible name always says the theme in effect. |
nameTooltip | boolean | true | While "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.
| Key | Action |
|---|---|
| Enter / Space / click | On the trigger: opens, focusing the checked item or the first. |
| Down Arrow / Up Arrow | On the trigger: opens on the first or last item. In the menu: next or previous item, wrapping. |
| Home / End | First or last item. |
| A to Z | Next item starting with that letter. |
| Enter / Space | In the menu: applies the theme, closes, and returns focus to the trigger. |
| Escape | Closes and returns focus to the trigger. |
| Tab | Closes and moves focus on as usual. |