The most-reused primitive. Five variants, three sizes, five states. Touch targets never fall below 44 × 44 px regardless of visual size.
Primary Secondary Ghost Destructive Link
default
hover
focus
disabled
loading
tsx · view.tsx
import { Button } from '@petanque-life/shared';
<Button variant="primary" size="md" onClick={save}>
Register
</Button>
<Button variant="secondary" leadingIcon={<Icon name="arrow-right" />}>
Learn more
</Button>
<Button variant="destructive" loading>
Delete season
</Button> API
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "primary" | "secondary" | "ghost" | "destructive" | "link" | "primary" | Visual emphasis. |
| size | "sm" | "md" | "lg" | "md" | Control height (44 px minimum on touch). |
| loading | boolean | false | Swap label for a spinner; disables the button. |
| disabled | boolean | false | Standard disabled state. |
| leadingIcon | ReactNode | — | Icon rendered before the label. |
| trailingIcon | ReactNode | — | Icon rendered after the label. |
| as | "button" | "a" | "button" | Render as an anchor when the action navigates. |