DEVELOPMENT PREVIEWIn development

Button

One button, two axes: variant sets the visual weight (how much attention it demands) and tone sets the meaning (brand, neutral, success, danger). Every pairing works — no more one-off variants for every color.

Variants — visual weight

From strongest to quietest. A view usually wants exactly one solid button; support it with outline, soft or ghost neighbors.

Snippet
import { Button } from '@creo-team/buzz-ui/client'

<Button>Solid</Button>              {/* the default */}
<Button variant="soft">Soft</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>
<Button variant="glass">Glass</Button>

Tones — meaning

Tones re-color any weight. Omitted, solid and link default to primary while the quieter weights default to neutral — chrome stays chrome unless you say otherwise.

tone ↓solidsoftoutlineghostlink
primary
neutral
success
danger
Snippet
<Button tone="danger">Delete</Button>              {/* solid danger */}
<Button variant="soft" tone="success">Approve</Button>
<Button variant="outline" tone="danger">Remove</Button>
<Button variant="ghost" tone="primary">Learn more</Button>
<Button tone="neutral">High contrast</Button>      {/* inverse button */}

Sizes

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

States

Snippet
<Button disabled>Disabled</Button>
<Button loading>Loading</Button>
<Button fullWidth>Full Width</Button>

With icons

Icon-only buttons

Snippet
<Button>
  <PlusIcon className="h-4 w-4" />
  Add Item
</Button>

{/* Icon-only: circular hit area; always label it for screen readers */}
<Button variant="ghost" iconOnly aria-label="Settings">
  <GearIcon className="h-5 w-5" />
</Button>

Selected state

Snippet
{/* selected sets aria-pressed — use it for toggles */}
<Button variant="ghost" selected={view === 'grid'} onClick={() => setView('grid')}>
  Grid
</Button>

Toggle button group

Snippet
function ToggleButtonGroup() {
  const [selected, setSelected] = useState('grid')

  return (
    <div className="inline-flex gap-0.5 rounded-xl border border-[var(--c-border)] p-0.5">
      {options.map(option => (
        <Button
          key={option.value}
          variant="ghost"
          size="sm"
          selected={selected === option.value}
          onClick={() => setSelected(option.value)}
        >
          {option.icon}
          {option.label}
        </Button>
      ))}
    </div>
  )
}

Migrating from v0.6

The ten flat v0.6 variants keep working as deprecated aliases — no breakage — but new code should use the axes:

v0.6now
variant="bold"(default — just <Button>)
variant="success"tone="success"
variant="danger"tone="danger"
variant="subtle"variant="soft"
variant="text"variant="link"
variant="nav"variant="ghost"
variant="icon"variant="ghost" iconOnly

API Reference

PropTypeDefaultDescription
variant
'solid' | 'soft' | 'outline' | 'ghost' | 'link' | 'glass''solid'Visual weight. v0.6 names are accepted as deprecated aliases.
tone
'primary' | 'neutral' | 'success' | 'danger''primary' (solid/link), 'neutral' otherwiseSemantic color, orthogonal to variant.
size
'sm' | 'md' | 'lg''md'Size preset for padding and text.
loading
booleanfalseShows a spinner, disables interaction, sets aria-busy.
selected
boolean—Toggle state — sets aria-pressed and the selected styling.
hotkey
string | { key, description?, action? }—Keyboard shortcut that clicks the button (e.g. 'mod+s').
iconOnly
booleanfalseCircular icon button — pair with aria-label.
fullWidth
booleanfalseStretch to the container's width.
asChild
booleanfalseRender the child element (e.g. a framework Link) with button styling.
...props
React.ButtonHTMLAttributes<HTMLButtonElement>—All standard button attributes.

See the full API: /components/button/api