Resinen
Actions

Button

stableserver-safe

Triggers an action. State is carried by a step on the neutral ramp rather than by movement — nothing translates on press, because motion should acknowledge input, not perform.

Variants

One primary per view. Ghost is the only variant that opts out of the border and shadow, because a row of three shadowed buttons is a mess.

<Button variant="primary">Set course</Button>
<Button>Secondary</Button>
<Button variant="danger">Scuttle</Button>
<Button variant="ghost">Cancel</Button>
<Button disabled>Disabled</Button>

Sizes

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

Props

PropTypeDefaultDescription
variant"default" | "primary" | "danger" | "ghost""default"Visual weight. Primary marks the one action you want taken.
size"sm" | "md" | "lg""md"Control height. Medium is 40px, matching inputs and selects.
blockbooleanfalseFill the container's width.
type"button" | "submit" | "reset""button"Defaults to button, not submit. A button inside a form that silently submits is the most common UI-kit footgun.

Guidance

Do
  • Label with the verb that happens: Publish, Delete, Send. The toast afterwards says Published.
  • Keep one primary button per view so the eye knows where to land.
Don't
  • Don't use a button for navigation — that's a Link, and it needs to be middle-clickable.
  • Don't disable a submit button to express a validation error; say what's wrong instead.

Accessibility

Renders a real <button>, so Enter and Space work with no extra wiring.

Focus shows the signal-coloured ring at 3px — a focus ring is a warning, and the system already has a colour that means that.

Disabled buttons are not focusable. If the reason isn't obvious on screen, explain it in nearby text.