Skip to content
omaris

Actions

Split Button

MD3 Expressive split button.

import { SplitButton } from 'omaris'
Learn

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), loading while 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 menu with MenuItems and give menuLabel a real name — "More save options" — since that half is an icon-only button.
  • Match variant, tone and size to the Buttons beside it; both halves share them, so it never looks like a guest.
  • Use loading for 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 filled primary. Give it its own tone="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, tonal and outlined show 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 bindable

Defaults 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.