Skip to content

Toggle Group

ButtonsSince 0.9.0
import { ToggleGroup } from '@absoluteui/components/toggle-group';
import '@absoluteui/components/button/style.css';

Using Angular? See Toggle Group for Angular.

A named group of toggle buttons for one setting with a few choices, such as text alignment, a list or grid view, or text styles. Each item is a native button with aria-pressed (Button with pressed). Single selection keeps at most one item pressed (and with required, exactly one); multiple lets several be pressed. One button is in the tab sequence and the arrow keys move between the buttons (roving tabindex).

  • Switching a view or a formatting state that applies at once: list or grid, bold and italic, alignment.
  • Two to about seven short choices shown side by side.
  • A form value submitted with other fields: use Radio Group or Checkbox Group.
  • Navigation between panels: use Tabs.
  • Commands that run once: use Button or Button Group.

Required single choice with icon-only buttons

Section titled “Required single choice with icon-only buttons”
import { ToggleGroup } from '@absoluteui/components/toggle-group';
const host = document.createElement('div');
document.body.append(host);
ToggleGroup.create(host, {
label: 'Text alignment',
required: true,
attached: true,
value: ['start'],
items: [
{ value: 'start', label: 'Align start', icon: 'align-start', iconOnly: true },
{ value: 'center', label: 'Align center', icon: 'align-center', iconOnly: true },
{ value: 'end', label: 'Align end', icon: 'align-end', iconOnly: true },
],
});
import { ToggleGroup, type ToggleGroupChangeDetail } from '@absoluteui/components/toggle-group';
const host = document.createElement('div');
const preview = document.createElement('p');
preview.textContent = 'The quick brown fox';
document.body.append(host, preview);
ToggleGroup.create(host, {
label: 'Text style',
multiple: true,
items: [
{ value: 'bold', label: 'Bold', icon: 'bold' },
{ value: 'italic', label: 'Italic', icon: 'italic' },
{ value: 'underline', label: 'Underline', icon: 'underline' },
],
});
host.addEventListener('aui-change', (event) => {
const { value } = (event as CustomEvent<ToggleGroupChangeDetail>).detail;
preview.style.fontWeight = value.includes('bold') ? 'bold' : '';
preview.style.fontStyle = value.includes('italic') ? 'italic' : '';
preview.style.textDecoration = value.includes('underline') ? 'underline' : '';
});
import { ToggleGroup } from '@absoluteui/components/toggle-group';
import '@absoluteui/components/button/style.css';
import '@absoluteui/components/toggle-group/style.css';
const host = document.querySelector<HTMLElement>('#density');
if (host) ToggleGroup.create(host, { label: 'Density', required: true, value: ['comfortable'], items: [{ value: 'compact', label: 'Compact' }, { value: 'comfortable', label: 'Comfortable' }] });
import { ToggleGroup, type ToggleGroupChangeDetail } from '@absoluteui/components/toggle-group';
const host = document.querySelector<HTMLElement>('#view');
if (host) {
ToggleGroup.create(host, { label: 'View', required: true, attached: true, value: ['list'], items: [{ value: 'list', label: 'List' }, { value: 'grid', label: 'Grid' }] });
host.addEventListener('aui-change', (event) => {
const [view] = (event as CustomEvent<ToggleGroupChangeDetail>).detail.value;
document.body.dataset.view = view ?? 'list';
});
}
<div class="aui-toggle-group [--vertical] [--attached]" role="group" aria-label="Text alignment">
<button class="aui-toggle-group__item aui-button [aui-button--pressed]" aria-pressed="true|false" tabindex="0|-1">icon label</button>
...
</div>
ToggleGroup.create(host: HTMLElement, options: ToggleGroupOptions): ToggleGroup

Global configuration key: toggleGroup (see Configuration).

Option Type Default Description
label string Accessible name of the group. Required.
items readonly ToggleGroupItem[] Buttons: { value, label, icon?, iconOnly?, disabled? } (1 to 100, unique values). Required.
value readonly string[] Pressed values; at most one in single mode.
multiple boolean "false" Allow several pressed items.
required boolean "false" Single mode: one item stays pressed.
orientation 'horizontal' | 'vertical' "horizontal" Layout and arrow-key axis.
attached boolean "false" Join the buttons into one segmented control.
disabled boolean "false" Disable every button.
size 'sm' | 'md' | 'lg' "md" Button size. Globally configurable.
Property Type Description
host HTMLElement The host element (role=group).
value readonly string[] Pressed values, in item order.
options Readonly<ToggleGroupOptions> Current options.
Method Description
setValue(value: readonly string[]): void Set the pressed values (no event).
focus(): void Focus the button in the tab sequence.
update(options: Partial<ToggleGroupOptions>): void Merge and apply options; new items re-create the buttons.
destroy(): void Destroy the buttons and remove attributes, classes, and listeners.
Event Detail Bubbles Cancelable Description
aui-change ToggleGroupChangeDetail Yes No The user changed the pressed items: { value, changed }.

All rules live in the aui.components cascade layer, so application styles override them without specificity battles.

Class Purpose
aui-toggle-group Host (role=group).
aui-toggle-group--vertical Vertical orientation.
aui-toggle-group--attached Segmented control.
aui-toggle-group__item Each button (also aui-button).

Tokens this stylesheet reads (verified in CI). Override them in a theme or with the Theme Designer.

--aui-border-width | --aui-radius-md | --aui-space-1

interface ToggleGroupConfig { size: 'sm' | 'md' | 'lg' }
interface ToggleGroupItem { value: string; label: string; icon?: IconRef | null; iconOnly?: boolean; disabled?: boolean }
interface ToggleGroupOptions extends Partial<ToggleGroupConfig> {
label: string;
items: readonly ToggleGroupItem[];
value?: readonly string[];
multiple?: boolean;
required?: boolean;
orientation?: 'horizontal' | 'vertical';
attached?: boolean;
disabled?: boolean;
}
interface ToggleGroupChangeDetail { value: string[]; changed: string }

Pattern: WAI-ARIA toggle buttons (button with aria-pressed) in a named group, with roving tabindex as in the APG toolbar pattern.

Key Context Action
Tab Group Moves focus into the group (to the last focused button) and out of it.
ArrowRight / ArrowLeft Horizontal Move to the next or previous enabled button (reading direction aware, wraps).
ArrowDown / ArrowUp Vertical Move to the next or previous enabled button (wraps).
Home / End Group Move to the first or last enabled button.
Enter / Space Item Toggle the button.
Element Role
host group
item button (native) with aria-pressed
Attribute Element Value
aria-label host the label option
aria-pressed item true when pressed, false otherwise
aria-orientation host vertical when vertical
aria-label icon-only item the item label

One button in the tab sequence (roving tabindex); clicking a button makes it the tab stop.

Criterion Level Note
1.3.1 Info and Relationships A
1.4.1 Use of Color A
2.1.1 Keyboard A
2.4.3 Focus Order A
4.1.2 Name, Role, Value A

Automated test results: Accessibility and compliance.

  • The pressed state differs in more than hue (selection fill and a stronger boundary) and is exposed with aria-pressed.
  • Required single groups keep one button pressed; pressing it again does nothing.
  • Manual screen-reader verification (NVDA, JAWS, VoiceOver) is pending.

Single or multiple; required; horizontal or vertical; attached; disabled; item disabled; pressed items.

From Trigger To
single, A pressed user presses B B pressed, A released; aui-change
single, A pressed user presses A none pressed (or unchanged when required)
multiple user presses an item it toggles; others unchanged
any setValue() / update({ value }) the given values, no event
  • Keep item labels the same whether pressed or not; aria-pressed announces the state.
  • The pressed state differs in more than hue: a selection fill and a stronger boundary.
  • The e2e axe run covers three themes; manual screen-reader verification is pending.

Buttons wrap unless attached; vertical stacks them.

Arrow keys follow the reading direction; attached radii use logical properties.

Button tokens apply; pressed colors come from the selection tokens (contrast gate pairs). Forced colors draw pressed buttons in Highlight.

configureAbsoluteUI({ components: { toggleGroup: { size: 'sm' } } });

The instance size overrides configuration; configuration changes re-render existing groups.

Per item icon; with iconOnly, the label becomes the accessible name.

Labels are rendered as text, never parsed as HTML.

No persistence, network access, or telemetry.

Pressing updates the state of each button in place; only new items re-create buttons.

Up to 100 items; intended for a handful.

  • required with an empty value presses the first enabled item.
  • A disabled item keeps its pressed state; the arrow keys skip it.
  • Values not among the items are rejected.
Code Category Cause
TOGGLE_GROUP_OPTIONS configuration Blank label, no items or more than 100, duplicate or blank values, a blank item label, unknown values, or several values in single mode.
ICON_UNKNOWN configuration Unknown item icon.
CFG_INVALID_VALUE / CFG_UNKNOWN_OPTION configuration Invalid size or unknown configuration.

Invalid options throw before the host is modified.

  • Not a form control: the value is not submitted with a form.
  • Manual screen-reader verification is pending.
  • Menus or popups inside the group.
  • Rich content in items.