TrademarkTrademarkDocs
Ctrl k
Search docs...
Components

ThemeSwitcher

Updated: September 15, 2026
View on GitHub
Use ThemeSwitcher to provide users with a quick way to toggle between themes. It integrates with ThemeProvider and uses useTheme() under the hood.
  • Highlights the active theme using the "primary" variant, and exposes it to assistive technology with aria-pressed.
  • Automatically updates the global theme via useTheme().setTheme.
  • Renders a row of three icons: system, dark, light.
collapsed shows only the active theme and reveals the rest on hover or focus. Use it where the control has to be reachable from every page but should not spend three slots of a header on itself. It stays a real toggle group. Every option keeps its tab stop, so tabbing into the group opens it; and a device that cannot hover gets all three from the start, because otherwise the only way in would be to tap the visible button — which would have already changed the theme. The width transition is the only motion, and prefers-reduced-motion turns it off. A collapsed group grows sideways by default, which is right when it has room beside it and wrong when it has neighbours: the group widening pushes them along, and the option the pointer was resting on slides out from under it. direction="column" lifts the options into a panel over the page instead. The control keeps a one-option footprint whatever it is doing, so nothing around it moves, and a sticky header does not change height when the panel opens. It opens downwards rather than centring itself on the active option. An open panel is taller than a typical header, so anchoring it on the second or third option would put its top edge above the viewport. The active option leads. Open in fixed order and the panel's first slot belongs to whichever theme is listed first, so the icon already under the pointer changes identity as the panel unrolls — hover the moon, and the computer arrives under your cursor. Leading with the active option keeps one invariant instead: the theme in force is the one in the anchor slot, before opening and again after choosing. The reorder is done in the markup, not with CSS order, so the tab order and the visual order stay the same thing. On a device that cannot hover the panel is always open, and it takes its space in the layout rather than hanging over what is underneath. Pass any valid Row props to control spacing, padding, layout, etc.
Prop
Type
Default
collapsed
boolean—
direction
row | column—
ref
HTMLDivElement—
className
string—
style
React.CSSProperties—
…and every FlexProps propinherited—
Edit this page on GitHub
TrademarkTrademark
Built with curiosity by Lorant One and the Design Engineers Club