Components / Actions

Button

A clear, responsive action with quiet secondary states.

Install

npx shadcn@latest add https://irisui.dev/r/button.json
import { Button } from "@/components/iris/button/button";
Registry item buttonBrings in foundationRegistry JSON

Preview

Button

The core action control: seven variants, four sizes, a loading state that keeps focus, and a label that crossfades when it changes.

When to use

  • primary for the one main action of a view, secondary for alternatives, ghost and quiet for low-emphasis actions in dense rows, danger for destructive actions.
  • accent for the one AI-forward action ("Draft with Polaris"), success for approving.
  • When a label changes after a press ("Restore" to "Restored"): the width springs to the new label instead of snapping.
  • For an action that runs async work and confirms itself, use ActionButton; for a main action with a menu of alternatives, use SplitButton; for copying a value, use CopyButton.

Usage

import { Button } from "@/components/iris/button/button";
function DeleteBar({ deleting, onDelete }) {
  return h(
    "div",
    { style: { display: "flex", gap: 8 } },
    h(Button, { variant: "ghost" }, "Cancel"),
    h(Button, { variant: "danger", loading: deleting, onClick: onDelete }, "Delete project"),
  );
}

Props

Prop Type Default Description
variant "primary" | "secondary" | "ghost" | "quiet" | "accent" | "success" | "danger" "primary" Visual weight. primary is ink-filled, secondary outlined on the surface, ghost and quiet transparent until hovered, accent and success coloured fills, danger outlined with a red label.
size "xs" | "sm" | "md" | "lg" "md" Height 28 / 32 / 36 / 40px; xs also uses smaller type.
loading boolean false Shows a spinner over the label, sets aria-busy, and swallows clicks while keeping focus.
disabled boolean – Native disabled. Outlined variants keep their shape and fade only the label.
children ReactNode – Label text and/or inline SVG icons. An icon-only child is treated as an icon for the morph, and the button becomes a circle as wide as its height. Give it an aria-label.
...props ButtonHTMLAttributes – Any native button attribute (type, onClick, aria-*). The ref is forwarded to the <button>.

Notes

  • Loading uses aria-disabled rather than disabled, so a keyboard user keeps focus through an async action; it also announces as busy.
  • Icon-only buttons need an aria-label. Set type="button" inside forms.
  • Press scale is driven by Motion and is skipped for reduced motion, while loading or disabled, and for buttons that anchor a popup (aria-haspopup, data-state, role="combobox"), so menus never measure a shrunken trigger.
  • Reads --ink, --page, --surface, --hover, --line, --accent, --green, --red, --radius-button and the control heights.