Button

Triggers an action or event.

Installation
$Terminal
npx shadcn@latest add https://sdk-components.thesqd.com/r/button.json
Usage
Import from the master file. Pass `variant` for tone and `size` for footprint.
TSImport
import { Button } from "@/components/ui/button";
import { ButtonGroup } from "@/components/ui/button-group";
TSExample
import { Button } from "@/components/ui/button";

export function Example() {
  return <Button variant="default">Click me</Button>;
}
Composition
Anatomy of the Button primitive and ButtonGroup.
Button
└── children (text, icons with data-icon="inline-start" | "inline-end")

ButtonGroup
└── Button[] (joined visually — first/last get rounded ends)
Variants
Ten stylistic variants out of the box. `tonal` inherits the surrounding `currentColor` so the button auto-tints to whatever surface it sits on (try it inside a warning Alert with `actionButton`).
Fancy
`variant="fancy"` is the glossy pill — a top-lit vertical gradient with a refined triple inset/drop shadow (top white highlight + bottom inner shadow + soft drop) and a hairline ring, scaling down slightly on press. Pick a tone with the `color` prop (`brand` | `coral` | `destructive` | `warning` | `success` | `ghost`, defaulting to `brand`); `ghost` is the neutral dark glossy button. Pass `className` only to override beyond those presets.
Fancy — with icons
Same glossy pill with icons. Mark a child icon with `data-icon="inline-start"` / `"inline-end"` for optical padding beside the label, or pass `size="icon"` for an icon-only button.
Fancy — loading
Loading state: drop a `<Spinner color="current" data-icon="inline-start" />` (use `color="current"` so the spinner matches the button text) into a `fancy` button and set `disabled` while the async action runs.
Long press
`<LongPressButton>` requires a press-and-hold to fire — a progress sweep fills over `holdDuration` (default 1600ms) and releasing early cancels (`onHoldCancel`); completing fires `onHoldComplete`. Works with pointer and keyboard (Space/Enter), respects reduced-motion, and takes the same `variant`/`size` props as Button. Good for destructive confirmations.
Tonal (inherits surrounding color)
`variant="tonal"` styles the button with `bg-current/10 text-current` so it picks up whatever `currentColor` the parent surface establishes. Drop one inside any tinted card, alert, or banner and it auto-matches without any per-tone wiring.
Neutral
Brand
Info
Success
Warning
Destructive
Sizes
Three text sizes plus matching icon-only sizes.
Wide
Always stretches to fill its container — ideal for form submits and full-width CTAs.
With icons
Icons can sit inline on either side of the label.
States
Default, hover, and disabled behavior per variant.
Toggle (outline ↔ primary)
`<ToggleButton>` manages its own pressed state — `inactiveVariant` (defaults to `outline`) when off, `activeVariant` (defaults to `default`/primary) when on, with `aria-pressed` wired automatically. Use uncontrolled (`defaultPressed`) or controlled (`pressed` + `onPressedChange`). The last row drives both the variant and label from state — an outline **And** that flips to a coral **Or**.
Button group
Adjacent buttons joined into a single control.
Button group with dropdown
Split button — primary action on the left, a dropdown menu on the right lets the user switch the action.
Button group with action menu
Primary button keeps its action; the dropdown contains separate secondary actions that each fire their own handler when clicked.
API Reference
Props exposed by the Button primitive and ButtonGroup wrapper.

Button

PropTypeDefaultDescription
variant"default" | "fancy" | "fancy-outline" | "secondary" | "outline" | "ghost" | "destructive" | "link" | "soft" | "tonal" | "coral" | "transparent""default"Visual tone. `default` is brand violet; `fancy` is the glossy gradient pill; `soft` is the tinted treatment.
color"brand" | "coral" | "destructive" | "warning" | "success" | "ghost""brand"Tone for `variant="fancy"` (ignored by other variants). `className` still overrides.
size"xs" | "sm" | "default" | "xl" | "wide" | "icon" | "icon-xs" | "icon-sm" | "icon-xl""default"`wide` stretches to fill its container. The `icon-*` sizes pair with a single child icon and `aria-label`.
renderReactElementBase UI render-prop — pass another element (e.g. `<Link/>`) to swap the underlying tag.
classNamestringOverride or extend the resolved variant classes.

ButtonGroup

PropTypeDefaultDescription
orientation"horizontal" | "vertical""horizontal"Stack adjacent buttons inline or vertically.
classNamestringAdditional classes applied to the group wrapper.