Components / Actions

SplitButton

A primary action with a menu of nearby alternatives.

Install

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

Preview

SplitButton

A primary action joined to a chevron that opens a menu of nearby alternatives, such as Publish with "Schedule for later".

When to use

  • One action is clearly the default, but a few close variants should stay one click away (publish now / schedule / publish to staging).
  • When the main label changes after a press ("Copy page" to "Copied"): shared letters stay put and only the changed ones morph.
  • For unrelated actions with no default, use DropdownMenu. For several equal-weight actions in a row, use ButtonGroup.

Usage

import { SplitButton } from "@/components/iris/split-button/split-button";

<SplitButton
  label="Publish"
  icon={<SendIcon size={16} />}
  onClick={publish}
  actions={[
    { label: "Schedule for 14:00", icon: <ClockIcon size={16} />, onSelect: schedule },
    { label: "Send back to review", onSelect: sendToReview },
    { label: "Discard draft", destructive: true, onSelect: discard },
  ]}
/>;

Props

Prop Type Default Description
label string — Main action label (required). Changing it morphs letter by letter.
actions SplitButtonAction[] — Menu items (required): { label, onSelect?, disabled?, destructive?, icon? }.
onClick () => void — Runs the main action.
icon ReactNode — Icon before the label; swapping to a different icon element crossfades it.
variant "primary" | "secondary" "primary" Filled or outlined surface.
disabled boolean — Disables both halves.

Notes

  • The menu is a Radix dropdown: it opens on press or Enter/Space/ArrowDown, loops with the arrow keys, closes on Escape, and returns focus to the chevron. The chevron is labelled "{label} more actions".
  • The main label is mirrored into a polite live region, so a morph such as "Copied" is announced.
  • The menu portals to <body>, aligns to the group's end edge with a 4px offset, and keeps 12px from the viewport edge.
  • The chevron half never scales on press, so the menu always anchors to a still trigger. Reduced motion turns the glyph morph into instant fades.