DreamLake

Button

A button for primary actions and form submits. Wraps a native <button> (so it accepts type, onClick, and the rest of the button attributes) and adds variants, sizes and a loading state.

Variants

Every variant shares one radius (6px, the badge step), one padding scale and one typeface. A set whose members round or set differently reads as parts from two kits, and none of those is where a variant should carry its meaning — the fill is. The typeface is mono, because that is the app's button vocabulary: the dialog footer, the toolbar pill and the chrome actions are all set in it.

primary fills with the accent — the app's dialog footer, to the pixel. It replaces an inverted ink fill, which made the submit button the heaviest ink on a form whose fields are bare text. Hover darkens the accent rather than fading it; a primary action should not look like it is switching off under the pointer.

ghost is the action you take by not acting — the cancel beside that primary. A bare muted mono label: no fill, no border, no hover chrome, just opacity. Two buttons in a footer make the reader compare two boxes; one button and one label say which is the way forward.

secondary is a bordered neutral button; action is the mono chrome pill for toolbars and detail headers; danger is primary's shape in the palette red; link renders as inline underlined text with no padding.

Sizes & states

Three sizes (sm, md, lg). loading shows a spinner and disables the button; disabled greys it out and blocks clicks.

Chrome actions

action is the borderless mono pill the app wears in toolbars and detail headers — + publish, + import, a back arrow. It differs from ghost in what it paints: ghost is a bare label, while action takes a hover fill, so a toolbar row reads as a row of targets rather than a run of words. Geometry is the set's — same radius, same padding as every other button.

tone colors it without reaching for style: muted for secondary chrome (a back arrow), danger for a destructive action — ink at rest, palette red under the pointer, because a row of permanently-red labels reads as an error state rather than an available action. value marks it active in the accent and switches its hover wash to --accent-soft with it; hoverBg overrides that wash for anything else. href makes it a real link, so cmd-click, middle-click and the status-bar URL all still work.

open in lake ↗

Props

PropTypeDefaultDescription
variant'primary' | 'secondary' | 'ghost' | 'action' | 'danger' | 'link''primary'Visual style. 'destructive' is also accepted as an alias for 'danger'.
size'sm' | 'md' | 'lg''sm'Padding/text scale, shared by every variant.
tone'default' | 'muted' | 'danger''default'Text color for the transparent variants (ghost, action, link). muted starts at muted ink and raises to full ink on hover — for a button inside an already-muted strip. danger keeps its ink until the pointer arrives, then turns red.
loadingbooleanfalseShows a spinner and disables the button.
leftIconReactNode—Icon rendered before the label.
iconbooleanfalseSquare icon-button padding (for a button whose content is a single icon).
valuebooleanfalseActive/selected state — renders the label and icon in the accent color, and takes --accent-soft as its hover wash.
hoverBgstringvar(--ink) at 5%Hover surface for the transparent variants. Pass var(--accent-soft) under an accent-colored label.
hrefstring—Renders an <a> with identical styling. target and rel ride along; a disabled link drops its href and reports aria-disabled.
asChildbooleanfalseRender the single child element with the button styling instead of a <button> (merging classes and forwarding props).
disabledbooleanfalseDisables interaction.
type'button' | 'submit' | 'reset''button'Native button type.
classNamestring—Extra classes on the button.

Any other native <button> attributes (onClick, aria-*, …) are forwarded.

buttonVariants

buttonVariants(options) returns the composed class string for a button without rendering one. Accepts variant, size, tone, icon, value, and className, and is useful for styling a non-button element (like a link) to match the button set.