Folio

Components

Button

Use for actions that trigger a mutation or event. Not for labels, navigation, or status.

Preview

Rendered with live Folio tokens -- toggle the theme and it remaps, no dark: classes.

Variants

<Button>Button</Button>
<Button variant="outline">Outline</Button>
<Button variant="destructive">Delete</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>

Sizes

<Button size="default"><Check />Default</Button>
<Button size="sm"><Check />Small</Button>
<Button size="icon"><Plus /></Button>
<Button size="icon-sm"><Plus /></Button>
<Button size="icon-xs"><Plus /></Button>
<Button loading loadingText="Saving…">Save</Button>
<Button size="sm" loading loadingText="Saving…">Save</Button>

Icons and the loading spinner scale with the button size -- no per-instance sizing. default is the top of the scale. The API also has xs, xxs, and icon-xxs for dense toolbars.

States

<Button disabled>Disabled</Button>
<Button loading loadingText="Saving…">Save</Button>

loading is a built-in prop -- it shows a spinner and disables the button. Don't add an external spinner.

API

Prop
Type
Default
Description
variant
"default" | "destructive" | "outline" | "secondary" | "ghost" | "link"
"default"
Visual style of the button. Prefer outline over secondary for a bordered button.
size
"default" | "sm" | "xs" | "xxs" | "icon" | "icon-sm" | "icon-xs" | "icon-xxs"
"default"
Height and padding; icons scale with the size. Icon sizes are square.
asChild
boolean
false
Render the child element as the button (e.g. a link), keeping the styles.
disabled
boolean
false
Dims to 50% and blocks interaction (native button prop).
loading
boolean
false
Shows a spinner in place of the children and disables the button.
loadingText
string
--
Label shown next to the spinner while loading is true.
tooltipText
string
--
Wraps the button in a Tooltip that shows on hover, enabled or disabled.
disabledTooltipText
string
--
Replaces tooltipText while the button is disabled. Use it to explain why.

Don't and Do

Don't

Don't use a Button as a non-interactive label, category, or status pill -- that's a Tag or a Badge.

Do
// Triggers a mutation or event
<Button onClick={save}>Save changes</Button>
<Button variant="destructive" onClick={remove}>
  Delete
</Button>
import { Button } from "@/components/shadcn/button";

export function SaveChanges() {
  return <Button onClick={handleSave}>Save changes</Button>;
}

Drop-in ready. Variants and Folio tokens are baked into the component -- no className needed for standard usage.

API matches @distylai/toolkit-ui Button -- variants, sizes, and props (asChild, loading, loadingText, tooltipText, disabledTooltipText).