Button

General-purpose trigger for in-page actions (toolbars, forms, cards, action bars).

// Radix — @radix-ui/react-slot
import { Button } from "@shavin/ui";

Variants (tone=accent)

<Button variant="solid">Solid</Button>
<Button variant="soft">Soft</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>

Tone=danger

<Button variant="solid" tone="danger">Solid</Button>
<Button variant="soft" tone="danger">Soft</Button>
<Button variant="outline" tone="danger">Outline</Button>
<Button variant="ghost" tone="danger">Ghost</Button>

Sizes

<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>

Disabled

<Button disabled>Solid</Button>
<Button variant="soft" disabled>Soft</Button>
<Button variant="outline" disabled>Outline</Button>
<Button variant="ghost" disabled>Ghost</Button>

With icons

<Button iconLeft={<PlusIcon />}>New</Button>
<Button variant="outline" iconRight={<ArrowRightIcon />}>Continue</Button>
<Button variant="soft" iconLeft={<DownloadIcon />}>Download</Button>

Text Truncation (truncate=true vs false)

truncate=true (default):
truncate=false (wraps):
<div className="w-36">
  <Button truncate iconLeft={<PlusIcon />}>Very Long Action Label Here</Button>
</div>

Best Practices

[Do]Use variant='solid' tone='accent' for primary action in a container or form.
[Do]Use variant='ghost' or variant='soft' for secondary/toolbar actions to preserve visual hierarchy.
[Don't]Do not place two solid accent buttons adjacent to each other in the same action bar.

Props

PropTypeDefault
asChildboolean
truncateboolean
iconLeftReactNode
iconRightReactNode
variant"solid" | "soft" | "outline" | "ghost""solid"
tone"accent" | "danger""accent"
size"sm" | "md" | "lg""md"
Configure Theme
Theme
Accent Color
Custom
Gray Family
Appearance
Radius
Scaling
Panel Style
Heading Font
Body Font