# Button

> Triggers an action, with six variants, four sizes and a loading state.

Category: Actions · Status: stable · Package: @bindshq/stance-react@0.1.1 · Docs: https://stanceui.com/components/button

Use Button for actions that change something: saving, submitting, opening a dialog. Use Link for navigation that only moves the user elsewhere. Keep one primary button per view so the main action is unambiguous.

## Import

```tsx
import { Button } from '@bindshq/stance-react';
```

Styles are imported once per app: `@bindshq/stance-tokens/css` and `@bindshq/stance-react/styles.css`.

## Examples

### Basic

```tsx
import { Button } from '@bindshq/stance-react';

export function Basic() {
  return <Button>Save changes</Button>;
}
```

### Variants

Emphasis from strongest to weakest. Danger is reserved for destructive actions.

```tsx
import { Button } from '@bindshq/stance-react';

export function Variants() {
  return (
    <div style={{ display: 'flex', flexWrap: 'wrap', gap: 12 }}>
      <Button variant="primary">Primary</Button>
      <Button variant="secondary">Secondary</Button>
      <Button variant="outline">Outline</Button>
      <Button variant="ghost">Ghost</Button>
      <Button variant="danger">Delete</Button>
      <Button variant="link">Link</Button>
    </div>
  );
}
```

### Sizes

Control heights of 24, 32, 40 and 48px align with inputs of the same size.

```tsx
import { Button } from '@bindshq/stance-react';

export function Sizes() {
  return (
    <div style={{ display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: 12 }}>
      <Button size="xs">Extra small</Button>
      <Button size="sm">Small</Button>
      <Button size="md">Medium</Button>
      <Button size="lg">Large</Button>
    </div>
  );
}
```

### With icons

```tsx
import { Button, Icon } from '@bindshq/stance-react';

export function WithIcons() {
  return (
    <div style={{ display: 'flex', flexWrap: 'wrap', gap: 12 }}>
      <Button leadingIcon={<Icon name="plus" />}>New template</Button>
      <Button variant="outline" trailingIcon={<Icon name="arrow-right" />}>
        Continue
      </Button>
    </div>
  );
}
```

### Loading

Loading keeps the button focusable and announces aria-busy while blocking repeat clicks.

```tsx
import { Button } from '@bindshq/stance-react';

export function Loading() {
  return (
    <div style={{ display: 'flex', flexWrap: 'wrap', gap: 12 }}>
      <Button loading>Save</Button>
      <Button loading loadingText="Publishing…" variant="outline">
        Publish
      </Button>
    </div>
  );
}
```

### Pill shape

Fully rounded ends for marketing calls to action.

```tsx
import { Button, Icon } from '@bindshq/stance-react';

export function Pill() {
  return (
    <Button shape="pill" size="lg" trailingIcon={<Icon name="arrow-right" />}>
      Let’s talk
    </Button>
  );
}
```

### As a link

Use asChild to give a router link button styling while keeping link semantics.

```tsx
import { Button } from '@bindshq/stance-react';

export function AsLink() {
  return (
    <Button asChild variant="outline">
      <a href="#docs">Read the docs</a>
    </Button>
  );
}
```

## API reference

| Component | Prop | Type | Default | Description |
| --- | --- | --- | --- | --- |
| Button | `variant` | `'primary' \| 'secondary' \| 'outline' \| 'ghost' \| 'danger' \| 'link'` | `'primary'` | Visual emphasis. |
| Button | `size` | `'xs' \| 'sm' \| 'md' \| 'lg'` | `'md'` | Control height: 24, 32, 40 or 48px. |
| Button | `shape` | `'default' \| 'pill'` | `'default'` | Pill gives fully rounded ends. |
| Button | `loading` | `boolean` | `false` | Shows a spinner, sets aria-busy and blocks clicks. |
| Button | `loadingText` | `ReactNode` | None | Replaces the label while loading. |
| Button | `leadingIcon` | `ReactNode` | None | Rendered before the label. |
| Button | `trailingIcon` | `ReactNode` | None | Rendered after the label. |
| Button | `fullWidth` | `boolean` | `false` | Fill the container width. |
| Button | `asChild` | `boolean` | `false` | Render the child element with button styles. |
| Button | `...props` | `ButtonHTMLAttributes` | None | All native button attributes. type defaults to "button". |

## Accessibility

- Renders a native <button>, so it is focusable and activates with Enter and Space without extra code.
- type defaults to "button" to prevent accidental form submission; pass type="submit" explicitly.
- Icon-only actions should use IconButton, which requires an accessible label.
- Loading sets aria-busy and aria-disabled but keeps focus, so keyboard users do not lose their place.
- Focus is shown with a 2px ring (3px in high contrast) offset from the button edge.

## Keyboard

| Keys | Action |
| --- | --- |
| `Enter` | Activates the button. |
| `Space` | Activates the button. |

## Guidelines

**Do**

- Start labels with a verb: “Save changes”, “Invite member”.
- Use one primary button per view.

**Don’t**

- Use a button to navigate between pages; use Link.
- Disable a submit button to signal errors; show the errors instead.

## Related

- https://stanceui.com/components/icon-button
- https://stanceui.com/components/button-group
- https://stanceui.com/components/split-button
- https://stanceui.com/components/link
