Skip to content

Button

Triggers an action. Six styles, destructive and on-colour versions, three sizes, icon-only and loading.

Version 0.4.1 ·

Styles

Installation

bunx --bun shadcn@latest add @dga/button

This also installs Spinner for the loading state.

Usage

app/page.tsx
tsx
import { Button } from "@/components/ui/button";

export default function Page() {
  return <Button>Submit request</Button>;
}

Anatomy

Root (<button type="button">, or any element through render), an optional Icon before or after the Label, and a Spinner that replaces the leading icon while loading.

Examples

Styles

StyleUse it for
primaryThe main action. One per view.
neutralA strong action without the brand colour (Figma: Primary-Neutral).
secondarySupporting actions next to a primary (Figma: Secondary-Solid).
outlineSupporting actions on busy backgrounds (Figma: Secondary-Outline).
subtleLow-emphasis actions in toolbars and tables.
transparentText-like actions. The label changes colour on hover.

Destructive

Add destructive for actions that delete or cannot be undone. Every style except neutral has a destructive version; neutral falls back to destructive primary.

Destructive

On colour

Add onColor on brand fills (background-primary, the nav header). Destructive labels are white there; the text carries the meaning.

On colour

Sizes

sm is 24px, md 32px (default) and lg 40px high.

Sizes

States

aria-pressed marks a toggle button (or data-selected in menus and groups), disabled blocks the action, loading shows progress.

Selected, disabled and loading

loading swaps the leading icon for a spinner, keeps the width and ignores clicks. The button stays focusable.

Icons

Mark a Hugeicons icon with data-icon="inline-start" or "inline-end". Icon-only buttons need iconOnly and an aria-label.

Icons

To make a link look like a button, render an anchor with the render prop:

page.tsx
tsx
<Button nativeButton={false} render={<a href="/services" />}>
  Services
</Button>

RTL

Icons, gaps and padding swap sides on their own (logical properties). Directional icons such as arrows do not: add rtl:-scale-x-100.

LTR (English)
RTL (Arabic)

Accessibility

KeyAction
TabMoves focus to the button.
Enter or SpaceActivates it.
  • Native <button type="button">: the button role and its label are announced.
  • Focus ring on :focus-visible only: 2px border-black (white in dark mode and on brand fills), 1px gap.
  • Icon-only buttons need an aria-label; icons are hidden from screen readers.
  • aria-pressed marks a pressed toggle. loading sets aria-busy and aria-disabled; the spinner is decorative.

API Reference

Button

Triggers an action. Six styles, destructive and on-colour versions, three sizes, icon-only and loading.

Button props
PropTypeDefault
"primary" | "neutral" | "secondary" | "outline" | "subtle" | "transparent"

Style. `neutral` is Figma's Primary-Neutral, `secondary` is Secondary-Solid and `outline` is Secondary-Outline.

"primary"
"sm" | "md" | "lg"

Height: `sm` 24px, `md` 32px, `lg` 40px.

"md"
boolean

Destructive version of the style. `neutral` has none in Figma and falls back to destructive `primary`.

false
boolean

For buttons on brand fills (`background-primary`, the nav header).

false
boolean

Square, icon only. Needs an `aria-label`.

false
boolean

Shows a spinner in place of the leading icon (or the icon, for icon-only buttons), sets aria-busy and ignores clicks. The button keeps its width and stays focusable.

false
ReactElement | function

Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render.

No default

Also accepts every prop of the Base UI Button (opens in a new tab).

buttonVariants() is exported for styling other elements as buttons.

Deviations from DGA

ChangeReason
--button-background-transparent-hovered (light)White label on white-20 over the brand fill fails AA (down to 2.38:1). Black-20 darkens the fill instead (6.30:1 or better), as dark mode already does.
--button-background-transparent-pressed (light)White label on white-40 over the brand fill fails AA (down to 2.38:1). Black-40 darkens the fill instead (6.30:1 or better), as dark mode already does.
--button-background-transparent-selected (light)White label on white-30 over the brand fill fails AA (down to 2.38:1). Black-30 darkens the fill instead (6.30:1 or better), as dark mode already does.
--button-label-transparent-hovered-on-color (light) and 11 moreGreen-300/400 on the brand fill is 2.10–2.82:1. The label stays white and the state is shown with an underline instead.

View all 46 deviations for this component

Contrast

1,210 pairs checked · all pass WCAG 2.1 AAShow 242 states
Variant / stateLightDark
primary / default4.74:1 AA4.74:1 AA
primary / default (icon)4.74:1 3:14.74:1 3:1
primary / hovered6.60:1 AA6.60:1 AA
primary / hovered (icon)6.60:1 3:16.60:1 3:1
primary / pressed10.81:1 AAA10.81:1 AAA
primary / pressed (icon)10.81:1 3:110.81:1 3:1
primary / selected8.55:1 AAA8.55:1 AAA
primary / selected (icon)8.55:1 3:18.55:1 3:1
primary / focused4.74:1 AA4.74:1 AA
primary / focused (icon)4.74:1 3:14.74:1 3:1
primary / focus ring17.31:1 3:117.49:1 3:1
neutral / default18.74:1 AAA15.89:1 AAA
neutral / default (icon)18.74:1 3:115.89:1 3:1
neutral / hovered14.53:1 AAA10.57:1 AAA
neutral / hovered (icon)14.53:1 3:110.57:1 3:1
neutral / pressed7.36:1 AAA7.66:1 AAA
neutral / pressed (icon)7.36:1 3:17.66:1 3:1
neutral / selected10.17:1 AAA10.57:1 AAA
neutral / selected (icon)10.17:1 3:110.57:1 3:1
neutral / focused18.74:1 AAA15.89:1 AAA
neutral / focused (icon)18.74:1 3:115.89:1 3:1
neutral / focus ring17.31:1 3:117.49:1 3:1
secondary / default16.44:1 AAA12.71:1 AAA
secondary / default (icon)16.44:1 3:112.71:1 3:1
secondary / hovered14.61:1 AAA6.95:1 AA
secondary / hovered (icon)14.61:1 3:16.95:1 3:1
secondary / pressed14.61:1 AAA6.95:1 AA
secondary / pressed (icon)14.61:1 3:16.95:1 3:1
secondary / selected14.61:1 AAA9.59:1 AAA
secondary / selected (icon)14.61:1 3:19.59:1 3:1
secondary / focused16.44:1 AAA12.71:1 AAA
secondary / focused (icon)16.44:1 3:112.71:1 3:1
secondary / focus ring17.31:1 3:117.49:1 3:1
outline / default17.31:1 AAA15.87:1 AAA
outline / default (icon)17.31:1 3:115.87:1 3:1
outline / hovered16.44:1 AAA12.71:1 AAA
outline / hovered (icon)16.44:1 3:112.71:1 3:1
outline / pressed14.61:1 AAA6.95:1 AA
outline / pressed (icon)14.61:1 3:16.95:1 3:1
outline / selected14.61:1 AAA9.59:1 AAA
outline / selected (icon)14.61:1 3:19.59:1 3:1
outline / focused17.31:1 AAA15.87:1 AAA
outline / focused (icon)17.31:1 3:115.87:1 3:1
outline / focus ring17.31:1 3:117.49:1 3:1
subtle / default17.31:1 AAA15.87:1 AAA
subtle / default (icon)17.31:1 3:115.87:1 3:1
subtle / hovered16.44:1 AAA12.71:1 AAA
subtle / hovered (icon)16.44:1 3:112.71:1 3:1
subtle / pressed14.61:1 AAA6.95:1 AA
subtle / pressed (icon)14.61:1 3:16.95:1 3:1
subtle / selected14.61:1 AAA9.59:1 AAA
subtle / selected (icon)14.61:1 3:19.59:1 3:1
subtle / focused17.31:1 AAA15.87:1 AAA
subtle / focused (icon)17.31:1 3:115.87:1 3:1
subtle / focus ring17.31:1 3:117.49:1 3:1
transparent / default17.31:1 AAA15.87:1 AAA
transparent / default (icon)17.31:1 3:115.87:1 3:1
transparent / hovered6.31:1 AA10.38:1 AAA
transparent / hovered (icon)6.31:1 3:110.38:1 3:1
transparent / pressed10.34:1 AAA13.05:1 AAA
transparent / pressed (icon)10.34:1 3:113.05:1 3:1
transparent / selected8.18:1 AAA10.38:1 AAA
transparent / selected (icon)8.18:1 3:110.38:1 3:1
transparent / focused17.31:1 AAA15.87:1 AAA
transparent / focused (icon)17.31:1 3:115.87:1 3:1
transparent / focus ring17.31:1 3:117.49:1 3:1
primary on-colour / default18.09:1 AAA17.04:1 AAA
primary on-colour / default (icon)18.09:1 3:117.04:1 3:1
primary on-colour / hovered12.97:1 AAA13.44:1 AAA
primary on-colour / hovered (icon)12.97:1 3:113.44:1 3:1
primary on-colour / pressed8.89:1 AAA10.30:1 AAA
primary on-colour / pressed (icon)8.89:1 3:110.30:1 3:1
primary on-colour / selected8.89:1 AAA10.30:1 AAA
primary on-colour / selected (icon)8.89:1 3:110.30:1 3:1
primary on-colour / focused18.09:1 AAA16.42:1 AAA
primary on-colour / focused (icon)18.09:1 3:116.42:1 3:1
primary on-colour / focus ring4.74:1 3:14.74:1 3:1
neutral on-colour / default18.09:1 AAA17.04:1 AAA
neutral on-colour / default (icon)18.09:1 3:117.04:1 3:1
neutral on-colour / hovered12.97:1 AAA13.44:1 AAA
neutral on-colour / hovered (icon)12.97:1 3:113.44:1 3:1
neutral on-colour / pressed8.89:1 AAA10.30:1 AAA
neutral on-colour / pressed (icon)8.89:1 3:110.30:1 3:1
neutral on-colour / selected10.76:1 AAA11.80:1 AAA
neutral on-colour / selected (icon)10.76:1 3:111.80:1 3:1
neutral on-colour / focused18.09:1 AAA16.42:1 AAA
neutral on-colour / focused (icon)18.09:1 3:116.42:1 3:1
neutral on-colour / focus ring4.74:1 3:14.74:1 3:1
secondary on-colour / default6.30:1 AA6.30:1 AA
secondary on-colour / default (icon)6.30:1 3:16.30:1 3:1
secondary on-colour / hovered6.30:1 AA6.30:1 AA
secondary on-colour / hovered (icon)6.30:1 3:16.30:1 3:1
secondary on-colour / pressed8.46:1 AAA8.46:1 AAA
secondary on-colour / pressed (icon)8.46:1 3:18.46:1 3:1
secondary on-colour / selected7.31:1 AAA7.31:1 AAA
secondary on-colour / selected (icon)7.31:1 3:17.31:1 3:1
secondary on-colour / focused6.30:1 AA6.30:1 AA
secondary on-colour / focused (icon)6.30:1 3:16.30:1 3:1
secondary on-colour / focus ring4.74:1 3:14.74:1 3:1
outline on-colour / default4.74:1 AA4.74:1 AA
outline on-colour / default (icon)4.74:1 3:14.74:1 3:1
outline on-colour / hovered6.30:1 AA6.30:1 AA
outline on-colour / hovered (icon)6.30:1 3:16.30:1 3:1
outline on-colour / pressed8.46:1 AAA8.46:1 AAA
outline on-colour / pressed (icon)8.46:1 3:18.46:1 3:1
outline on-colour / selected7.31:1 AAA7.31:1 AAA
outline on-colour / selected (icon)7.31:1 3:17.31:1 3:1
outline on-colour / focused4.74:1 AA4.74:1 AA
outline on-colour / focused (icon)4.74:1 3:14.74:1 3:1
outline on-colour / focus ring4.74:1 3:14.74:1 3:1
subtle on-colour / default4.74:1 AA4.74:1 AA
subtle on-colour / default (icon)4.74:1 3:14.74:1 3:1
subtle on-colour / hovered6.30:1 AA6.30:1 AA
subtle on-colour / hovered (icon)6.30:1 3:16.30:1 3:1
subtle on-colour / pressed8.46:1 AAA8.46:1 AAA
subtle on-colour / pressed (icon)8.46:1 3:18.46:1 3:1
subtle on-colour / selected7.31:1 AAA7.31:1 AAA
subtle on-colour / selected (icon)7.31:1 3:17.31:1 3:1
subtle on-colour / focused4.74:1 AA4.74:1 AA
subtle on-colour / focused (icon)4.74:1 3:14.74:1 3:1
subtle on-colour / focus ring4.74:1 3:14.74:1 3:1
transparent on-colour / default4.74:1 AA4.74:1 AA
transparent on-colour / default (icon)4.74:1 3:14.74:1 3:1
transparent on-colour / hovered4.74:1 AA4.74:1 AA
transparent on-colour / hovered (icon)4.74:1 3:14.74:1 3:1
transparent on-colour / pressed4.74:1 AA4.74:1 AA
transparent on-colour / pressed (icon)4.74:1 3:14.74:1 3:1
transparent on-colour / selected4.74:1 AA4.74:1 AA
transparent on-colour / selected (icon)4.74:1 3:14.74:1 3:1
transparent on-colour / focused4.74:1 AA4.74:1 AA
transparent on-colour / focused (icon)4.74:1 3:14.74:1 3:1
transparent on-colour / focus ring4.74:1 3:14.74:1 3:1
destructive primary / default4.83:1 AA4.83:1 AA
destructive primary / default (icon)4.83:1 3:14.83:1 3:1
destructive primary / hovered6.57:1 AA6.57:1 AA
destructive primary / hovered (icon)6.57:1 3:16.57:1 3:1
destructive primary / pressed9.84:1 AAA9.84:1 AAA
destructive primary / pressed (icon)9.84:1 3:19.84:1 3:1
destructive primary / selected8.66:1 AAA8.66:1 AAA
destructive primary / selected (icon)8.66:1 3:18.66:1 3:1
destructive primary / focused4.83:1 AA4.83:1 AA
destructive primary / focused (icon)4.83:1 3:14.83:1 3:1
destructive primary / focus ring17.31:1 3:117.49:1 3:1
destructive secondary / default6.04:1 AA8.59:1 AAA
destructive secondary / default (icon)6.04:1 3:18.59:1 3:1
destructive secondary / hovered5.45:1 AA7.94:1 AAA
destructive secondary / hovered (icon)5.45:1 3:17.94:1 3:1
destructive secondary / pressed4.63:1 AA7.50:1 AAA
destructive secondary / pressed (icon)4.63:1 3:17.50:1 3:1
destructive secondary / selected6.04:1 AA8.59:1 AAA
destructive secondary / selected (icon)6.04:1 3:18.59:1 3:1
destructive secondary / focused6.04:1 AA8.59:1 AAA
destructive secondary / focused (icon)6.04:1 3:18.59:1 3:1
destructive secondary / focus ring17.31:1 3:117.49:1 3:1
destructive primary on-colour / default4.83:1 AA4.83:1 AA
destructive primary on-colour / default (icon)4.83:1 3:14.83:1 3:1
destructive primary on-colour / hovered6.57:1 AA6.57:1 AA
destructive primary on-colour / hovered (icon)6.57:1 3:16.57:1 3:1
destructive primary on-colour / pressed9.84:1 AAA9.84:1 AAA
destructive primary on-colour / pressed (icon)9.84:1 3:19.84:1 3:1
destructive primary on-colour / selected8.66:1 AAA8.66:1 AAA
destructive primary on-colour / selected (icon)8.66:1 3:18.66:1 3:1
destructive primary on-colour / focused4.83:1 AA4.83:1 AA
destructive primary on-colour / focused (icon)4.83:1 3:14.83:1 3:1
destructive primary on-colour / focus ring4.74:1 3:14.74:1 3:1
destructive secondary on-colour / default6.04:1 AA6.04:1 AA
destructive secondary on-colour / default (icon)6.04:1 3:16.04:1 3:1
destructive secondary on-colour / hovered5.45:1 AA5.45:1 AA
destructive secondary on-colour / hovered (icon)5.45:1 3:15.45:1 3:1
destructive secondary on-colour / pressed4.63:1 AA4.63:1 AA
destructive secondary on-colour / pressed (icon)4.63:1 3:14.63:1 3:1
destructive secondary on-colour / selected6.04:1 AA6.04:1 AA
destructive secondary on-colour / selected (icon)6.04:1 3:16.04:1 3:1
destructive secondary on-colour / focused6.04:1 AA6.04:1 AA
destructive secondary on-colour / focused (icon)6.04:1 3:16.04:1 3:1
destructive secondary on-colour / focus ring4.74:1 3:14.74:1 3:1
destructive outline / default6.29:1 AA9.01:1 AAA
destructive outline / default (icon)6.29:1 3:19.01:1 3:1
destructive outline / hovered5.45:1 AA7.94:1 AAA
destructive outline / hovered (icon)5.45:1 3:17.94:1 3:1
destructive outline / pressed4.63:1 AA7.50:1 AAA
destructive outline / pressed (icon)4.63:1 3:17.50:1 3:1
destructive outline / selected6.04:1 AA8.59:1 AAA
destructive outline / selected (icon)6.04:1 3:18.59:1 3:1
destructive outline / focused6.29:1 AA9.01:1 AAA
destructive outline / focused (icon)6.29:1 3:19.01:1 3:1
destructive outline / focus ring17.31:1 3:117.49:1 3:1
destructive outline on-colour / default4.74:1 AA4.74:1 AA
destructive outline on-colour / default (icon)4.74:1 3:14.74:1 3:1
destructive outline on-colour / hovered6.30:1 AA6.30:1 AA
destructive outline on-colour / hovered (icon)6.30:1 3:16.30:1 3:1
destructive outline on-colour / pressed8.46:1 AAA8.46:1 AAA
destructive outline on-colour / pressed (icon)8.46:1 3:18.46:1 3:1
destructive outline on-colour / selected7.31:1 AAA7.31:1 AAA
destructive outline on-colour / selected (icon)7.31:1 3:17.31:1 3:1
destructive outline on-colour / focused4.74:1 AA4.74:1 AA
destructive outline on-colour / focused (icon)4.74:1 3:14.74:1 3:1
destructive outline on-colour / focus ring4.74:1 3:14.74:1 3:1
destructive subtle / default6.29:1 AA9.01:1 AAA
destructive subtle / default (icon)6.29:1 3:19.01:1 3:1
destructive subtle / hovered5.45:1 AA7.94:1 AAA
destructive subtle / hovered (icon)5.45:1 3:17.94:1 3:1
destructive subtle / pressed4.63:1 AA7.50:1 AAA
destructive subtle / pressed (icon)4.63:1 3:17.50:1 3:1
destructive subtle / selected6.04:1 AA8.59:1 AAA
destructive subtle / selected (icon)6.04:1 3:18.59:1 3:1
destructive subtle / focused6.29:1 AA9.01:1 AAA
destructive subtle / focused (icon)6.29:1 3:19.01:1 3:1
destructive subtle / focus ring17.31:1 3:117.49:1 3:1
destructive subtle on-colour / default4.74:1 AA4.74:1 AA
destructive subtle on-colour / default (icon)4.74:1 3:14.74:1 3:1
destructive subtle on-colour / hovered6.30:1 AA6.30:1 AA
destructive subtle on-colour / hovered (icon)6.30:1 3:16.30:1 3:1
destructive subtle on-colour / pressed8.46:1 AAA8.46:1 AAA
destructive subtle on-colour / pressed (icon)8.46:1 3:18.46:1 3:1
destructive subtle on-colour / selected7.31:1 AAA7.31:1 AAA
destructive subtle on-colour / selected (icon)7.31:1 3:17.31:1 3:1
destructive subtle on-colour / focused4.74:1 AA4.74:1 AA
destructive subtle on-colour / focused (icon)4.74:1 3:14.74:1 3:1
destructive subtle on-colour / focus ring4.74:1 3:14.74:1 3:1
destructive transparent / default4.62:1 AA6.27:1 AA
destructive transparent / default (icon)4.62:1 3:16.27:1 3:1
destructive transparent / hovered6.29:1 AA9.01:1 AAA
destructive transparent / hovered (icon)6.29:1 3:19.01:1 3:1
destructive transparent / pressed9.42:1 AAA12.32:1 AAA
destructive transparent / pressed (icon)9.42:1 3:112.32:1 3:1
destructive transparent / selected8.29:1 AAA9.01:1 AAA
destructive transparent / selected (icon)8.29:1 3:19.01:1 3:1
destructive transparent / focused4.62:1 AA6.27:1 AA
destructive transparent / focused (icon)4.62:1 3:16.27:1 3:1
destructive transparent / focus ring17.31:1 3:117.49:1 3:1
destructive transparent on-colour / default4.74:1 AA4.74:1 AA
destructive transparent on-colour / default (icon)4.74:1 3:14.74:1 3:1
destructive transparent on-colour / hovered4.74:1 AA4.74:1 AA
destructive transparent on-colour / hovered (icon)4.74:1 3:14.74:1 3:1
destructive transparent on-colour / pressed4.74:1 AA4.74:1 AA
destructive transparent on-colour / pressed (icon)4.74:1 3:14.74:1 3:1
destructive transparent on-colour / selected4.74:1 AA4.74:1 AA
destructive transparent on-colour / selected (icon)4.74:1 3:14.74:1 3:1
destructive transparent on-colour / focused4.74:1 AA4.74:1 AA
destructive transparent on-colour / focused (icon)4.74:1 3:14.74:1 3:1
destructive transparent on-colour / focus ring4.74:1 3:14.74:1 3:1

Text needs 4.5:1, icons and focus rings 3:1. Disabled states are exempt. Full contrast report