# Button

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

<Preview name="button-variants" title="Styles" />

## Installation

<ComponentInstall name="button" />

This also installs [Spinner](/en/docs/components/spinner) for the loading state.

## Usage

```tsx title="app/page.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

| Style | Use it for |
| --- | --- |
| `primary` | The main action. One per view. |
| `neutral` | A strong action without the brand colour (Figma: Primary-Neutral). |
| `secondary` | Supporting actions next to a primary (Figma: Secondary-Solid). |
| `outline` | Supporting actions on busy backgrounds (Figma: Secondary-Outline). |
| `subtle` | Low-emphasis actions in toolbars and tables. |
| `transparent` | Text-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`.

<Preview compact name="button-destructive" title="Destructive" />

### On colour

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

<Preview compact name="button-on-color" title="On colour" />

### Sizes

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

<Preview compact name="button-sizes" title="Sizes" />

### States

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

<Preview compact name="button-states" title="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](/en/docs/foundations/icons) icon with `data-icon="inline-start"` or `"inline-end"`. Icon-only buttons need `iconOnly` and an `aria-label`.

<Preview compact name="button-icons" title="Icons" />

### As a link

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

```tsx title="page.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`.

<DirectionCompare name="button-variants" title="Button styles" />

## Accessibility

| Key | Action |
| --- | --- |
| <kbd>Tab</kbd> | Moves focus to the button. |
| <kbd>Enter</kbd> or <kbd>Space</kbd> | Activates 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

<ApiReference component="button" />

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

## Deviations from DGA

<ComponentDeviations component="button" />

## Contrast

<ComponentContrast component="button" />


---

[Index of every page](https://dga.omqkhafi.dev/en/llms.txt)
