A primary action with its alternatives folded beside it.
| Prop / event | Type | Notes |
|---|---|---|
| onClick | () => void | The default action, fired by the main button |
| options | { label, onSelect, danger? }[] | The alternatives behind the chevron |
| variant | primary · brand · ghost | Shared skin for both halves |
| size | S · M · L | Matches Button; M is the default |
| disabled | boolean | Locks main and toggle together |
| Esc · outside click · select | — | Each closes the menu |
Use a Split Button when one action dominates and a few siblings share its verb. If no action leads, use a plain Button beside a Menu instead.
Put the most common action on the main button; hide its variations.
Don't make the main button a placeholder. If nothing leads, use a Dropdown.
Keep the siblings in the same family — Publish, schedule, publish as draft.
Don't line up two warm split buttons. One leading action per view still holds.
Save leads; save-and-duplicate and save-as-template wait in the menu.
The one warm action, with schedule and draft folded beside it.
A quiet ghost split in a table row: export CSV, JSON or PDF.
| Token | Value | Role |
|---|---|---|
| --split-toggle-w | 34px | Chevron half width |
| --split-divider | 1px rgba(0,0,0,.16) | Seam between the halves |
| --split-menu-bg | #141519 | Menu panel |
| --split-menu-border | #262A30 | Menu hairline |
| --split-opt-hover | #1E1F25 | Row hover fill |
| --split-chevron | 180° · .2s | Toggle rotation when open |
<div class="o-split">
<button class="o-btn o-btn--m o-btn--primary o-split__main">Save</button>
<button class="o-btn o-btn--m o-btn--primary o-split__toggle"
aria-haspopup="menu" aria-expanded="false" aria-label="More save options">
<svg class="o-split__chevron">…</svg>
</button>
<div class="o-split__menu" role="menu" hidden>
<button role="menuitem" class="o-split__opt">Save and duplicate</button>
<button role="menuitem" class="o-split__opt">Save as template</button>
</div>
</div>