Skip to content

Buttons

Button is the primary action primitive. Pick a variant for emphasis and a size for density; both map to --ds-* tokens, so you never hardcode a color. Use asChild to render the button styling on another element (for example a router link) without nesting an extra DOM node.

Live demo

The interactive story below runs from the deployed Storybook. Use the controls to switch variant and size.

Usage

Source: button.tsx

import { Button } from "@beacon/design-system";
<Button>Save</Button>
<Button variant="secondary">Cancel</Button>
<Button variant="destructive">Delete</Button>
<Button variant="outline">Export</Button>
<Button variant="ghost">More</Button>
<Button variant="link">Learn more</Button>
// Sizes
<Button size="sm">Compact</Button>
<Button size="lg">Prominent</Button>
// Render as another element (e.g. a link) without an extra wrapper
<Button asChild>
<a href="/dashboard">Go to dashboard</a>
</Button>

Variants

VariantStoryUse for
defaultDefaultThe primary action on a view.
secondarySecondaryA supporting action next to the primary.
destructiveDestructiveIrreversible actions (delete, remove).
outlineOutlineLower-emphasis action with a visible border.
ghostGhostMinimal action, often in toolbars or menus.
linkLinkLooks like a hyperlink; no button chrome.

Sizes

SizeStoryNotes
defaultDefaultStandard control height.
smSmallDense layouts and inline actions.
lgLargeHigh-emphasis primary calls to action.

Props

PropTypeDefaultDescription
variant"default" | "secondary" | "destructive" | "outline" | "ghost" | "link""default"Visual emphasis.
size"default" | "sm" | "lg" | "icon""default"Control density. icon for square icon-only buttons.
asChildbooleanfalseRender styling on the child element instead of a <button>.

When to use

  • Any committed user action: submit, save, cancel, navigate, delete.
  • Aim for one default (primary) action per view; everything else is secondary, outline, or ghost.

Do not use a Button for navigation that should be a real link when SEO or middle-click matters. Use asChild with an <a> instead so it stays a true anchor.