# Button (/docs/button)

A composable Base UI button with variants, loading state, asChild support, and spring press feedback.

## Install

```bash
npx shadcn@latest add https://4af.selfsimilar.dev/r/button.json
```

## Usage

```tsx
import { Button } from "@/components/ui/button";

<Button variant="primary">Deploy</Button>
<Button loading>Deploy</Button>
```

## API

**Main export:** `Button`

| | Values |
| --- | --- |
| `variant` | `primary` (default), `outline`, `ghost`, `plain`, `destructive`, `link` |
| `size` | `xs` (24px), `sm` (30px), `md` (34px), `lg` (38px) |
| Square icon sizes | `icon-xs`, `icon-sm`, `icon`, `icon-lg`, matching the heights above |

The gap between icon and label is 8px at `xs`/`sm`, 10px at `md`, and 12px at `lg`. Leading and
trailing icons get a small optical edge adjustment; icon-only buttons have no gap.

`loading` blocks interaction without changing the button's size. `loader={<MySpinner />}` sets
its indicator; otherwise it inherits
[LoaderProvider](/docs/reference/engineering#shared-loading-indicators), with `AsciiLoader` as the
fallback. The slot reserves a square and keeps the busy announcement.

`asChild` renders the button's styles onto its child, such as a link, which keeps its own
semantics.

## Press behavior

Buttons scale to `0.95` while pressed by default. Set `pressScale={false}` on anchored triggers,
where the resize would make the attached panel appear to move.

```tsx
<Button pressScale={false}>Open menu</Button>
<Toggle pressScale={false} aria-label="Filter" />
```

`pressTarget="content"` scales only the label and icons, so a button joined to another control
keeps its edges still. Button Group already sets this on its children.

```tsx
<Button pressTarget="content">Save</Button>
```

Action Button, Copy Button, and Delete Button accept both props.

The native button presses with a Motion spring. With `asChild`, the press is CSS.