Toggle group

A set of Toggles with one shared selection, single or multiple, and one tab stop.

<tp-toggle-group>
Toggle group
Default density Compact density Restart from the initial state Show the copyable source
List Board Timeline

Usage

Put tp-toggle elements with unique values inside the group. The selection is always an ordered list of values, in both modes, so default-value takes a JSON array. Give the group a label; it is one tab stop and arrow keys move between items without selecting.

A scalar attribute value is treated as one identifier; it is never split on spaces. Use properties or JSON arrays for lists.

In multiple mode, membership is ordered by registered items and retains unmatched selected values. In a standalone Group, arrow keys follow orientation/direction and skip disabled members; Home/End move to boundary items. Action controls never submit a value or reset on native form reset; consumer-owned form participation must be explicit.

Multiple selection

multiple lets each item toggle independently, as in a formatting toolbar. Icon-only items need an aria-label, and an icon-* size on the group makes them square. An explicitly supplied Icon size remains authoritative.

Text formatting
Default density Compact density Restart from the initial state Show the copyable source

Spacing

spacing is the gap in spacing units (default 2). Zero joins the items into one segmented control with shared seams.

Joined
Default density Compact density Restart from the initial state Show the copyable source
7 days 30 days 90 days 12 months

Orientation and size

The group’s size and variant override the items’ own. size takes the Button’s set: xs, sm, the default and lg for text, and the square icon-xs, icon-sm, icon and icon-lg for icon-only items. orientation="vertical" stacks the items and switches arrow navigation to Up and Down.

The host sizes to its members. An inline size set on the host (for example inline-size: 100% to span a column or a grid cell) is the group’s own size: the toggle-group part fills the host, vertical members stretch across it, and a grid set on the part through partPresentation lays its tiles out over the full width.

Vertical, small
Default density Compact density Restart from the initial state Show the copyable source
All messages Unread Mentions Starred

Icons with labels

An item can pair an Icon with its text. With visible text the item needs no aria-label, and data-icon="inline-start" tightens the padding beside the icon.

View switcher
Default density Compact density Restart from the initial state Show the copyable source
List Board Calendar

Rich items

Items can hold more than a word, such as a sample above its name. Reshape an item through its partContracts: here styleHook stacks the content and gives each item its own weight. A Field names the group, and its description reports the selection.

Font weight
Default density Compact density Restart from the initial state Show the copyable source
Light Regular Medium Bold Headings use Medium

Keeping one selected

In single mode, pressing the selected item clears the selection. When an empty selection makes no sense, cancel that proposal in tp-value-change.

Required choice
Default density Compact density Restart from the initial state Show the copyable source
Monthly Yearly $96 per seat, billed yearly

Disabled

Disabled items
Default density Compact density Restart from the initial state Show the copyable source
CSV Excel PDF

Arrow navigation skips disabled items. disabled on the group disables every item while keeping each item’s own setting for later.

Inside a Toolbar

A Toggle group placed inside a ToolbarController root becomes one of its groups by itself; it needs no registration call. Its toggle-group part is registered as the toolbar group and keeps role="group" and the group’s label, and its Toggles join the toolbar’s single arrow-key sequence in order. The group then has no tab stop or arrow-key handling of its own: the toolbar’s orientation, loopFocus and Home/End apply, while the group’s orientation still lays out its Toggles. Selection mode, values and tp-value-change are unchanged. A disabled Toggle, or every Toggle of a disabled group, stays a focusable toolbar stop that does not activate; a Toggle excluded for a missing or duplicate value is skipped.

Do not register the group’s host, its part or its Toggles with the toolbar yourself; a Toggle that is already registered keeps that registration, and the group reports a tp-diagnostic. A group added to the toolbar later, or present before the toolbar is created, joins it once; a group removed from the toolbar, or a disposed toolbar, restores the standalone tab stop and arrow keys. A Toggle group inside a popup or dialog placed within the toolbar stays independent.

<div id="view-tools" aria-label="View"> <tp-button id="fit">Fit</tp-button> <tp-toggle-group label="Layout" default-value='["single"]'> <tp-toggle value="single">Single</tp-toggle> <tp-toggle value="spread">Spread</tp-toggle> </tp-toggle-group> </div>
import { ToolbarController } from '@tweakpad/ui'; import '@tweakpad/ui/register'; await customElements.whenDefined('tp-button'); const toolbar = new ToolbarController(document.getElementById('view-tools')!); toolbar.registerItem(document.getElementById('fit')!, { kind: 'button' }); // The Layout group registers itself and its Toggles.

API Reference

Every element also accepts motion-policy.

Attributes

AttributePropertyTypeDefaultDescriptiondefault-valuedefaultValuereadonly string[] | undefined—The pressed values at first render, as a JSON array in the attribute, when the page does not own value.multiplemultipleboolean—Lets each Toggle be pressed independently; otherwise pressing one releases the others.selection-modeselectionMode'single' | 'multiple'—The same choice as multiple, as a word: single or multiple.loop-focusloopFocusbooleantrueWhether the arrow keys wrap from the last Toggle to the first and back.variantvariant'ghost' | 'outline''ghost'The paint of every Toggle in the group, overriding their own.sizesizeToggleSize'default'The size of every Toggle in the group, overriding their own; the icon-* sizes make square Toggles for Icons alone.spacingspacingnumber2The gap between the Toggles in spacing units; 0 joins them into one segmented control with shared seams.labellabelstring''The accessible name of the group when no Field names it.

Properties

PropertyTypeDefaultDescriptiononValueChange((event: TpValueChangeEvent<readonly string[]>) => void) | undefined—Called with each proposed selection before it commits; assign value to accept it or cancel the event to reject it.

Events

EventTypeDescriptiontp-value-changeTpValueChangeEvent<readonly string[]>Cancelable proposal of a new selection before it commits; detail.value is the list of pressed values, with detail.previousValue and the detail.reason.

Methods

MethodReturnsDescriptionisPressed(member)booleanWhether the given Toggle's value is in the selection; Toggles call it to render their state.isDisabled(member)booleanWhether the group disables the given Toggle.tabStop(member)numberThe tab index of the given Toggle: 0 for the one the group's tab stop lands on, -1 for the rest.memberChanged()voidRe-reads the Toggles after one is added, removed or changes its value or disabled state.requestToggle(member, pressed, source)voidProposes pressing or releasing the given Toggle; Toggles call it when pressed.setValue(value, reason, source?)voidProposes a new selection as if the user had made it, notifying listeners first; single mode keeps only the first value.

Slots

SlotDescriptiondefaultThe Toggles, each with a unique value.

CSS parts

PartDescription::part(toggle-group)The element with the group role that holds the Toggles.

<tp-toggle>

Attributes

AttributePropertyTypeDefaultDescriptionpressedpressedboolean—Whether the Toggle is pressed. Set it to own the state: presses then propose changes and the Toggle shows only what you assign.default-presseddefaultPressedboolean | undefined—The pressed state at first render, when the page does not own pressed.aria-labelariaLabelstring | null—The accessible name of a Toggle that shows only an Icon.native-actionnativeActionbooleantrueRenders the control as a native button; turn it off only when a part contract supplies another element.variantvariant'ghost' | 'outline'—The paint: ghost shows a fill only while pressed or hovered, outline adds a border for a Toggle that stands alone.sizesizeToggleSize—The height and padding, matching the Button sizes; the icon-* sizes make a square Toggle for an Icon alone.

Properties

PropertyTypeDefaultDescriptiononPressedChange((event: TpValueChangeEvent<boolean>) => void) | undefined—Called with each proposed state before it commits; assign pressed to accept it or cancel the event to reject it.selectionOwnerToggleSelectionOwner | null—The Toggle group that owns this Toggle's state, if any; set by the group itself.controlElementread-onlyHTMLElement | null—The inner button that carries the pressed state and receives focus.toggleDisabledread-onlyboolean—Whether the Toggle is disabled, by itself or by its Toggle group.

Events

EventTypeDescriptiontp-value-changeTpValueChangeEvent<boolean>Cancelable proposal of the inverse pressed state on each press of a standalone Toggle; detail.value, detail.previousValue and the detail.reason.

Methods

MethodReturnsDescriptionsetPressed(pressed, reason, event?)voidProposes a new pressed state as if the user had made it, notifying listeners first; a grouped Toggle ignores it, since its group owns the value.

Slots

SlotDescriptiondefaultThe label: text, an Icon, or both. Mark a leading or trailing Icon with data-icon="inline-start" or data-icon="inline-end" to tighten the padding on that edge.

CSS parts

PartDescription::part(toggle)The native button that carries the pressed state.::part(toggle-content)The label inside the button; its part contract can render content from the pressed state.

Components, widgets and patterns that use this one.

Show more