Toggle button

A toggle button is on or off, and says so with aria-pressed. Bold in a text editor, a filter that is applied, a panel that is showing.

There is no hidden input behind it: aria-pressed is the whole state, so a server-rendered toggle shows a setting and setPressed() is what changes it. Reach for checkbox() when it belongs in a form and toggle() — the switch — when it is a setting in a list.

Basic toggle

stack({ direction: 'row', gap: 'sm' },
  toggleButton({ pressed: true }, 'Bold'),
  toggleButton('Italic'),
  toggleButton('Underline'),
)

Variants

stack({ gap: 'md' },
  stack({ direction: 'row', gap: 'sm' },
    toggleButton({ variant: 'outline', pressed: true }, 'Outline on'),
    toggleButton({ variant: 'outline' }, 'Outline off'),
  ),
  stack({ direction: 'row', gap: 'sm' },
    toggleButton({ variant: 'ghost', pressed: true }, 'Ghost on'),
    toggleButton({ variant: 'ghost' }, 'Ghost off'),
  ),
  stack({ direction: 'row', gap: 'sm' },
    toggleButton({ variant: 'soft', pressed: true }, 'Soft on'),
    toggleButton({ variant: 'soft' }, 'Soft off'),
  ),
)

Sizes

stack({ direction: 'row', gap: 'sm', align: 'center' },
  toggleButton({ size: 'sm', pressed: true }, 'Small'),
  toggleButton({ size: 'md', pressed: true }, 'Medium'),
  toggleButton({ size: 'lg', pressed: true }, 'Large'),
)

With icons

An icon-only toggle needs an accessible name — pass aria-label, which falls through to the button.

stack({ direction: 'row', gap: 'sm' },
  toggleButton({
    pressed: true,
    'aria-label': 'Bold',
    title: 'Bold',
    startIcon: icon('bold'),
  }),
  toggleButton({
    'aria-label': 'Italic',
    title: 'Italic',
    startIcon: icon('italic'),
  }),
)

Disabled

stack({ direction: 'row', gap: 'sm' },
  toggleButton({ pressed: true, disabled: true }, 'On, locked'),
  toggleButton({ disabled: true }, 'Off, locked'),
)

Making it do something

One call flips the attribute; the styling follows it. Inside a single-choice toggleGroup() it lets go of the siblings too.

toggleButton({ onclick: "import('/su/pressed.js').then(m=>m.set(this))" }, 'Bold')

Or from your own module, when there is already one running:

import { setPressed } from 'sitelo/ui/client'

setPressed('bold')

Props

PropTypeDefaultDescription
pressedbooleanfalseSets aria-pressed. setPressed() changes it afterwards.
variant'outline' | 'ghost' | 'soft''outline'How the unpressed button looks.
size'sm' | 'md' | 'lg''md'Same scale as button().
disabledbooleanfalseDisables the button.

Everything else falls through to button() — startIcon, endIcon, onclick and the rest. For a set of them, see toggleGroup().