Lynx/Modules/Zero/ToggleGroup
@sigx/lynx-zero · Beta · Component library

ToggleGroup#

A row or column of two-state buttons under one value model, such as text alignment, a view switcher or a set of formatting marks. It works in single or multiple selection. On Lynx, each item is its own tap target and accessibility element.

The anatomy is zero's toggle-group scope, shared with the web. See Toggle Group in @sigx/zero for the contract. This page covers what is different on Lynx.

Import#

TSX
import { ToggleGroup } from '@sigx/lynx-zero';

ToggleGroup is a compound: ToggleGroup.Root and ToggleGroup.Item.

Usage#

Single selection#

By default one item is on at a time. The model is a string, and '' means no item is on. Tapping the item that is on turns it off, unless you pass deselectable={false}:

TSX
import { component } from '@sigx/lynx';
import { ToggleGroup } from '@sigx/lynx-zero';

export const Alignment = component(({ signal }) => {
    const state = signal({ align: 'left' });
    return () => (
        <ToggleGroup.Root model={() => state.align} deselectable={false} color="secondary">
            <ToggleGroup.Item value="left"><text>Left</text></ToggleGroup.Item>
            <ToggleGroup.Item value="center"><text>Center</text></ToggleGroup.Item>
            <ToggleGroup.Item value="right"><text>Right</text></ToggleGroup.Item>
        </ToggleGroup.Root>
    );
});

An item valued '' throws in single mode, because '' is reserved for "nothing pressed".

Multiple selection#

With multiple, the model is a string[] and each tap flips that item's value in or out of the list. The exported root is typed by overload, so a string model binds a single group and an array binds a multiple one:

TSX
<ToggleGroup.Root multiple defaultValue={['bold']} onValueChange={(v: string[]) => save(v)}>
    <ToggleGroup.Item value="bold" label="Bold"><text>B</text></ToggleGroup.Item>
    <ToggleGroup.Item value="italic" label="Italic"><text>I</text></ToggleGroup.Item>
    <ToggleGroup.Item value="underline" label="Underline"><text>U</text></ToggleGroup.Item>
</ToggleGroup.Root>

Orientation and state#

orientation (horizontal by default) and the root's color and size axes are stamped on every item. disabled on the root disables every item, and disabled on one item disables that item alone. invalid and required are flags on the root, used for paint and Field wiring. They are not constraints: Lynx has no constraint validation. The root ORs each of disabled, invalid and required with an enclosing Field's, and adopts the field's size when it sets none.

What the platform changes#

  • No roving focus. There is no keyboard on this platform. An item is activated by a tap, so zero's roving tab stop is not wired.
  • No group role. Lynx has no role="group", and marking the root as an accessibility element would hide its items from the reader on iOS. So the root carries no accessibility props. Each item is announced as a button, and as selected while it is on. Pass label for an icon-only item.
  • No hidden-input part. Lynx has no forms, so there is no value to post.
  • Press feedback per item. The touched item scales on the main thread and its pressed flag paints the skin's held state. pressFeel={false} on an item turns off the scale. See Press feedback.

The ends of the join (skin authors)#

Lynx CSS has no :first-child or :last-child. The root tracks its items in mount order and stamps the end items with the first and last modifiers: the zx-m-first and zx-m-last classes, plus data-mod-first and data-mod-last. A skin uses them to round the join's outer corners on the end items and to drop the first item's leading seam. A single item carries both.

An item mounted later, such as a conditional one, joins the end of that order, wherever it sits in the row.

Props#

ToggleGroup.Root#

PropTypeDefaultDescription
modelstring | string[]—Two-way binding of the pressed values. A string ('' for none) in single mode, a string[] under multiple.
defaultValuestring | string[]'' / []The initial value when there is no model.
multiplebooleanfalseAllow more than one item on at a time.
deselectablebooleantrueIn single mode, tapping the on item turns it off.
orientation'horizontal' | 'vertical''horizontal'Stamped on the root and every item.
disabledbooleanfalseDisables every item. ORed with an enclosing Field's.
invalid / requiredbooleanfalseRoot flags. ORed with an enclosing Field's.
color / sizestringskin defaultVariant axes, stamped on every item. size falls back to the Field's.
classstring—Extra classes.
EventPayloadDescription
valueChange (onValueChange)string | string[]The pressed values changed. Same shape as the model.

ToggleGroup.Item#

PropTypeDefaultDescription
valuestringrequiredThis item's value in the group's model. Must not be '' in single mode.
disabledbooleanfalseDisables this item.
pressFeelbooleantruefalse turns off the main-thread press scale. The pressed flag stays.
labelstring—Accessible name. Required for icon-only items.
classstring—Extra classes.

The item emits nothing. Changes are reported by the root's valueChange.

Anatomy on Lynx#

PartElementStatesFlagsModifiers
rootview—disabled, invalid, required—
itemview (button trait)on, offdisabled, selected, pressedfirst, last

focus-visible can only be forced for display, through ForceStates from @sigx/lynx-zero/testing.

See also#