Skip to content
omaris

Actions

Button

MD3 buttons, the Expressive way.

import { Button } from 'omaris'
Learn

Examples

Variants

The five MD3 fill styles, in the spec's own order of emphasis, plus link.

<script lang="ts">	import { Button } from 'omaris';</script>​<Button variant="elevated">Elevated</Button><Button variant="filled">Filled</Button><Button variant="tonal">Tonal</Button><Button variant="outlined">Outlined</Button><Button variant="text">Text</Button><Button variant="link">Link</Button>

Tones

tone is the colour role. Every tone works with every fill style.

<script lang="ts">	import { Button } from 'omaris';</script>​<div class="flex flex-col gap-3">	<div class="flex flex-wrap items-center gap-2">		<Button variant="filled" tone="primary" size="xs">primary</Button>		<Button variant="filled" tone="secondary" size="xs">secondary</Button>		<Button variant="filled" tone="tertiary" size="xs">tertiary</Button>		<Button variant="filled" tone="destructive" size="xs">destructive</Button>		<Button variant="filled" tone="success" size="xs">success</Button>		<Button variant="filled" tone="warning" size="xs">warning</Button>		<Button variant="filled" tone="info" size="xs">info</Button>	</div>	<div class="flex flex-wrap items-center gap-2">		<Button variant="tonal" tone="primary" size="xs">primary</Button>		<Button variant="tonal" tone="secondary" size="xs">secondary</Button>		<Button variant="tonal" tone="tertiary" size="xs">tertiary</Button>		<Button variant="tonal" tone="destructive" size="xs">destructive</Button>		<Button variant="tonal" tone="success" size="xs">success</Button>		<Button variant="tonal" tone="warning" size="xs">warning</Button>		<Button variant="tonal" tone="info" size="xs">info</Button>	</div>	<div class="flex flex-wrap items-center gap-2">		<Button variant="outlined" tone="primary" size="xs">primary</Button>		<Button variant="outlined" tone="secondary" size="xs">secondary</Button>		<Button variant="outlined" tone="tertiary" size="xs">tertiary</Button>		<Button variant="outlined" tone="destructive" size="xs">destructive</Button>		<Button variant="outlined" tone="success" size="xs">success</Button>		<Button variant="outlined" tone="warning" size="xs">warning</Button>		<Button variant="outlined" tone="info" size="xs">info</Button>	</div></div>

Sizes

MD3 Expressive's five heights: 32 / 40 / 56 / 96 / 136dp.

<script lang="ts">	import { Button } from 'omaris';</script>​<Button size="xs">Extra small</Button><Button size="sm">Small</Button><Button size="md">Medium</Button>

With icons

Hand it an <svg>; the button sets the size and the colour.

<script lang="ts">	import { Button, IconButton } from 'omaris';</script>​{#snippet plus()}	...{/snippet}​<Button>{@render plus()}New invoice</Button><Button variant="tonal" size="md">{@render plus()}Bigger</Button><IconButton aria-label="New invoice">{@render plus()}</IconButton>

Loading

The spinner grows in from zero width with a negative margin that cancels the gap, so an idle button measures as if it had no spinner and nothing jumps when one appears.

<script lang="ts">	import { Button } from 'omaris';​	let busy = $state(false);​	function save() {		busy = true;		setTimeout(() => (busy = false), 2000);	}</script>​<Button loading={busy} onclick={save}>Save changes</Button><Button variant="tonal" loading>Always loading</Button>

Toggle

A toggle drops to a neutral surface when off and takes its tone when on.

<script lang="ts">	import { Button } from 'omaris';​	let starred = $state(false);	let muted = $state(true);</script>​<Button toggle bind:pressed={starred}>{starred ? 'Starred' : 'Star'}</Button><Button toggle bind:pressed={muted} variant="outlined" tone="tertiary">	{muted ? 'Muted' : 'Mute'}</Button>

Overridden

class is merged last, so a utility beats the component's own — including the height and the pill radius that size and shape set.

<script lang="ts">	import { Button } from 'omaris';</script>​<Button class="h-12 rounded-none px-8">Squared and taller</Button><Button variant="tonal" class="w-full max-w-56 justify-between">	Full width<span aria-hidden="true">→</span></Button>

When to use it

Use it for

  • The main action on a screen or dialog. Use filled, once per view.
  • The actions next to it. tonal for the second most important, outlined or text for the rest.
  • An action that takes a moment. Pass loading; the label stays and a spinner appears.

Not for

  • A link that only changes the URL → give it href and it renders an <a>. variant="link" is for a link inside a sentence.
  • An icon with no label → Icon Button.
  • The floating main action on a phone → FAB.
  • One action plus a menu of alternatives → Split Button.
  • Picking between options → Segmented Button or filter Chips.

Do

  • Keep one filled button per view. Everything else is tonal, outlined or text.
  • Write labels in sentence case, verb first: "Save changes", not "SAVE" or "OK".
  • Give destructive actions tone="destructive" and confirm them in a Dialog.

Don't

  • Wrap a label onto two lines, or put two icons in one button.
  • Disable a button to explain why it cannot be pressed. Keep it enabled and say why in the supporting text or a toast.
  • Use size="lg" or xl in a dashboard. They are for landing screens.

Quick reference

tone
  • primary (default)
  • secondary
  • tertiary
  • destructive
  • success
  • warning
  • info
variant
  • filled (default)
  • tonal
  • elevated
  • outlined
  • text
  • link
size
  • xs
  • sm (default)
  • md
  • lg
  • xl

MD3 Expressive's five heights: 32 / 40 / 56 / 96 / 136dp. sm is the classic Material button and stays the default.

shape
  • round (default)
  • square

A pill, or MD3's rounded-rectangle. Fixed — it never morphs.

API

Button

MD3 buttons, the Expressive way.

Two axes instead of one long variant list: variant is the fill style (elevated / filled / tonal / outlined / text) and tone is the color role (primary / secondary / … / destructive), which resolves to the --btn-* custom properties in tones.ts. Every fill style works with every tone, with no combinatorial explosion of classes.

import { Button } from 'omaris'

Props

variant

Defaults to 'filled'

ButtonVariant

Fill style. MD3's five, plus link for inline navigation.

filled
tonal
elevated
outlined
text
link
tone

Defaults to 'primary'

ButtonTone

Color role the fill style paints with.

primary
secondary
tertiary
destructive
success
warning
info
size

Defaults to 'sm'

ButtonSize

MD3 Expressive heights: 32 / 40 / 56 / 96 / 136dp.

xs
sm
md
lg
xl
shape

Defaults to 'round'

ButtonShape

Pill (round) or MD3 rounded rectangle (square).

round
square
icon

Defaults to false

boolean

Square, label-less button. Requires an aria-label.

ripple

Defaults to true

boolean

Material ripple on press. Set false for a flat, instant button.

confetti

Defaults to false

boolean | ConfettiOptions

Confetti on press. true for the default burst, or any ConfettiOptions — confetti={{ preset: 'fireworks' }}.

loading

Defaults to false

boolean

Grows a spinner in at the start of the button and blocks interaction. The label stays put; only an icon button swaps its icon out.

toggle

Defaults to false

boolean

Turns the button into a two-state toggle driven by pressed. Ignored when href is set — a link has no pressed state.

pressed bindable

Defaults to false

boolean

Selected state of a toggle button. Bindable.

class
string
children
Snippet