Actions
Split Button
MD3 Expressive split button.
import { SplitButton } from 'omaris' Examples
Basic
A wide half that does the obvious thing, and a narrow half that offers the rest — with a hairline gap between them, the same shape language as ButtonGroup's connected ends.
<script lang="ts"> import { MenuItem, SplitButton, toast } from 'omaris';</script><SplitButton label="Save" onclick={() => toast.success('Saved')}> {#snippet menu()} <MenuItem>Save as a copy…</MenuItem> <MenuItem>Save as template</MenuItem> {/snippet}</SplitButton><SplitButton label="Deploy" variant="tonal" tone="tertiary"> {#snippet menu()} <MenuItem>Deploy to staging</MenuItem> <MenuItem tone="destructive">Roll back</MenuItem> {/snippet}</SplitButton> Sizes icons and loading
Both halves share variant, tone and size with Button, so a split button never looks like a guest among them. loading disables the pair and spins the main half; icon is the leading slot on that half.
<script lang="ts"> import { MenuItem, SplitButton, toast } from 'omaris'; let publishing = $state(false); async function publish() { publishing = true; await new Promise((resolve) => setTimeout(resolve, 1400)); publishing = false; toast.success('Published'); }</script>{#snippet uploadIcon()} ...{/snippet}<SplitButton label="Publish" size="xs" loading={publishing} onclick={publish} icon={uploadIcon}> {#snippet menu()} <MenuItem>Schedule…</MenuItem> <MenuItem>Save as draft</MenuItem> {/snippet}</SplitButton><SplitButton label="Export" variant="outlined" size="sm"> {#snippet menu()} <MenuItem>Export as CSV</MenuItem> <MenuItem>Export as JSON</MenuItem> {/snippet}</SplitButton><SplitButton label="Invite" variant="elevated" tone="secondary" size="md" align="end"> {#snippet menu()} <MenuItem>Invite by email</MenuItem> <MenuItem>Copy invite link</MenuItem> {/snippet}</SplitButton> When to use it
Use it for
- One obvious default with variants behind it: Save / Save as, Save and close; Export CSV / PDF, XLSX; Merge / Squash, Rebase.
- A set of related commands that would otherwise be three buttons — the default stays one press away, the rest one more.
- The primary action of a dashboard header:
variant="filled",size="sm"(the defaults),loadingwhile it runs.
Not for
- A menu with no default — "Actions", "More" → a Button or Icon Button as the trigger of a Menu.
- A choice that stays chosen → Segmented Button or Select. The menu here holds commands, not state.
- Two actions of equal weight → two buttons in a Button Group.
- A card's whole action set → a Menu behind a "more" icon button. A split button with six items is a menu with a hat on.
Do
- Make the wide half the thing pressed nine times in ten, and repeat it in the menu so the list is complete on its own.
- Fill
menuwithMenuItems and givemenuLabela real name — "More save options" — since that half is an icon-only button. - Match
variant,toneandsizeto the Buttons beside it; both halves share them, so it never looks like a guest. - Use
loadingfor the whole control; it disables the menu half too, so the list cannot open mid-save.
Don't
- Bury Delete in the menu under a
filledprimary. Give it its owntone="destructive"button and a Dialog. - Rename the wide half to whatever was picked last; the default should stay predictable.
- Use
variant="text"; without a fill or a border the seam between the halves disappears.filled,tonalandoutlinedshow it.
API
SplitButton
MD3 Expressive split button.
One button doing two jobs: the wide half runs the default action, the narrow half opens the rest. Both halves share a fill and tone, and the chevron rotates while the menu is open — the MD3 Expressive detail that tells you which half you just pressed.
import { SplitButton } from 'omaris' Parts
Every element this renders is reachable from outside. Pass Tailwind for one part as classes={{ part: '…' }}; class covers the root and is merged last, so it always wins.
action- The wide half that runs the default action.
trigger- The narrow half that opens the menu.
chevron- No description in the source yet.
Props
label string Label of the main action.
variant Defaults to 'filled'
ButtonVariant tone Defaults to 'primary'
ButtonTone size Defaults to 'sm'
ButtonSize disabled Defaults to false
boolean loading Defaults to false
boolean open bindableDefaults to false
boolean Menu open state. Bindable.
side Defaults to 'bottom'
AnchorSide align Defaults to 'end'
AnchorAlign menuLabel Defaults to 'More actions'
string Accessible name for the half that opens the menu.
onclick (event: MouseEvent) => void The default action.
class string classes SplitButtonClasses Per-part Tailwind overrides. class still covers the root.
icon Snippet Leading icon on the main half.
children Snippet Rich label, in place of label.
menu Snippet The menu's items.