Button
Interactive button for actions and form submissions.
Installation
npx asteria-ui add buttonUsage
import { Button } from "@/components/ui/button";
<Button>Save changes</Button>
<Button variant="secondary">Cancel</Button>Examples
Variants
Primary, secondary, ghost, destructive, and link.
Sizes
sm 32px · md 40px · lg 48px · xl 56px.
With icon
leadingIcon accepts any element and sizes it automatically to match the
button — 16px at sm/md, 20px at lg/xl. It's a decorative slot: the icon is
marked aria-hidden for you.
States
loading shows a spinner, sets aria-busy, and disables the button —
independent of the disabled prop, so a button can be disabled without
being in a loading state.
API reference
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "primary" | "secondary" | "ghost" | "destructive" | "link" | "primary" | Visual style. |
| size | "sm" | "md" | "lg" | "xl" | "md" | Density — 32 / 40 / 48 / 56px height. |
| leadingIcon | ReactNode | — | Instance-swap icon slot rendered before the label, auto-sized to match the button's size (16px sm/md, 20px lg/xl). |
| loading | boolean | false | Shows a spinner, sets aria-busy, and disables the button. |
| disabled | boolean | false | Prevents interaction. |
Accessibility
Accessibility
Role. Native
<button>, sorole="button"and keyboard activation (Enter/Space) come from the browser, not manual ARIA.Focus. Visible
glow-focusring on Tab, viafocus-visible— never shown on a pointer click.Disabled. The native
disabledattribute prevents all interaction, including fromloading.Loading.
aria-busy="true"announces the busy state to screen readers while the spinner is visible.