Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Dark Mode Navbar Block for React

A 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.

Framework
UI library

Preview

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Overview

A navbar with an appearance picker for React with Base UI, for an e-book reader called Duskreader. The bar is a full-bleed band on a soft tint (bg-muted/50 on the section, with foreground links and an outlined button) between the page's rails. Its Appearance button opens a popover with three pictures of a reading page, Light, Dark and Match system, as radio cards; the chosen one takes a 2 pixel ring. Choosing really changes the page: the dark class goes on or off <html>, Match system follows the device and keeps following it, and a polite line says "Theme: Dark". The pictures are drawn with the page's own tokens: the Dark one sits in a dark scope because it is a picture of dark, and in a dark page the Light one swaps the two token pairs, so each stays what its name says in every theme and preset. On a phone the button keeps only its icon, and the links and the Shine Button move into a sheet from the top. The popover is portalled over the page, so the block stays one bar high (64 pixels, 56 on a phone). It's built from Popover, Sheet, Guides, Shine Button and Button, with your theme's tokens for every colour. For reading and writing apps where the look of the page is part of the product.

FAQ

Why does the Dark picture carry a dark scope?

It is a picture of dark, not part of the navbar: the bar itself follows the theme and paints nothing dark. The picture's wrapper takes the dark class, so inside it every token resolves to its dark value in your preset; the Light picture needs no scope in a light page, and in a dark page it swaps --background and --foreground for the card's --sample-* copies of the page's own pair. Match system is the Dark picture with the Light one cut across it by a diagonal.

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 cards; the theme the page starts with is read once on mount. While Match system is chosen the block listens to the device's prefers-color-scheme and re-applies it when it changes.

How does the picker work with a keyboard and a screen reader?

The Appearance button says whether its popover is open. The three cards are native radios in one fieldset named Appearance: one tab stop, the arrow keys move the choice (and, as the choice is the setting, the page changes with it), the pictures are hidden from assistive technology and each card is named by its words. Escape closes the popover and focus goes back to the Appearance button. The status line says "Theme: Light", "Theme: Dark" or "Theme: Match system" once per change.

How is the tinted bar made?

The tint is bg-muted/50 on the header, not on the column, so it runs to both edges of the window while the rails and the top rule from Guides stay where every other block has them. The links are foreground rather than muted, the current page keeps its 1 pixel stroke on the bar's bottom edge, and the Appearance button is an outline Button. The tint is a token, so it follows every preset in light and dark.

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 reading. The Appearance button stays in the bar with its icon only (its name is still read), and its popover is as wide as the screen allows, so the three cards fit at 320 pixels. 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.

What moves, and what happens with reduced motion?

Little: the chosen card's ring eases in, the chevron turns, the popover and the sheet use the catalog's own entrances, and a band of light sweeps across Start reading on hover. With reduced motion the ring and the chevron change at once, and the popover and the sheet appear without sliding, zooming or fading.

  • Pro

    Theme Toggle Navbar

    Surface and theme

    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.

  • Pro

    Language Switcher Navbar

    Accounts and scopes

    A 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 scopes

    An 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 highlights

    The 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

    A corner-radius picker card for a design-token editor: four chips drawn with their own corners, a greyscale preview that re-rounds as you choose, and Apply and Reset actions.

  • Pro

    A slim footer for a design-token editor with a theme button that cycles light, dark and system and really changes the page's theme.