# Button

> A button, or a link styled as one.

## Examples

### Variants

```vue
<template>
  <div class="demo-row">
    <UiButton>Primary</UiButton>
    <UiButton variant="secondary">Secondary</UiButton>
    <UiButton variant="solid">Solid</UiButton>
    <UiButton variant="ghost">Ghost</UiButton>
    <UiButton variant="danger">Danger</UiButton>
    <UiButton variant="link">Link</UiButton>
  </div>
</template>
```

### Sizes

```vue
<template>
  <div class="demo-row">
    <UiButton size="small" variant="secondary">Small</UiButton>
    <UiButton variant="secondary">Medium</UiButton>
    <UiButton size="large" variant="secondary">
      Large
      <template #trailing><Icon name="arrow-right" :size="14" /></template>
    </UiButton>
  </div>
</template>
```

### Loading

```vue
<script setup lang="ts">
const saving = ref(false);

async function save() {
  saving.value = true;
  await new Promise((resolve) => setTimeout(resolve, 1500));
  saving.value = false;
}
</script>

<template>
  <UiButton :loading="saving" @click="save">
    <template #spinner><span class="spinner" /></template>
    {{ saving ? "Saving…" : "Save changes" }}
  </UiButton>
</template>
```

### Links

`href` renders an `<a>`; `to` renders your router's link.

```vue
<template>
  <div class="demo-row">
    <UiButton to="/installation" variant="secondary">Router link</UiButton>
    <UiButton href="https://github.com/humanonlyweb/ui" target="_blank" variant="ghost">
      External link
    </UiButton>
    <UiButton href="/" variant="ghost" disabled>Disabled link</UiButton>
  </div>
</template>
```

## API

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `variant` | `"primary" \| "secondary" \| "solid" \| "ghost" \| "danger" \| "link"` | — | Style hook, exposed as `data-button-variant`. |
| `size` | `"small" \| "medium" \| "large"` | — | Size hook, exposed as `data-button-size`. |
| `fullWidth` | `boolean` | — | Layout hook, exposed as `data-button-full-width`. |
| `loading` | `boolean` | — | Busy state: blocks clicks and sets `aria-busy`, but stays focusable. |
| `disabled` | `boolean` | — | Disables the button. A disabled link loses its `href` and leaves the tab order. |
| `type` | `"button" \| "submit" \| "reset"` | — | Native button type. |
| `href` | `string` | — | Renders an `<a>` to this URL instead of a `<button>`. |
| `to` | `string \| Record<string, unknown>` | — | Route for the router link given to `createUi({ link })`, rendering it instead of a `<button>`. |
| `target` | `"_blank" \| "_self" \| "_parent" \| "_top"` | — | Link target. |

| Slot | Props | Description |
| --- | --- | --- |
| `default` | — | Label. |
| `leading` | — | Before the label, e.g. an icon. |
| `trailing` | — | After the label, e.g. an icon. |
| `spinner` | — | Shown while `loading`. |

## Styling

- Parts (`[data-part="…"]`): `button`, `button-spinner`, `button-label`
- State attributes: `data-button-variant`, `data-button-size`, `data-button-full-width`, `data-button-disabled`, `data-button-loading`

## Keyboard

| Keys              | Action   |
| ----------------- | -------- |
| `Enter` / `Space` | Activate |

## Accessibility

- While `loading`, clicks are ignored but the button keeps focus.
- Disabled links lose their `href` and leave the tab order.
