Danger
Destructive action people cannot undo: solid chrome, danger tone.
<Button variant="solid" tone="danger">
Delete item
</Button>Triggers an action — save, submit, delete, open.
<Button variant="solid">Save changes</Button>Do not use a Button for plain navigation.
Don’t
<Button href="/settings">Settings</Button>Do
<Link href="/settings">Settings</Link>pnpm add @usefragments/uiImport styles once from @usefragments/ui/styles. See the installation guide for framework and theme setup.
Destructive action people cannot undo: solid chrome, danger tone.
<Button variant="solid" tone="danger">
Delete item
</Button>The one track: xs 24 for in-row actions, sm 28, md 32, lg 40.
<Stack direction="row" gap="sm" align="center" wrap>
<Button size="xs">Micro</Button>
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>
</Stack>Blocks clicks and drops the button out of the tab order.
<Button disabled>Unavailable</Button>Work is running: presses are ignored at once, the spinner shows after a second.
<Button pending>Saving</Button>render swaps the element; an anchor keeps its link role and takes the look.
<Button variant="soft" render={<a href="#billing-settings" />}>
Billing settings
</Button>Long labels stay on one line; shorten the label or give the button room.
<Button>
Save the localized account preferences and notify every affected workspace administrator
</Button>Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | Not set | The label. Optional only so a Button can be the `render` element of a trigger (`<Dialog.Trigger render={<Button />}>Open</Dialog.Trigger>`), where the trigger's children become the label. |
focusableWhenDisabled | boolean | undefined | false | Keep a disabled button in the tab order (`aria-disabled` instead of `disabled`), so keyboard and screen reader users can still reach it and read why it is unavailable. |
fullWidth | boolean | undefined | Not set | Fill the parent's width. Without it a button is as wide as its label in every parent, a column stack or a grid cell included. |
nativeButton | boolean | undefined | Not set | Whether the rendered element is a native `<button>`. Inferred from an element passed to `render` (a `<button>`, or a component without `href`); pass it when `render` is a function or a component that renders an anchor without an `href` prop. |
pending | boolean | undefined | false | Work started by this button is running. The button sets `aria-busy` and ignores further presses at once; after a second (`--fui-pending-delay`) its label fades and a spinner takes its place, and its width holds. |
render | useRender.RenderProp<Record<string, unknown>> | undefined | Not set | Replace the rendered element, e.g. `render={<a href="/docs" />}` or a router link. A rendered anchor keeps its link semantics (no button role); the button's look, pending and disabled behaviour move onto it. |
size | "xs" | "sm" | "md" | "lg" | undefinedxssmmdlg | "md" | Control height on the one track: xs 24, sm 28, md 32, lg 40. |
tone | "danger" | "neutral" | "accent" | undefineddangerneutralaccent | Not set | Colour. `solid` takes `accent` (default) or `danger`. Colour. `soft` and `ghost` take `neutral` (default) or `danger`, shown as ink. Colour. `link` takes `accent` (default, the link ink) or `neutral`. |
variant | "link" | "solid" | "soft" | "ghost" | undefinedlinksolidsoftghost | "solid" | Chrome family. |