UnflowUI
Components

SplitButton

A compound action button combining a primary action (left) with a dropdown of secondary actions (right chevron). Useful when one action is clearly primary but alternatives must remain accessible.

Overview

SplitButton renders [Button | divider | IconButton] — three DOM nodes inside a single visual unit. The divider is a border-r CSS rule, not a separate DOM element. The IconButton (chevron) toggles an ActionsDropdown portal.

Control open/close state externally via open, onSplitClick, and onDropdownClickAway — SplitButton is uncontrolled by default, so you manage the open state.

Import

import { SplitButton } from '@unflow/ui/components/SplitButton';

Props

PropTypeDefaultDescription
labelstringRequired. Primary button label
variant'primary' | 'secondary' | 'tertiary' | 'destructive' | 'destructiveSecondary' | 'social''primary'Visual variant
size'xs' | 'sm' | 'md' | 'lg''sm'Button size
openbooleanfalseWhether the dropdown is open
itemsActionsDropdownItem[]Dropdown action items
onButtonClickMouseEventHandlerHandler for the primary button
onSplitClickMouseEventHandlerHandler for the chevron (toggle)
onDropdownClickAway() => voidCalled when clicking outside the dropdown
loadingbooleanfalseLoading state
disabledbooleanfalseDisables both segments
fullWidthbooleanfalseFull-width layout

Default

const [open, setOpen] = useState(false);

const items = [
  { label: 'Save as draft', onClick: () => save('draft') },
  { label: 'Save and publish', onClick: () => save('publish'), groupIndex: 1 },
  { label: 'Save and schedule', onClick: () => save('schedule') },
];

<SplitButton
  label="Save"
  open={open}
  items={items}
  onButtonClick={() => save('default')}
  onSplitClick={() => setOpen((v) => !v)}
  onDropdownClickAway={() => setOpen(false)}
/>

Variants

<SplitButton label="Primary" variant="primary" ... />
<SplitButton label="Secondary" variant="secondary" ... />

items is an array of ActionsDropdownItem which extends IActionCard. The groupIndex property on consecutive items creates a separator in the dropdown when the index changes between adjacent items.

const items: ActionsDropdownItem[] = [
  { label: 'Save as draft', onClick: handleDraft },
  { label: 'Save and publish', onClick: handlePublish, groupIndex: 1 }, // separator before this
  { label: 'Discard changes', onClick: handleDiscard, groupIndex: 1 },
];

Customization (slotProps)

SlotPropsDescription
buttonPartial<IButton>Override props on the left Button segment
splitPartial<IIconButton>Override props on the right chevron IconButton
actionsDropdownOmit<IActionsDropdown, 'open' | 'anchorEl' | ...>Override the dropdown
loadingButtonLoadingSlotPropsLoading state config

Accessibility

  • The left Button and right IconButton are separately focusable and keyboard-operable.
  • Always provide aria-label on the right segment via slotProps.split if the chevron purpose isn't obvious: slotProps={{ split: { 'aria-label': 'More save options' } }}.
  • The ActionsDropdown follows WAI-ARIA menu pattern internally.