shadcn.io is not affiliated with official shadcn/ui
Appearance Command Menu Block for React
A dashboard app's appearance menu shown open beside a live mini app: mode, corner radius, density and text size in four groups with a tick on each current choice, and a preview that restyles the moment you choose while the menu stays open.
Installation
Overview
Try an appearance before you commit to it with this appearance command menu for React with Base UI. It opens from the Appearance panel of Dialhouse, a dashboard app, whose header holds an outline field with its ⌘ K cap, and the dashboard is drawn under a soft scrim inside a hairline frame with a plus mark on each corner. The menu is the catalog Command with four groups: Mode (Light, Dark, System), Radius (Sharp, Soft, Round), Density (Compact, Comfortable) and Text size (Small, Default, Large), each with a small glyph, a short hint and a tick on the group's current choice. Beside the list sits a preview, a small drawn dashboard with a bar, a field, a button and two rows, and choosing restyles it at once while the menu stays open, so you can try one choice after another. The preview's colours, corner radius, spacing and text size are four custom properties set on its own wrapper: Dark swaps the theme's own background and text colour, System reads your device's colour scheme once the page has loaded, and the page itself, its theme and the document never change. A readout under the preview says the same in words. For preview the menu is drawn open in place when the page loads; the field, or Ctrl or ⌘ K while focus is in the block, opens the real command dialog with the same choices and query. For dashboards, editors and any product with an appearance setting.
FAQ
Why is the menu already open, and what do I keep?
So you can see it without a click. On load the menu is the Command and its preview drawn inline under a picture of the dashboard, in a plain shell that is not modal, so nothing is trapped, hidden or focused and the page around the preview keeps working. The header's field opens the real command dialog, modal, with its focus trap, Escape and focus return, and the inline copy stays closed until a reload. Both show the same Palette and share the block's state, so the choices you made in the copy are the ones the dialog opens with. In your app keep the dialog and drop the copy: the "in-place" state, the scrim with its shell and the Escape and blur effects.
Does choosing change my page?
No. The preview is a drawing with its own wrapper, and a choice only sets four custom properties on that wrapper: the two base colours, the corner radius, the spacing and the text size. Dark swaps the theme's background and text colour for each other (and swaps them again when the page itself is dark, so Light stays light), there is no dark class and no change to the page's theme, and a mix of the two colours makes every line and tint, so the preview follows any preset. In your app the same four choices would write to your theme provider.
What does System do?
It asks the browser for the device's colour scheme (prefers-color-scheme) once, after the page has loaded, and the preview wears that mode; the readout says which, "System, dark on this device". The server never knows it, so the block renders light first and corrects itself after mount. It does not follow a change made while the page is open; in your app subscribe to the media query's change event.
How do I know what is chosen?
A tick and the words ", current" mark the one choice in each group that the preview wears, and choosing the current one only says so on the status line. The readout under the preview lists the four choices, and on a phone, where the preview sits above the list, it is read out but not drawn.
What stays local, and how do I wire it?
All of it. The four choices are typed state in the block; nothing is saved and nothing leaves the page. In your app keep CHOICES as the menu's rows, make pick call your theme provider and persist the result with the user's other settings, and keep the preview as the way to see a change before it applies.
Is it accessible from the keyboard?
Yes. Type to search by name, hint or group ("dark", "round", "compact", "large"), the arrow keys move through the choices, Enter applies the highlighted one and keeps focus in the input, and Escape closes the menu and puts focus on the field. Ctrl or ⌘ K opens the dialog while focus is inside the block, and only then. The rows are options of a cmdk listbox; the block turns off its own fuzzy filter and lists the rows itself. The preview is a picture and is hidden from assistive technology; the readout and the status line carry what it shows.
How does it look on a phone?
The dashboard goes and the preview moves above the list, about 200 pixels tall. The copy shown on load docks to the top of the page at full width, so the keyboard does not cover the foot; the hints in the rows and the key hints go, and the count stays. The real dialog keeps the Command dialog's own phone layout.
Related
- Pro
Tone Picker Command Menu
Visual pickersA design tool's tone picker as a command menu shown open over its Fill row: an eleven-step grey ramp and recent tones, a HEX, RGB or HSL switch that rewrites every value and what Enter copies, and a band with the highlighted tone's contrast on white and on black.
- Pro
Design Tokens Command Menu
Visual pickersA design-system inspector's token picker as a command menu hung from a Fill field: tokens in groups with their resolved values and a small drawing, a box pane that wears whatever you apply, the alias chain of the last token, and a copy as CSS variable or JSON.
- AaAgAaAaAaPro
Font Picker Command Menu
Visual pickersA document editor's font menu hung from the toolbar's font name, with six system font stacks each set in its own real CSS stack, a specimen band that follows the highlight, a row of weights and an italic toggle, and Enter to set the document's font.
- Pro
Layout Switcher Command Menu
Visual pickersA dashboard configurator's layout switcher as a command menu docked at the end of the page: six layouts each with a greyscale diagram, a band that draws the highlighted one larger, and Enter to re-arrange the drawn dashboard, still under reduced motion.
- Pro
Language Switcher Command Menu
SwitchersA language-learning app's language menu as a command menu shown open above the language button in a lesson page's foot: ten languages by their own names with lang and dir set, a completeness bar and percent, search in any script, and a lesson page whose labels flip.
- Pro
Motion Presets Command Menu
Visual pickersA motion tool's preset menu shown open over its transitions panel: easing curves, springs and durations each drawn as a 24 px curve, a track band that runs the highlighted preset's real CSS timing once on an arrow key or Replay, and a text reading under reduced motion.