Button
Desktop-sized buttons on Base UI. The default is polished chrome, secondary is a glass chip, and record is metallic red that lights while a session runs.
Installation
$ pnpm dlx shadcn@latest add @videorc/buttonUsage
import { Button } from "@/components/ui/button";<Button>Go Live…</Button>Examples
Variants
default is the one chrome fill on a surface: the primary action. secondary is the everyday button, a glass chip. ghost sits in toolbars and rows, outline beside a field, and destructive deletes.
Chromatic and solid
Two more fills for when the chrome default isn't the right voice. solid is the regular button: a flat fill in the primary ink, with no chrome. chromatic is a face of the theme's solid in a 2px ring of liquid chrome: bands of silver flow around the ring, glints run against them, and hover surges the flow.
chromatic is always moving, so give it one moment on a screen, not every button. Under reduced motion, the ring's metal holds still.
Sizes
Every control is 28 px tall. xs and icon-xs (24 px) are for dense rows only; lg (32 px) is for a dialog's or a card's single call to action.
Record
record is for Record and its stop button, nothing else: metallic red, polished like the default's chrome. Set data-lit while a recording or livestream runs, and it turns the brand red and its glow breathes. Delete stays destructive.
For the whole control, with its glyph, its words and the starting and stopping states, use Record Button.
As a link
A link that looks like a button is still a link: put buttonVariants() on a plain <a>. Rendering an <a> through render with nativeButton={false} keeps Base UI's button behaviour and adds role="button", which is right only for an element that acts like a button.
Theming
| Token or attribute | Meaning |
|---|---|
chrome-fill | The default fill: polished silver in dark, graphite in light |
chrome-led | Record's metallic red, lit by data-lit, with a --chrome-led-glow glow |
chrome-chromatic | The chromatic ring: --chrome-chromatic-bands of metal around --chrome-chromatic-face-stops |
glass-chip | The secondary fill |
h-control, size-control | The 28 px desktop control height |
data-variant, data-size | The variant and size, for styling from a parent |
Accessibility
An icon-only button needs an aria-label. Icons inside a labelled button are decorative; mark their position with data-icon="inline-start" or "inline-end" so the padding adjusts. Disabled buttons take no hover, so explain why with Disabled reason.
API reference
Every Base UI Button prop, plus:
Prop
Type
buttonVariants({ variant, size }) returns the classes, for a link or any element styled as a button.