Split button
A split button joins a default action to a caret that opens a menu of alternatives. The default runs in one click; the rest wait behind the caret.
<tk-split-button variant="primary" trigger-label="More merge options">
<tk-button slot="action">Merge pull request</tk-button>
<tk-menu slot="menu" label="Merge options">
<tk-menu-item>Squash and merge</tk-menu-item>
<tk-menu-item>Rebase and merge</tk-menu-item>
</tk-menu>
</tk-split-button>Anatomy
| Part | What it is |
|---|---|
tk-split-button |
the element; groups the two segments |
action slot |
the default action: a tk-button, on the left; its own Tab stop |
divider part |
the 1px line between the segments |
| caret | a chevron icon button the split button adds for you; its own Tab stop |
menu slot |
a tk-menu with items only; the caret opens it |
Composition
Put a tk-button in the action slot and a tk-menu with only its items in the menu
slot. Don't write a trigger: the split button adds the caret and wires it to the menu. It
passes variant, size, disabled, and loading to both segments, so set them on
tk-split-button, not on the parts.
Listen for click on the action button and on each tk-menu-item.
Variants
<tk-split-button variant="primary" trigger-label="More publish options"> <tk-button slot="action">Publish</tk-button> <tk-menu slot="menu" label="Publish options"><tk-menu-item>Schedule</tk-menu-item></tk-menu> </tk-split-button> <tk-split-button trigger-label="More export options"> <tk-button slot="action">Export</tk-button> <tk-menu slot="menu" label="Export options"><tk-menu-item>Export as PDF</tk-menu-item></tk-menu> </tk-split-button>
primary: the main action of a view. Use one per view.secondary(default): every other split button.
There is no ghost and no danger split button.
Shape
shape="round" gives the block pill ends. The seam between the segments stays square.
<tk-split-button shape="round" trigger-label="More save options"> <tk-button slot="action">Save</tk-button> <tk-menu slot="menu" label="Save options"><tk-menu-item>Save as copy</tk-menu-item></tk-menu> </tk-split-button>
Sizes
<tk-split-button size="small" trigger-label="More options"> <tk-button slot="action">Small</tk-button> <tk-menu slot="menu" label="Options"><tk-menu-item>Duplicate</tk-menu-item></tk-menu> </tk-split-button> <tk-split-button size="large" trigger-label="More options"> <tk-button slot="action">Large</tk-button> <tk-menu slot="menu" label="Options"><tk-menu-item>Duplicate</tk-menu-item></tk-menu> </tk-split-button>
small, medium (default), and large are 24, 32, and 36px tall, the same as
States
<tk-split-button disabled trigger-label="More publish options"> <tk-button slot="action">Publish</tk-button> <tk-menu slot="menu" label="Publish options"><tk-menu-item>Schedule</tk-menu-item></tk-menu> </tk-split-button> <tk-split-button variant="primary" loading trigger-label="More publish options"> <tk-button slot="action">Publish</tk-button> <tk-menu slot="menu" label="Publish options"><tk-menu-item>Schedule</tk-menu-item></tk-menu> </tk-split-button>
disabled: disables both segments.loading: the action shows a spinner and ignores repeat clicks; the caret is disabled until loading ends.
When to use
- Use a split button when one action clearly leads, a few alternatives exist, and space is tight.
- Use a
Menu with a labelled trigger when no action leads: the whole control opens the menu. - Use a
Button group or plainButtons when every action fits on screen. - Use a
Select to pick a value that stays chosen and is submitted. A split button runs commands. - Don't make a destructive action the default. Use a danger
Button with a confirmation, or put it last in the menu.
Content
- Action label: the most common action, written like any
Button label: a verb and the object, sentence case. - The menu holds the alternatives only. Don't repeat the default in it, and don't change the action label to the last item picked.
- One alternative is enough. With none, use a plain Button.
trigger-labelnames the caret's scope: "More merge options". The default is "More actions".- Menu items follow
Menu 's rules: a destructive item goes last, after a divider, and asks for confirmation.
Do / Don't
| ✅ Do | ❌ Don't |
|---|---|
| Use a split button when one action leads | Use one when the actions are equal; use a menu |
| Keep the leading action in the visible segment | Hide it in the menu or list it there again |
| Keep a destructive action in the menu, confirmed | Make it the one-click default |
Use tk-split-button for one joined block |
Place two separate buttons side by side |
Related
Button : the action segment.Menu : the caret's menu, and the choice when no action leads.Button group : several visible actions joined together.Select : picks a value instead of running a command.
API
Attributes
| Attribute | Type | Default | What it does |
|---|---|---|---|
variant |
primary | secondary |
secondary |
emphasis, passed to both segments |
size |
small | medium | large |
medium |
height 24 / 32 / 36px, passed to both segments |
shape |
rect | round |
rect |
rounded or pill outer corners; the seam stays square |
disabled |
boolean | false |
disables both segments |
loading |
boolean | false |
spinner in the action, caret disabled |
label |
string | unset | accessible name for the group |
trigger-label |
string | More actions |
accessible name for the caret |
Slots
| Slot | Content |
|---|---|
action |
one tk-button, the default action |
menu |
one tk-menu with items only, no trigger |
Events
No custom events. Listen for click on the action button and on the menu items.
CSS
::part(divider): the line between the segments.
Tokens
| Part | Token |
|---|---|
| segments | |
divider, secondary |
border/strong |
divider, primary |
text/accent/on-fill at 25% opacity |
| outer corners | radius-8; radius-full with shape="round" |
Accessibility
Built in:
- Two real buttons and two Tab stops: the action first, then the caret.
- The caret has
aria-haspopup="menu"andaria-expanded. - The segments sit in a
role="group";labelnames it. - The menu moves focus through its items and returns it to the caret on Escape.
Your part:
- Set a
trigger-labelthat names the caret's scope. - Set
labelwhen the group needs a name of its own.
| Key | Action |
|---|---|
Tab |
moves to the action, then to the caret |
Space / Enter |
activates the focused segment |
Down / Up |
on the caret, opens the menu |
Esc |
closes the menu and returns focus to the caret |