Skip to content
ArcadiaDesign

TSX

One pill, two parts. The main part names the best move and runs it; the chevron opens the menu of every other move, the best one first. A 1px divider in the border's ink keeps them apart, each part hovers and presses on its own, and each takes its own focus ring. A hint shows the key that runs the main part from elsewhere.

The main part's label is whole or gone, never faded. With less room than the split needs, the chevron stands alone, labelled menuLabel, and the menu still opens from it: Continue on where the split said Continue on Large model. collapse="menu" keeps that form for a move that has no single best choice, several items at once.

Examples

Variants

The four Button variants a split takes. Both parts share the variant; primary draws its divider in the label's ink.

Collapse

Drag to narrow the room. The split measures the width it needs and stands the chevron alone below it, before it paints, so nothing jumps.

Several items

Moving a group has no single best move: collapse="menu" shows the menu alone at any width.

Busy

Press the main part. While busy, it keeps its label and its width, the spinner takes the chevron's place, and both parts ignore presses while keeping focus.

Holding still

The best move changes as plans are used.

88% left

While the pointer is on the control or its menu is open, the label and the action it runs hold still; the change lands once the pointer leaves.

Variant and state
Size and kind

rootStyle takes where the split sits: margins, self-alignment, flex and grid placement and size bounds. Its look is the Button variant it takes.

TSX

Two native <button>s in reading order. The main part is named by its label; the chevron by menuLabel, with aria-haspopup and aria-expanded, and focus moves into the menu and back. Standing alone, the chevron is one button named by the label it shows.

A hint is drawn only and becomes aria-keyshortcuts on the main part; binding the key is yours. busy sets aria-busy on the main part and blocks both parts without dropping focus.

EnterSpace
On the main part, run its move
EnterSpace↓
On the chevron, open the menu
Esc
Close the menu and return focus

SplitButton

onClick
(e: MouseEvent<HTMLButtonElement>) => void
menuLabelrequired
string
The chevron's accessible name, and its label standing alone.
menurequired
ReactNode
The MenuContent the chevron opens.
variant
"primary" | "secondary" | "ghost" | "text"Default "secondary"
size
"xs" | "sm"Default "sm"
hint
ShortcutSpec | ReactElement
A key hint on the main part.
collapse
"auto" | "menu"Default "auto"
auto: the chevron stands alone when the split doesn't fit. menu: always.
busy
booleanDefault false
The main part keeps its width, a spinner takes the chevron's place, both parts are inert.
disabled
booleanDefault false
hold
booleanDefault true
The label and its action hold while the pointer is on the control or the menu is open.
open
boolean
defaultOpen
booleanDefault false
onOpenChange
(open: boolean, details: OpenChangeDetails) => void
rootStyle
RootStyle
A component's typed override prop: Layout plus the knobs it documents. Knobs maps each knob to the references it takes ({ "--button-px": Ref<Space> }), so a literal colour, a wrong-kind token or a property the component doesn't expose is a type error at the call site. A knob also takes another kit knob of the same kind ("--icon-size": "var(--button-icon)").
childrenrequired
ReactNode
The main part's label: whole or gone, never faded.

Rest props go to <span> props.