Chuv Studio

02 — COMPONENTS

Button

Trigger actions or navigate. Built on @base-ui/react/button with class-variance-authority variants.

Variants

Six semantic variants — choose based on action hierarchy

Default
<Button>Default</Button>
Secondary
<Button variant="secondary">Secondary</Button>
Outline
<Button variant="outline">Outline</Button>
Ghost
<Button variant="ghost">Ghost</Button>
Destructive
<Button variant="destructive">Destructive</Button>
Link
<Button variant="link">Link</Button>

Sizes

Eight size tokens — from xs icon buttons to large CTAs

XS
<Button size="xs">Extra Small</Button>
SM
<Button size="sm">Small</Button>
Default
<Button>Default</Button>
LG
<Button size="lg">Large</Button>

Icon Buttons

Square icon-only buttons — use aria-label for accessibility

icon-xs
<Button size="icon-xs" variant="outline" aria-label="Add">
  <Plus />
</Button>
icon-sm
<Button size="icon-sm" variant="outline" aria-label="Add">
  <Plus />
</Button>
icon
<Button size="icon" aria-label="Add">
  <Plus />
</Button>
icon-lg
<Button size="icon-lg" aria-label="Add">
  <Plus />
</Button>

With Icons

Combine text with leading or trailing icons

Leading
<Button>
  <Mail />
  Send Email
</Button>
Trailing
<Button>
  Continue
  <ArrowRight />
</Button>
Outline
<Button variant="outline">
  <Download />
  Download
</Button>
Destructive
<Button variant="destructive">
  <Trash2 />
  Delete
</Button>

States

Disabled and loading states for interactive feedback

Disabled
<Button disabled>Disabled</Button>
Outline dis.
<Button variant="outline" disabled>Disabled</Button>
Loading
<Button disabled>
  <Loader2 className="animate-spin" />
  Loading…
</Button>
Load outline
<Button variant="outline" disabled>
  <Loader2 className="animate-spin" />
  Loading…
</Button>

All Variants — Side by Side

Visual comparison across all variants and the default size

Usage

Import and use in any component

Import

import { Button } from "@/components/ui/button"

Props

variant

"default" | "secondary" | "outline" | "ghost" | "destructive" | "link"

Default: "default"

size

"xs" | "sm" | "default" | "lg" | "icon-xs" | "icon-sm" | "icon" | "icon-lg"

Default: "default"

disabled

boolean

Default: false

asChild

boolean

Default: false — render as a different element

Accessibility

  • Icon-only buttons must have an aria-label
  • Use disabled prop — never CSS-only opacity
  • Keyboard: Space / Enter to activate

Chuv Studio Design System · Component: button.tsx · @base-ui/react/button + CVA