Components
Button
Triggers an action. Buttons are how users commit to a primary, contextual, or destructive intent. Pick the variant that matches the weight of the action.
Installation
terminal
npx shadcn@latest add @wuko/buttonUsage
components/example.tsx
import { Button } from "@/components/ui/button";
export function Example() {
return <Button variant="primary">Deploy</Button>;
}Variants
Five variants cover the full hierarchy from this is the action down to subtle, contextual, optional.
tsx
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="danger">Danger</Button>Sizes
tsx
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>States
disabled blocks interaction; loading shows a spinner before the children, sets aria-busy, and disables the button.
tsx
<Button>Default</Button>
<Button disabled>Disabled</Button>
<Button loading>Saving…</Button>Composing with icons
Place any icon (or other element) inside the button as a child. Button uses flex with a size-aware gap, so spacing matches the button's size automatically.
tsx
Icon button
Square sizes for icon-only triggers: icon-xs, icon-sm, icon, and icon-lg. An aria-label is required so the button has an accessible name.
tsx
<Button size="icon-xs" aria-label="Deploy">
<Zap className="size-3.5" />
</Button>
<Button size="icon-sm" aria-label="Deploy">
<Zap className="size-4" />
</Button>
<Button size="icon" aria-label="Deploy">
<Zap className="size-4" />
</Button>
<Button size="icon-lg" aria-label="Deploy">
<Zap className="size-5" />
</Button>Props
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "primary" | "secondary" | "outline" | "ghost" | "danger" | "primary" | Visual hierarchy of the button. |
| size | "sm" | "md" | "lg" | "icon-xs" | "icon-sm" | "icon" | "icon-lg" | "md" | Controls dimensions, padding, and font size. The icon-* sizes are square. Use them for icon-only buttons with an aria-label. |
| loading | boolean | false | Shows a spinner before the children, sets aria-busy, and disables interaction. |
| disabled | boolean | false | Prevents user interaction via the native disabled attribute. |
| ...rest | ButtonHTMLAttributes<HTMLButtonElement> | — | All native button attributes are forwarded to the element. |
Accessibility
- Renders a native
<button>element. Tab focus, Enter, and Space activation work without extra wiring. - The
loadingstate setsaria-busy="true"and disables interaction; the spinner SVG isaria-hiddenso screen readers announce the button text (e.g. “Saving…”) as the progress indicator. disableduses the native attribute, which removes the element from the tab order and blocks click events.- Focus is announced visually with a 2px outline in
--wuko-accentat a 2px offset, visible against any background. - Icon-only buttons (any
size="icon-*") require anaria-labelso screen readers can announce the button's purpose. The icon SVG itself should remainaria-hidden.