shadcn.io is not affiliated with official shadcn/ui
Theme Toggle Navbar Block for React
A navbar whose theme button opens the new theme as a circle growing from the button you pressed (View Transitions, guarded), with a menu to pick Light, Dark or System by name.
Installation
Overview
A navbar with a theme control for React with Base UI, for a notes app called Duskdial. After the links sit the catalog's Theme Toggle Button, which cycles light, dark and system, and a small chevron button that opens a menu to pick Light, Dark or System by name. A change opens as a circle that grows from the button you used, through the View Transitions API: the browser keeps a picture of the old page and the new theme is revealed under an expanding circle. Where the browser lacks the API, or the visitor prefers reduced motion, the theme simply changes. The page really changes: the dark class goes on or off <html>, System follows the device and keeps following it while it is chosen, and a polite line says "Theme: Dark". Both controls stay in the bar on a phone, while the links and the Shine Button move into a sheet from the top. The menu is portalled over the page, so the block stays one bar high (64 pixels, 56 on a phone). It's built from Theme Toggle Button, Dropdown Menu, Sheet, Guides, Shine Button and Button, with your theme's tokens for every colour. For products where the theme is a choice, not a given.
FAQ
How does the circle reveal work, and where does it start?
reveal calls document.startViewTransition with a function that sets the theme. When the transition is ready it animates the new picture's clip-path from a circle of zero radius at a point to a circle that reaches the window's farthest corner, over half a second; a temporary style switches off the browser's own cross-fade while it runs and is removed when it ends. The point is where you pressed: the pointer for a click, the middle of the button for a key press, and the middle of the chevron button for a choice in the menu.
What if the browser can't do it, or I prefer reduced motion?
reveal checks both before it starts: document.startViewTransition must be a function and prefers-reduced-motion must not be reduce. Otherwise it applies the theme at once, with no animation and no error. The toggle button's own sun and moon turn with a CSS transition and only fade under reduced motion.
How do I connect it to next-themes or my own theme store?
The block keeps the theme in state and applies it in one function, apply, which toggles the dark class on <html>. Replace that function with your library's setTheme(theme), and read your library's theme for the buttons (the page it starts from is read once on mount). Keep the call to reveal: it wraps whatever you apply in the transition.
How does the menu work with a keyboard and a screen reader?
The chevron button is named Theme options and says whether its menu is open. The menu is a group labelled Theme with three radio items, each with an icon, the current one checked; the arrow keys move between them, Enter or Space chooses one and closes the menu, and Escape closes it. In every case focus goes back to the chevron button, and the status line says "Theme: Light", "Theme: Dark" or "Theme: System" once. Opening the menu with Enter puts focus on the first item.
How does it work on a phone?
Below the md breakpoint the links fold into a menu button that opens a sheet from the top with the four links and Start writing; the theme button and the chevron stay in the bar, so the feature is one tap away, and nothing wraps at 320 pixels. The Shine Button leaves the bar below sm and lives in the sheet. Focus moves into the sheet and stays there; Escape, the close button or choosing a link closes it, and focus goes back to the menu button.
Related
- Pro
Dark Mode Navbar
Surface and themeA tinted full-bleed navbar whose Appearance button opens a popover of three pictures, Light, Dark and Match system, that really switch the page's theme.
- Pro
Language Switcher Navbar
Accounts and scopesA navbar whose language button opens a searchable list of twelve languages in their own scripts; choosing one rewrites the bar's links and action, and choosing Arabic flips the whole bar right to left.
- Pro
Account Menu Navbar
Accounts and scopesAn app bar with an account button behind a split divider that opens a menu: an identity header with plan badge and storage bar, a Switch account radio list, and Profile, Settings, Billing and Sign out.
- Pro
Minimal Navbar
Link highlightsThe least navbar there is: a slim 48 px bar with a wordmark, three plain links and one Shine Button for a journaling app, with no motion, the current page marked by weight and a dot, and a bottom drawer on phones.
- Pro
Theme Toggle Footer
PreferencesA slim footer for a design-token editor with a theme button that cycles light, dark and system and really changes the page's theme.
- Pro
A theme pill for a writing app: a three-way toggle group (Light, System, Dark) seeded from the page's theme, with a label that says which one is on.