Primitives

Button

Trigger for user actions; renders as <button> or <a> depending on context

Markdown version for agents

Import
import { Button } from '@amezquita/design-system/components/primitives/Button'

Live render

    Props

    PropTypeDescription
    variant?'primary' | 'secondary' | 'ghost' | 'link'
    childrenReact.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?booleanTrailing 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) => voidCalled 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

    TokenTypeValue
    --button-arrow-nudgedimension2px
    --button-ghost-backgroundcolortransparent
    --button-ghost-bordercolortransparent
    --button-glow-colorcolorrgba(255, 255, 255, 0.45)
    --button-glow-sizedimension52px
    --button-outline-border-widthdimension2px
    --button-padding-xdimension24px
    --button-padding-ydimension12px
    --button-secondary-backgroundcolortransparent
    --button-secondary-background-hovercolor#262626 †
    --button-secondary-bordercolor#262626 †
    --button-secondary-foregroundcolor#262626 †
    --button-spinner-durationduration750ms
    --button-wipe-duration-curveduration220ms
    --button-wipe-duration-curve-outduration180ms
    --button-wipe-duration-enterduration550ms
    --button-wipe-duration-exitduration400ms

    † resolves differently across base/portfolio and light/dark themes — see tokens.json for all four values.

    Accessibility

    • Semantic element: <button> by default; <a> when href is passed
    • When rendered as <a>: no disabled attribute — use visual suppression only if truly needed
    • ARIA: use aria-label for icon-only buttons; disabled on <button> removes it from tab order
    • Keyboard: Enter + Space activate <button>; Enter follows <a>