Button
A button runs an action. Comb splits it by meaning: a button acts, an icon button acts with an icon and a name, and a link button navigates. None takes a class or style, so the variant is the whole look.
Variants
Secondary is the default. Primary is the one gold action in a view. Ghost sits in bars and rows. Ghost danger is the quiet red for a row action that destroys something (Revoke, Remove). Danger is the filled red for the one confirmed destructive action. Link is a text action inside copy or a row.
Show code
<KbButton variant="primary">Resolve request</KbButton>
<KbButton>Assign to me</KbButton>
<KbButton variant="ghost">Hide details</KbButton>
<KbButton variant="danger">Delete rule</KbButton>
<KbButton variant="link">View history</KbButton>Sizes
Medium (36px) is the default. Small (32px) fits dense rows and toolbars; large (40px) is for a page's lead action. Under 860px wide, icon buttons grow to 44px so they stay easy to tap.
Show code
<KbButton size="sm">Assign</KbButton>
<KbButton>Assign to me</KbButton>
<KbButton size="lg">Assign to me</KbButton>
<KbButton full>Assign to me</KbButton>States
Hover deepens the fill, press scales to 98%, keyboard focus draws the gold ring. Busy keeps the label in place for width, shows a spinner and blocks input. Disabled fades to half strength.
Show code
<KbButton variant="primary" busy={saving} onClick={save}>
Save changes
</KbButton>Show code
<KbButton variant="primary" disabled>Resolve request</KbButton>Icon and link buttons
Show code
<KbIconButton label="Close details">
<CloseIcon />
</KbIconButton>
<KbIconButton label="Close details" variant="secondary" round>
<CloseIcon />
</KbIconButton>Show code
<KbLinkButton href="/design/components/lozenge">Read about lozenges</KbLinkButton>When to use
- Use a button for an action that happens on this page: save, resolve, assign, delete.
- Write the label as a verb and a noun, in sentence case: Resolve request, Add rule. The confirmation uses the same words.
- Put the one primary on the trailing edge of the header. If two actions compete, one becomes secondary.
- Use a link button, not a button, when the action takes the person to another page.
- Use danger only when something is destroyed. Cancel is never red.
Import
import { KbButton, KbIconButton, KbLinkButton, KbKbd } from "@/components/ui/KbButton";Props
| Prop | Type | Default | What it does |
|---|---|---|---|
variant | "primary" | "secondary" | "ghost" | "ghost-danger" | "danger" | "link" | "secondary" | The whole look. One primary per view. |
size | "sm" | "md" | "lg" | "md" | 32, 36 or 40px tall. |
full | boolean | false | Fills the width of its container. |
busy | boolean | false | Shows the spinner, sets aria-busy and blocks input. |
type | "button" | "submit" | "reset" | "button" | Set submit only on a form's own save button. |
disabled | boolean | false | Fades the button and removes it from the tab order. |
| Prop | Type | Default | What it does |
|---|---|---|---|
label | string | None | Required. The accessible name and the tooltip. |
variant | "primary" | "secondary" | "ghost" | "ghost-danger" | "danger" | "link" | "ghost" | Ghost in bars and rows; secondary when it needs a plate. |
size | "sm" | "md" | "lg" | "md" | A square at the button height. |
round | boolean | false | Pill corners, for bar triggers. |
children | ReactNode | None | The icon: a 16px stroke SVG with aria-hidden. |
| Prop | Type | Default | What it does |
|---|---|---|---|
href | LinkProps["href"] | None | Required. Where it goes. |
variant | "primary" | "secondary" | "ghost" | "ghost-danger" | "danger" | "link" | "secondary" | Same looks as the button. |
size | "sm" | "md" | "lg" | "md" | Same heights as the button. |
full | boolean | false | Fills the width of its container. |
round | boolean | false | Pill corners. |
aria-current | "page" | undefined | None | Marks the link to the page you are on. |
Keyboard and screen readers
- Buttons render a native button with type button, so a stray click inside a form never submits it.
- An icon button must have a label. It becomes the accessible name and the tooltip.
- Busy sets aria-busy and disables input; the label stays in the DOM, so the name does not change mid-save.
- Focus shows the shared 2px gold ring on keyboard focus only.
- Disabled buttons cannot be focused. When a person needs to know why, keep the button enabled and explain in a notice.