# Button

## Overview

Buttons support key user actions, like submitting forms or adding items.

- **When to use**:
  - The user needs to trigger an action: submit a form, open a modal, delete, toggle state. If pressing it doesn't navigate, use a Button.
  - Form navigation (back/next): although these lead to another screen, the user stays in the same flow — use buttons, not links.
- **When not to use**:
  - Navigation to another page, section, or external destination (URL changes, no side effects) — use a **Link**.
  - Navigation where parent-page context matters — use **Breadcrumbs**.
  - Destructive actions without a confirmation step.

### Types

Choose the type based on the action it represents:

- **Primary** — the most important action on a page. Use sparingly; max one per set of actions.
- **Secondary** — more common actions.
- **Ghost** — lightweight option for where the context is clear.
- **Intelligence** — automation and generation (AI) actions.
- **Status** — critical, warning, or success actions.
- **Brand** — Lighthouse-related messaging.

### Sizes

Small, medium, large. Medium is the default. Only use small and large when space is limited or additional hierarchy is needed.

## Anatomy

1. **Container** — holds all elements; background and border communicate the type and state. Border-radius is 6px, applied globally via `prism-foundation` (not a standard token step — do not override).
2. **Label** — describes the action. Verb-first, 1–3 words, sentence case. Optional for icon-only buttons (see A11y intent).
3. **Leading icon** (optional) — reinforces the action's meaning. Icon-label gap: `spacing.200` (8px).
4. **Trailing icon** (optional) — only when it represents forward movement (e.g. "Next step →").
5. **Loading spinner** — replaces the label while a clicked action processes; the button keeps its original width to avoid layout shifts.

## Variants

| `buttonType`             | Intent                                                                          |
| ------------------------ | ------------------------------------------------------------------------------- |
| `primary`                | The most important action on a page. Use sparingly; max one per set of actions. |
| `secondary`              | More common actions.                                                            |
| `critical`               | Critical status action.                                                         |
| `critical-secondary`     | Lower-emphasis critical action.                                                 |
| `warning`                | Warning status action.                                                          |
| `success`                | Success status action.                                                          |
| `intelligence`           | Automation and generation (AI) actions.                                         |
| `intelligence-secondary` | Lower-emphasis AI action.                                                       |
| `brand`                  | Lighthouse-related messaging.                                                   |
| `ghost`                  | Lightweight option for where the context is clear.                              |
| `unstyled`               | _[Design to fill]_                                                              |

## Props / API

| Prop             | Type                                                                                                                                                                         | Default     | Description                                                   |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------------------------------------------------------------- |
| `buttonType`     | `"primary" \| "secondary" \| "critical" \| "critical-secondary" \| "warning" \| "success" \| "intelligence" \| "intelligence-secondary" \| "brand" \| "ghost" \| "unstyled"` | `"primary"` | Visual/semantic style of the button.                          |
| `size`           | `"small" \| "medium" \| "large"`                                                                                                                                             | `"medium"`  | Control height and type scale.                                |
| `icon`           | `IconName`                                                                                                                                                                   | -           | Leading icon (shorthand).                                     |
| `iconBefore`     | `IconName`                                                                                                                                                                   | -           | Icon before the label.                                        |
| `iconAfter`      | `IconName`                                                                                                                                                                   | -           | Icon after the label.                                         |
| `isLoading`      | `boolean`                                                                                                                                                                    | `false`     | Shows spinner + `loadingMessage`; content is replaced.        |
| `loadingMessage` | `string`                                                                                                                                                                     | `"Loading"` | Text announced/shown while loading.                           |
| `href`           | `string`                                                                                                                                                                     | -           | When set, renders as an anchor (`<a>`) instead of `<button>`. |
| `isDisabled`     | `boolean`                                                                                                                                                                    | `false`     | Disables the button (button only, not with `href`).           |

Standard HTML `<button>` / `<a>` attributes are forwarded via `...rest`.

## States

- Default (idle) / Hover / Active/pressed — buttons provide interaction feedback while changing between these states.
- Focus-visible — for keyboard navigation, displays a focus ring as visual feedback when moving between elements. Always `color.interactive.border.focus`, 2px outline, 2px offset.
- Disabled — use to show an action exists but is temporarily unavailable.
- Loading — a spinner shows a clicked action is processing; interaction is disabled but the button stays visible and keeps its width. Don't conditionally hide a button during async actions.

## Code examples

```tsx
import { Button } from "@mylighthouse/prism-react";

export default function ButtonExample(): React.JSX.Element {
  return (
    <>
      <Button size="large" iconBefore="plus">
        Primary large with icon before
      </Button>
      <Button buttonType="secondary" size="small" iconAfter="plus">
        Secondary small with icon after
      </Button>
      <Button buttonType="brand" isLoading loadingMessage="Brand is loading...">
        Brand loading
      </Button>
      <Button buttonType="critical" isDisabled>
        Critical disabled
      </Button>
      <Button aria-label="Icon only - Add" buttonType="ghost" icon="plus" />
      <Button buttonType="secondary" href="/settings">
        Link
      </Button>
    </>
  );
}
```

## A11y intent

- Icon-only buttons must always have an `aria-label` — a tooltip alone is not sufficient.
- Minimum 44×44px touch target on mobile (WCAG 2.2.1).
- Focus must be visible for keyboard navigation: `color.interactive.border.focus`, 2px outline, 2px offset.
- Never rely on color alone to convey the button's meaning (WCAG 1.4.1) — status buttons pair color with a clear label and/or icon.
- Labels must let users predict the outcome (WCAG 2.4.6 intent): verb-first, specific.
- Loading state: interaction is disabled while processing; the control remains in the accessibility tree.
- Ghost buttons on dark backgrounds require the `--prism-surface-inverse` parent context to keep contrast.
- Renders semantic `<button>` by default, `href` renders a real `<a>` (link semantics, keyboard/AT correct for free).
- `isLoading` surfaces `loadingMessage` so state change is announced, not silent.
- Icon-only usage must still expose an accessible name.

## Do's & don'ts

**Primary actions**

- ✅ Use only one primary button in the available actions to focus the most important action in a flow.
- ❌ Don't present multiple primary buttons as high-level actions.

**Labels with clear expectations**

- ✅ Start labels with a verb so users can predict what happens when clicked — "Save changes", not "Submit".
- ❌ Don't make users guess what will happen.

**Icons**

- ✅ Use icons with labels when they clearly support important actions; place a trailing icon only for forward movement.
- ✅ Use icon-only buttons only in layouts with limited space and when the icon is widely recognized (menu, edit); add a tooltip on hover to clarify.
- ❌ Don't use specific/ambiguous icons without a label.

**Ghost buttons**

- ✅ Use position and additional icons to make the action context clear.
- ❌ Don't place ghost buttons so they look like static content.

**Loading**

- ✅ Keep the button visible and sized during async actions via the loading state.
- ❌ Don't conditionally hide or swap the button while processing.

## Cross-references

- **[Link](../link.md)** — navigation instead of action. Link → changes URL, opens a new tab, anchors to a section. Button → triggers an action with side effects.
- **[Button group](../button-group.md)** — segmented control for selecting from a fixed set of options; not a row of action buttons.
- **Actions (category overview)** — decision tree for Button vs Link vs Breadcrumbs.
- **Writing guidelines: action copy** — verb first, action at the front followed by expected result; applies to all buttons.
