Primitives
Button
Trigger for user actions; renders as <button> or <a> depending on context
import { Button } from '@amezquita/design-system/components/primitives/Button'Live render
Props
| Prop | Type | Description |
|---|---|---|
variant? | 'primary' | 'secondary' | 'ghost' | 'link' | |
children | React.ReactNode | |
onClick? | (event: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => void | |
disabled? | boolean | |
loading? | boolean | |
fullWidth? | boolean | |
type? | 'button' | 'submit' | 'reset' | |
icon? | React.ReactNode | |
iconPosition? | 'start' | 'end' | |
arrow? | boolean | Trailing arrow after the label. Off by default — turn it on for a call to action that leads somewhere. Ignored on the link variant and while loading. |
motion? | 'functional' | 'expressive' | 'expressive' adds the hover wipe and glow, and loads GSAP on demand. Left at 'functional', hover is a plain background change and no animation code is fetched. See decisions/0016. |
aria-label? | string | |
href? | string | |
curtainColor? | string | |
onNavigate? | (href: string, curtainColor?: string) => void | Called instead of a plain navigation when set and the link is internal — lets host apps inject route-transition behavior (e.g. a page-curtain animation) without Button depending on any specific router or transition system. Omit for a plain internal navigation. |
Also accepts all props of: Omit<React.HTMLAttributes<HTMLElement>, 'onClick' | 'type'>
Tokens
| Token | Type | Value |
|---|---|---|
--button-arrow-nudge | dimension | 2px |
--button-ghost-background | color | transparent |
--button-ghost-border | color | transparent |
--button-glow-color | color | rgba(255, 255, 255, 0.45) |
--button-glow-size | dimension | 52px |
--button-outline-border-width | dimension | 2px |
--button-padding-x | dimension | 24px |
--button-padding-y | dimension | 12px |
--button-secondary-background | color | transparent |
--button-secondary-background-hover | color | #262626 † |
--button-secondary-border | color | #262626 † |
--button-secondary-foreground | color | #262626 † |
--button-spinner-duration | duration | 750ms |
--button-wipe-duration-curve | duration | 220ms |
--button-wipe-duration-curve-out | duration | 180ms |
--button-wipe-duration-enter | duration | 550ms |
--button-wipe-duration-exit | duration | 400ms |
† resolves differently across base/portfolio and light/dark themes — see tokens.json for all four values.
Accessibility
- Semantic element:
<button>by default;<a>whenhrefis passed - When rendered as
<a>: nodisabledattribute — use visual suppression only if truly needed - ARIA: use
aria-labelfor icon-only buttons;disabledon<button>removes it from tab order - Keyboard:
Enter+Spaceactivate<button>;Enterfollows<a>