Toggle Group
A set of two-state buttons that can be toggled on or off.
import { component$, useStyles$ } from '@builder.io/qwik';
import styles from '../snippets/toggle.css?inline';
import { ToggleGroup } from '@qwik-ui/headless';
export default component$(() => {
useStyles$(styles);
return (
<div class="toggle-container">
<ToggleGroup.Root>
<ToggleGroup.Item value="left" aria-label="Left aligned" class="toggle">
Left
</ToggleGroup.Item>
<ToggleGroup.Item value="center" aria-label="Center aligned" class="toggle">
Center
</ToggleGroup.Item>
<ToggleGroup.Item value="right" aria-label="Right aligned" class="toggle">
Right
</ToggleGroup.Item>
</ToggleGroup.Root>
</div>
);
});
✨ Features
- Follows the WAI-Aria design pattern
- Full keyboard navigation
- Can open one or multiple items at a time
- Supports initial and reactive values
- Supports looping
- Choose the orientation and direction
Building blocks
import { component$ } from '@builder.io/qwik';
import { ToggleGroup } from '@qwik-ui/headless';
export default component$(() => {
return (
<ToggleGroup.Root>
<ToggleGroup.Item value="left" aria-label="Left aligned">
Left
</ToggleGroup.Item>
<ToggleGroup.Item value="center" aria-label="Center aligned">
Center
</ToggleGroup.Item>
<ToggleGroup.Item value="right" aria-label="Right aligned">
Right
</ToggleGroup.Item>
</ToggleGroup.Root>
);
});
🎨 Anatomy
Component | Description |
ToggleGroup.Root | The primary container for the toggle group. |
ToggleGroup.Item | A single item. |
Usage / Component State
Multiple selection
Pass a multiple
prop to enable multi-selection.
import { component$, useStyles$ } from '@builder.io/qwik';
import styles from '../snippets/toggle.css?inline';
import { ToggleGroup } from '@qwik-ui/headless';
export default component$(() => {
useStyles$(styles);
return (
<div class="toggle-container">
<ToggleGroup.Root multiple>
<ToggleGroup.Item value="left" aria-label="Left aligned" class="toggle">
Left
</ToggleGroup.Item>
<ToggleGroup.Item value="center" aria-label="Center aligned" class="toggle">
Center
</ToggleGroup.Item>
<ToggleGroup.Item value="right" aria-label="Right aligned" class="toggle">
Right
</ToggleGroup.Item>
</ToggleGroup.Root>
</div>
);
});
Initial Value (Uncontrolled)
An initial, uncontrolled value can be provided using the value
prop.
import { component$, useStyles$ } from '@builder.io/qwik';
import styles from '../snippets/toggle.css?inline';
import { ToggleGroup } from '@qwik-ui/headless';
export default component$(() => {
useStyles$(styles);
return (
<div class="toggle-container">
<ToggleGroup.Root value={'left'}>
<ToggleGroup.Item value="left" aria-label="Left aligned" class="toggle">
Left
</ToggleGroup.Item>
<ToggleGroup.Item value="center" aria-label="Center aligned" class="toggle">
Center
</ToggleGroup.Item>
<ToggleGroup.Item value="right" aria-label="Right aligned" class="toggle">
Right
</ToggleGroup.Item>
</ToggleGroup.Root>
</div>
);
});
If you want to have some control when an item is selected, like making some side effect you can use
the onChange$
. The event is fired when the user toggle the button, and receives the new value.
import { component$, useSignal, useStyles$ } from '@builder.io/qwik';
import styles from '../snippets/toggle.css?inline';
import { ToggleGroup } from '@qwik-ui/headless';
export default component$(() => {
const valueSelected = useSignal<string>('left');
useStyles$(styles);
return (
<div class="toggle-container">
<ToggleGroup.Root
value={'left'}
onChange$={(v: string) => {
valueSelected.value = v;
}}
>
<ToggleGroup.Item value="left" aria-label="Left aligned" class="toggle">
Left
</ToggleGroup.Item>
<ToggleGroup.Item value="center" aria-label="Center aligned" class="toggle">
Center
</ToggleGroup.Item>
<ToggleGroup.Item value="right" aria-label="Right aligned" class="toggle">
Right
</ToggleGroup.Item>
</ToggleGroup.Root>
<span>You selected: {valueSelected.value}</span>
</div>
);
});
Reactive Value (Controlled)
Pass a signal to bind:value
prop to make the pressed state controlled (binding the value with a signal).
import { component$, useSignal, useStyles$ } from '@builder.io/qwik';
import styles from '../snippets/toggle.css?inline';
import { ToggleGroup } from '@qwik-ui/headless';
export default component$(() => {
const valueSelected = useSignal<string>('left');
useStyles$(styles);
return (
<div class="toggle-container">
<ToggleGroup.Root bind:value={valueSelected}>
<ToggleGroup.Item value="left" aria-label="Left aligned" class="toggle">
Left
</ToggleGroup.Item>
<ToggleGroup.Item value="center" aria-label="Center aligned" class="toggle">
Center
</ToggleGroup.Item>
<ToggleGroup.Item value="right" aria-label="Right aligned" class="toggle">
Right
</ToggleGroup.Item>
</ToggleGroup.Root>
<span>You selected: {valueSelected.value}</span>
<button
style={{ border: '1px solid black', padding: '10px' }}
onClick$={() => (valueSelected.value = 'right')}
>
I can only press 'right'
</button>
</div>
);
});
Disabled
Pass the disabled
prop.
import { component$, useStyles$ } from '@builder.io/qwik';
import styles from '../snippets/toggle.css?inline';
import { ToggleGroup } from '@qwik-ui/headless';
export default component$(() => {
useStyles$(styles);
return (
<div class="toggle-container">
<ToggleGroup.Root disabled>
<ToggleGroup.Item value="left" aria-label="Left aligned" class="toggle">
Left
</ToggleGroup.Item>
<ToggleGroup.Item value="center" aria-label="Center aligned" class="toggle">
Center
</ToggleGroup.Item>
<ToggleGroup.Item value="right" aria-label="Right aligned" class="toggle">
Right
</ToggleGroup.Item>
</ToggleGroup.Root>
</div>
);
});
You can also disabled specific items, pass the disabled
prop at the ToggleGroup.Item
level:
When navigating with key arrows, the disabled item will be skipped.
import { component$, useStyles$ } from '@builder.io/qwik';
import styles from '../snippets/toggle.css?inline';
import { ToggleGroup } from '@qwik-ui/headless';
export default component$(() => {
useStyles$(styles);
return (
<div class="toggle-container">
<ToggleGroup.Root>
<ToggleGroup.Item value="left" aria-label="Left aligned" class="toggle">
Left
</ToggleGroup.Item>
<ToggleGroup.Item
disabled
value="center"
aria-label="Center aligned"
class="toggle"
>
Center
</ToggleGroup.Item>
<ToggleGroup.Item value="right" aria-label="Right aligned" class="toggle">
Right
</ToggleGroup.Item>
</ToggleGroup.Root>
</div>
);
});
Looping Enabled
Pass the loop
prop. When enabled, keyboard navigation will loop from last item to first, and vice versa.
If one item is disabled it will skip it.
import { component$, useStyles$ } from '@builder.io/qwik';
import styles from '../snippets/toggle.css?inline';
import { ToggleGroup } from '@qwik-ui/headless';
export default component$(() => {
useStyles$(styles);
return (
<div class="toggle-container">
<ToggleGroup.Root loop>
<ToggleGroup.Item value="left" aria-label="Left aligned" class="toggle">
Left
</ToggleGroup.Item>
<ToggleGroup.Item value="center" aria-label="Center aligned" class="toggle">
Center
</ToggleGroup.Item>
<ToggleGroup.Item value="right" aria-label="Right aligned" class="toggle">
Right
</ToggleGroup.Item>
</ToggleGroup.Root>
</div>
);
});
If one item is disabled it will skip it.
import { component$, useStyles$ } from '@builder.io/qwik';
import styles from '../snippets/toggle.css?inline';
import { ToggleGroup } from '@qwik-ui/headless';
export default component$(() => {
useStyles$(styles);
return (
<div class="toggle-container">
<ToggleGroup.Root loop>
<ToggleGroup.Item disabled value="left" aria-label="Left aligned" class="toggle">
Left
</ToggleGroup.Item>
<ToggleGroup.Item value="center" aria-label="Center aligned" class="toggle">
Center
</ToggleGroup.Item>
<ToggleGroup.Item value="right" aria-label="Right aligned" class="toggle">
Right
</ToggleGroup.Item>
</ToggleGroup.Root>
</div>
);
});
Vertical Orientation
Pass the orientation
prop.
import { component$, useStyles$ } from '@builder.io/qwik';
import styles from '../snippets/toggle.css?inline';
import { ToggleGroup } from '@qwik-ui/headless';
export default component$(() => {
useStyles$(styles);
return (
<div class="toggle-container">
<ToggleGroup.Root orientation={'vertical'}>
<ToggleGroup.Item value="left" aria-label="Left aligned" class="toggle">
Left
</ToggleGroup.Item>
<ToggleGroup.Item value="center" aria-label="Center aligned" class="toggle">
Center
</ToggleGroup.Item>
<ToggleGroup.Item value="right" aria-label="Right aligned" class="toggle">
Right
</ToggleGroup.Item>
</ToggleGroup.Root>
</div>
);
});
Right-to-Left (rtl) Direction
Pass the direction
prop to rtl
.
import { component$, useStyles$ } from '@builder.io/qwik';
import styles from '../snippets/toggle.css?inline';
import { ToggleGroup } from '@qwik-ui/headless';
export default component$(() => {
useStyles$(styles);
return (
<div class="toggle-container">
<ToggleGroup.Root orientation={'horizontal'} direction={'rtl'}>
<ToggleGroup.Item value="left" aria-label="Left aligned" class="toggle">
Left
</ToggleGroup.Item>
<ToggleGroup.Item value="center" aria-label="Center aligned" class="toggle">
Center
</ToggleGroup.Item>
<ToggleGroup.Item value="right" aria-label="Right aligned" class="toggle">
Right
</ToggleGroup.Item>
</ToggleGroup.Root>
</div>
);
});
Accessibility
Keyboard interaction
Key | Description |
---|---|
Space | |
Enter | |
ArrowLeft | |
ArrowRight | |
ArrowDown | |
ArrowUp |
API
ToggleGroup.Root
Prop | Type | Description |
---|---|---|
multiple | boolean | Enable multiple selections. Default to `false`. |
value | string | string[] | Initial value to make the pressed state uncontrolled. Use in conjunction with `onChange$` to have some reactivity. |
onChange$ | function PropFunction<() => void> | Called when the state changes. |
bind:value | Signal<string | string[]> | Reactive value (signal) to make the pressed state controlled. |
disabled | boolean | Disables all items. |
loop | boolean | Enable looping when navigating with the keyboard. Default to `false`. |
orientation | "horizontal" | "vertical" | Choose the orientation of the toggle items. Default to "horizontal". |
direction | "ltr" | "rtl" | Choose the direction of the toggle items. Default to "ltr". |
ToggleGroup.Item
Prop | Type | Description |
---|---|---|
value | string | A unique value for the item. |
disabled | boolean | Disables the toggle making the toggle unpressable. |
pressed | boolean | Makes the toggle initially pressed. |