Skip to content
omaris

Actions

Icon Button

MD3 icon button. Same tone system as Button, but its own geometry: height comes from size, width from width as a ratio of that height (MD3's narrow / default / wide, which are ~0.8× / 1× / 1.3×).

import { IconButton } from 'omaris'
Learn

Examples

Variants

standard has no fill until touched, right for a toolbar; filled marks the one that matters. aria-label is required.

<script lang="ts">	import { IconButton } from 'omaris';</script>​{#snippet star()}	...{/snippet}​<IconButton variant="standard" aria-label="standard">{@render star()}</IconButton><IconButton variant="filled" aria-label="filled">{@render star()}</IconButton><IconButton variant="tonal" aria-label="tonal">{@render star()}</IconButton><IconButton variant="elevated" aria-label="elevated">{@render star()}</IconButton><IconButton variant="outlined" aria-label="outlined">{@render star()}</IconButton>

Size and width

Height from size, width from width — narrow, default, wide. xs for a dense table row, sm where a thumb lands, wide to anchor a row.

<script lang="ts">	import { IconButton } from 'omaris';</script>​{#snippet plus()}	...{/snippet}​<IconButton size="xs" variant="tonal" aria-label="Add">{@render plus()}</IconButton><IconButton size="sm" variant="tonal" aria-label="Add">{@render plus()}</IconButton><IconButton size="md" variant="tonal" aria-label="Add">{@render plus()}</IconButton><IconButton width="narrow" variant="outlined" aria-label="Add, narrow">{@render plus()}</IconButton><IconButton width="default" variant="outlined" aria-label="Add, default"	>{@render plus()}</IconButton><IconButton width="wide" variant="outlined" aria-label="Add, wide">{@render plus()}</IconButton><IconButton shape="square" variant="filled" aria-label="Add">{@render plus()}</IconButton>

Toggle

A toggle is an action that stays on — favourite, mute. selectedIcon swaps the glyph, so an outline star fills in.

<script lang="ts">	import { IconButton } from 'omaris';​	let starred = $state(false);</script>​<IconButton	toggle	bind:pressed={starred}	variant="tonal"	aria-label={starred ? 'Remove star' : 'Add star'}>	<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8">		<path			d="m12 4 2.4 5 5.6.8-4 3.9 1 5.5-5-2.7-5 2.7 1-5.5-4-3.9 5.6-.8z"			stroke-linejoin="round"		/>	</svg>	{#snippet selectedIcon()}		...	{/snippet}</IconButton>

When to use it

Use it for

  • An action whose icon everyone reads: close, search, more, edit, delete. In a Top App Bar, a toolbar, a table row or a card corner.
  • An on/off that is an action, not a setting: favourite, bookmark, mute, play/pause. Use toggle with bind:pressed, and selectedIcon so the outline fills in when on.
  • A row of them in a connected Button Group, like a text-editor toolbar.
  • MD3 Expressive rhythm: one width="wide" shape="square" filled button anchoring a row of standard ones.

Not for

  • Anything without a universal icon → a Button with a label. A Tooltip names an icon; it does not make it obvious.
  • The screen's one floating action → FAB.
  • An on/off that saves a preference → Switch. A pressed icon button means "doing this now", not "this is how it is set".
  • One of two to five options → Segmented Button.
  • A set of destinations → Navigation Bar. href on a single icon button, like a back arrow, is fine.

Do

  • Pass aria-label with the verb in it: "Delete row", not "Trash". The prop is required; the type refuses without it.
  • Wrap it in a Tooltip with the same words, so pointer users get the name too.
  • Keep standard (no fill until touched) as the default. Use filled or tonal for the one action in a row that matters, outlined when it needs a boundary on a busy surface.
  • Stay at size="sm" (40dp) where a thumb lands. xs (32dp) only in a dense table row; md and up for a hero control.

Don't

  • Put text inside. An icon button is a square; if it needs a label it is a Button.
  • Set toggle on something that opens a Menu or navigates. A toggle reports aria-pressed; a trigger does not stay pressed.
  • Make every button in a row filled. The emphasis is lost.

Quick reference

tone
  • primary (default)
  • secondary
  • tertiary
  • destructive
  • success
  • warning
  • info
variant
  • filled
  • tonal
  • elevated
  • outlined
  • standard (default)
size
  • xs
  • sm (default)
  • md
  • lg
  • xl
width
  • narrow
  • default (default)
  • wide
shape
  • round (default)
  • square

API

IconButton

MD3 icon button. Same tone system as Button, but its own geometry: height comes from size, width from width as a ratio of that height (MD3's narrow / default / wide, which are ~0.8× / 1× / 1.3×).

import { IconButton } from 'omaris'

Props

variant

Defaults to 'standard'

IconButtonVariant
filled
tonal
elevated
outlined
standard
The default: no container until you touch it.
tone

Defaults to 'primary'

IconButtonTone
primary
secondary
tertiary
destructive
success
warning
info
size

Defaults to 'sm'

IconButtonSize
xs
sm
md
lg
xl
width

Defaults to 'default'

IconButtonWidth

Horizontal weight relative to the height — MD3's three densities.

narrow
default
wide
shape

Defaults to 'round'

IconButtonShape
round
square
ripple

Defaults to true

boolean
confetti

Defaults to false

boolean | ConfettiOptions

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

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.

selectedIcon
Snippet

Icon shown while pressed. Lets a toggle swap outline for solid, the way Material's own icons do.

aria-label required
string

Required — an icon alone carries no accessible name.

class
string
children
Snippet
icon
boolean

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

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