Skip to content

Button

Triggers an action. Text label always; use IconButton for icon-only actions.

  • Free core, MIT
  • Version 2.0.0-rc.1
  • APG pattern: Button

Examples

These are the real React components. Use them with a mouse, touch or keyboard, and switch the theme and density for every example at once.

Default

Show the code

Default, code

<Button>Save changes</Button>

Variants

Show the code

Variants, code

<div className="flex flex-wrap items-center gap-gap-md">
  <Button>Default</Button>
  <Button variant="secondary">Secondary</Button>
  <Button variant="outline">Outline</Button>
  <Button variant="ghost">Ghost</Button>
  <Button variant="destructive">Delete project</Button>
  <Button variant="link">Read the guide</Button>
</div>

Sizes

Show the code

Sizes, code

<div className="flex flex-wrap items-center gap-gap-md">
  <Button size="sm">Small</Button>
  <Button>Default</Button>
  <Button size="lg">Large</Button>
</div>

With icons

Show the code

With icons, code

<div className="flex flex-wrap items-center gap-gap-md">
  <Button iconStart={Plus}>New project</Button>
  <Button variant="outline" iconEnd={ArrowRight}>Continue</Button>
  <Button variant="destructive" iconStart={Trash2}>Remove member</Button>
</div>

Loading

Show the code

Loading, code

<Button isLoading>Saving</Button>

Disabled

Show the code

Disabled, code

<div className="flex flex-wrap items-center gap-gap-md">
  <Button isDisabled>Default</Button>
  <Button variant="secondary" isDisabled>Secondary</Button>
  <Button variant="outline" isDisabled>Outline</Button>
  <Button variant="ghost" isDisabled>Ghost</Button>
  <Button variant="destructive" isDisabled>Destructive</Button>
</div>

Tokens

The 36 design tokens Button reads, with the value each has in the theme and density chosen above. Change a token and the component follows, in Figma and in code.

Show all 36 tokens
Tokens Button reads
TokenValue nowCSS variable
button.danger.bg…--sd-button-danger-bg
button.danger.bg-hover…--sd-button-danger-bg-hover
button.danger.bg-pressed…--sd-button-danger-bg-pressed
button.danger.fg…--sd-button-danger-fg
button.disabled.bg…--sd-button-disabled-bg
button.disabled.border…--sd-button-disabled-border
button.disabled.fg…--sd-button-disabled-fg
button.gap…--sd-button-gap
button.ghost.bg-hover…--sd-button-ghost-bg-hover
button.ghost.bg-pressed…--sd-button-ghost-bg-pressed
button.ghost.fg…--sd-button-ghost-fg
button.height.lg…--sd-button-height-lg
button.height.md…--sd-button-height-md
button.height.sm…--sd-button-height-sm
button.hit-area…--sd-button-hit-area
button.link.fg…--sd-button-link-fg
button.link.fg-pressed…--sd-button-link-fg-pressed
button.outline.bg…--sd-button-outline-bg
button.outline.bg-hover…--sd-button-outline-bg-hover
button.outline.bg-pressed…--sd-button-outline-bg-pressed
button.outline.border…--sd-button-outline-border
button.outline.fg…--sd-button-outline-fg
button.padding-x.lg…--sd-button-padding-x-lg
button.padding-x.md…--sd-button-padding-x-md
button.padding-x.sm…--sd-button-padding-x-sm
button.primary.bg…--sd-button-primary-bg
button.primary.bg-hover…--sd-button-primary-bg-hover
button.primary.bg-pressed…--sd-button-primary-bg-pressed
button.primary.fg…--sd-button-primary-fg
button.secondary.bg…--sd-button-secondary-bg
button.secondary.bg-hover…--sd-button-secondary-bg-hover
button.secondary.bg-pressed…--sd-button-secondary-bg-pressed
button.secondary.fg…--sd-button-secondary-fg
motion.duration.fast…--sd-motion-duration-fast
motion.easing.standard…--sd-motion-easing-standard
shape.radius-control…--sd-shape-radius-control

Install

The npm package isn’t published yet. When it is, this is the install line; until then, this page runs the same build of the package (from commit fa3abf8).

Install

npm i @superduperui/react @superduperui/tokens

Import

import { Button, buttonVariants } from "@superduperui/react"

Props

Button also takes the props of the React Aria component it’s built on.

Button props
PropTypeWhat it does
variant'default' | 'secondary' | 'outline' | 'ghost' | 'destructive' | 'link'shadcn meanings: default = primary (one per view); secondary = filled brand tint, no border; outline = bordered on the canvas; ghost = no fill until hovered; destructive = danger fill; link = underlined text action. Figma's Variant options are the same six in Title Case.
size'sm' | 'default' | 'lg'sm 36px visual (44px hit area), default 44px, lg 52px.
childrenrequiredReactNodeThe visible label. Always text: never an icon alone (use IconButton).
iconStartLucideIconLucide icon before the label (decorative).
iconEndLucideIconLucide icon after the label (decorative).
isLoadingbooleanPending state: keeps the label, shows a spinner, sets aria-busy and blocks presses while staying focusable.

When to use it

Use it for

  • Submitting or saving a form
  • Starting a task in the current view
  • Opening a Dialog

Use something else for

  • Navigating to another page: use a link
  • Icon-only actions: use IconButton
  • Toggling a setting: use Switch

Accessibility

Screen readers announce "Save changes, button"; loading adds "busy".

WCAG 2.2 AAA criteria the component meets in Comfortable density: 1.4.6, 1.4.9, 2.1.3, 2.3.2, 2.4.13, 2.5.5, 2.5.6, 2.3.3.

Compact density meets AA (2.5.8, 24px targets), not AAA.

What your product still has to do

  • One primary (default) button per view
  • Destructive actions confirm or offer undo

Shared patterns it ships with: 3.3.6 (destructive actions pair with an alert dialog or undo).

This release’s test results

Test results for Button in this release
axe-core (WCAG A, AA, AAA and best practice)160 runs across every story, theme, density and width: 0 violations
Rendered text contrast260 text runs: 0 below 7:1, lowest 7.79:1
Target size90 targets: 0 under 44px in Comfortable
Focus appearance (2.4.13)126 focus stops in 3 browser engines: all pass
Keyboard scriptChromium 3 of 3, Firefox 3 of 3, WebKit 3 of 3

Manual passes with VoiceOver and NVDA haven’t been done yet.

Keyboard

Each step is scripted and run in Chromium, Firefox and WebKit.

Button keyboard steps
KeyWhat happens
TabTab reaches the button
EnterEnter activates
SpaceSpace activates

In Figma

The Figma component is Button, with Variant (Default, Secondary, Outline, Ghost, Destructive, Link); Size (Small, Default, Large); State (Default, Hover, Pressed, Focus, Disabled, Loading). The Figma library isn’t published yet.

Figma to code: Variant → variant (Default = "default", Secondary = "secondary", Outline = "outline", Ghost = "ghost", Destructive = "destructive", Link = "link"); Size → size (Small = "sm", Default = "default", Large = "lg"); State (Default, Hover, Pressed, Focus, Disabled = isDisabled, Loading = isLoading); Label → children; Leading icon → iconStart when Show leading icon; Trailing icon → iconEnd when Show trailing icon.