0
# Toggle Button Groups
1
2
Manages collections of toggle buttons with proper ARIA semantics, supporting both single and multiple selection modes. The group hooks provide container management and individual item behavior for toggle button collections.
3
4
## Capabilities
5
6
### useToggleButtonGroup Hook
7
8
Creates container behavior for toggle button groups with proper ARIA semantics.
9
10
```typescript { .api }
11
/**
12
* Provides container behavior for toggle button groups with proper ARIA semantics
13
* and keyboard navigation support.
14
*/
15
function useToggleButtonGroup(
16
props: AriaToggleButtonGroupProps,
17
state: ToggleGroupState,
18
ref: RefObject<HTMLElement | null>
19
): ToggleButtonGroupAria;
20
```
21
22
### useToggleButtonGroupItem Hook
23
24
Creates behavior for individual items within a toggle button group.
25
26
```typescript { .api }
27
/**
28
* Provides the behavior and accessibility implementation for a toggle button component
29
* within a toggle button group. Handles selection state coordination with the group.
30
*/
31
function useToggleButtonGroupItem(props: AriaToggleButtonGroupItemOptions<'button'>, state: ToggleGroupState, ref: RefObject<HTMLButtonElement | null>): ToggleButtonAria<ButtonHTMLAttributes<HTMLButtonElement>>;
32
function useToggleButtonGroupItem(props: AriaToggleButtonGroupItemOptions<'a'>, state: ToggleGroupState, ref: RefObject<HTMLAnchorElement | null>): ToggleButtonAria<AnchorHTMLAttributes<HTMLAnchorElement>>;
33
function useToggleButtonGroupItem(props: AriaToggleButtonGroupItemOptions<'div'>, state: ToggleGroupState, ref: RefObject<HTMLDivElement | null>): ToggleButtonAria<HTMLAttributes<HTMLDivElement>>;
34
function useToggleButtonGroupItem(props: AriaToggleButtonGroupItemOptions<'input'>, state: ToggleGroupState, ref: RefObject<HTMLInputElement | null>): ToggleButtonAria<InputHTMLAttributes<HTMLInputElement>>;
35
function useToggleButtonGroupItem(props: AriaToggleButtonGroupItemOptions<'span'>, state: ToggleGroupState, ref: RefObject<HTMLSpanElement | null>): ToggleButtonAria<HTMLAttributes<HTMLSpanElement>>;
36
function useToggleButtonGroupItem(props: AriaToggleButtonGroupItemOptions<ElementType>, state: ToggleGroupState, ref: RefObject<Element | null>): ToggleButtonAria<DOMAttributes>;
37
```
38
39
**Usage Examples:**
40
41
```typescript
42
import { useToggleButtonGroup, useToggleButtonGroupItem } from "@react-aria/button";
43
import { useToggleGroupState } from "@react-stately/toggle";
44
import { useRef } from "react";
45
46
// Basic toggle button group
47
function ToggleButtonGroup(props) {
48
let groupRef = useRef<HTMLDivElement | null>(null);
49
let state = useToggleGroupState(props);
50
let { groupProps } = useToggleButtonGroup(props, state, groupRef);
51
52
return (
53
<div {...groupProps} ref={groupRef}>
54
{props.children}
55
</div>
56
);
57
}
58
59
// Toggle button group item
60
function ToggleButtonGroupItem(props) {
61
let ref = useRef<HTMLButtonElement | null>(null);
62
let { buttonProps, isPressed, isSelected, isDisabled } = useToggleButtonGroupItem(
63
props,
64
props.state,
65
ref
66
);
67
68
return (
69
<button
70
{...buttonProps}
71
style={{
72
background: isPressed
73
? (isSelected ? 'darkblue' : 'gray')
74
: (isSelected ? 'blue' : 'lightgray'),
75
color: isSelected ? 'white' : 'black',
76
border: '1px solid #ccc',
77
padding: '8px 12px'
78
}}
79
ref={ref}>
80
{props.children}
81
</button>
82
);
83
}
84
85
// Complete toggle button group example
86
function TextAlignmentGroup() {
87
let groupRef = useRef<HTMLDivElement | null>(null);
88
let state = useToggleGroupState({
89
selectedKeys: ['center'],
90
selectionMode: 'single',
91
onChange: (selectedKeys) => {
92
console.log('Selected alignment:', [...selectedKeys]);
93
}
94
});
95
let { groupProps } = useToggleButtonGroup({
96
'aria-label': 'Text alignment',
97
orientation: 'horizontal'
98
}, state, groupRef);
99
100
return (
101
<div {...groupProps} ref={groupRef} style={{ display: 'flex', gap: 2 }}>
102
<ToggleButtonGroupItem id="left" state={state}>
103
Left
104
</ToggleButtonGroupItem>
105
<ToggleButtonGroupItem id="center" state={state}>
106
Center
107
</ToggleButtonGroupItem>
108
<ToggleButtonGroupItem id="right" state={state}>
109
Right
110
</ToggleButtonGroupItem>
111
</div>
112
);
113
}
114
115
// Multiple selection group
116
function FeatureToggles() {
117
let groupRef = useRef<HTMLDivElement | null>(null);
118
let state = useToggleGroupState({
119
selectedKeys: ['bold'],
120
selectionMode: 'multiple',
121
onChange: (selectedKeys) => {
122
console.log('Active features:', [...selectedKeys]);
123
}
124
});
125
let { groupProps } = useToggleButtonGroup({
126
'aria-label': 'Text formatting options'
127
}, state, groupRef);
128
129
return (
130
<div {...groupProps} ref={groupRef} style={{ display: 'flex', gap: 4 }}>
131
<ToggleButtonGroupItem id="bold" state={state}>
132
<strong>B</strong>
133
</ToggleButtonGroupItem>
134
<ToggleButtonGroupItem id="italic" state={state}>
135
<em>I</em>
136
</ToggleButtonGroupItem>
137
<ToggleButtonGroupItem id="underline" state={state}>
138
<u>U</u>
139
</ToggleButtonGroupItem>
140
</div>
141
);
142
}
143
```
144
145
### Toggle Button Group Props Interface
146
147
Configuration options for toggle button groups.
148
149
```typescript { .api }
150
interface AriaToggleButtonGroupProps extends ToggleGroupProps, AriaLabelingProps {
151
/**
152
* The orientation of the toggle button group.
153
* @default 'horizontal'
154
*/
155
orientation?: Orientation;
156
/** Whether the toggle button group is disabled. */
157
isDisabled?: boolean;
158
}
159
160
interface ToggleGroupProps {
161
/** The currently selected keys in the collection (controlled). */
162
selectedKeys?: 'all' | Iterable<Key>;
163
/** The initial selected keys in the collection (uncontrolled). */
164
defaultSelectedKeys?: 'all' | Iterable<Key>;
165
/** Handler that is called when the selection changes. */
166
onChange?: (keys: Selection) => void;
167
/** The type of selection that is allowed in the collection. */
168
selectionMode?: SelectionMode;
169
/** Whether the collection allows empty selection. */
170
disallowEmptySelection?: boolean;
171
}
172
173
type SelectionMode = 'none' | 'single' | 'multiple';
174
type Selection = 'all' | Set<Key>;
175
type Orientation = 'horizontal' | 'vertical';
176
```
177
178
### Toggle Button Group Return Interface
179
180
Return value from the useToggleButtonGroup hook.
181
182
```typescript { .api }
183
interface ToggleButtonGroupAria {
184
/**
185
* Props for the toggle button group container.
186
*/
187
groupProps: DOMAttributes;
188
}
189
```
190
191
### Toggle Button Group Item Props Interface
192
193
Configuration options for individual toggle button group items.
194
195
```typescript { .api }
196
interface AriaToggleButtonGroupItemOptions<E extends ElementType> extends Omit<AriaToggleButtonGroupItemProps<E>, 'children'> {
197
/** An identifier for the item in the selectedKeys of a ToggleButtonGroup. */
198
id: Key;
199
/** The HTML element or React element used to render the button. @default 'button' */
200
elementType?: E | JSXElementConstructor<any>;
201
/** Whether the button is disabled. */
202
isDisabled?: boolean;
203
/** Handler that is called when the press is released over the target. */
204
onPress?: (e: PressEvent) => void;
205
/** Handler that is called when a press interaction starts. */
206
onPressStart?: (e: PressEvent) => void;
207
/** Handler that is called when a press interaction ends. */
208
onPressEnd?: (e: PressEvent) => void;
209
/** Handler that is called when the press state changes. */
210
onPressChange?: (isPressed: boolean) => void;
211
/** Handler that is called when a press is released over the target. */
212
onPressUp?: (e: PressEvent) => void;
213
/** Whether to prevent focus from moving to the button when pressing it. */
214
preventFocusOnPress?: boolean;
215
}
216
```
217
218
### Toggle Group State Interface
219
220
State management interface for toggle button groups (from @react-stately/toggle).
221
222
```typescript { .api }
223
interface ToggleGroupState {
224
/** The keys for the currently selected items. */
225
selectedKeys: Set<Key>;
226
/** Whether the collection allows empty selection. */
227
disallowEmptySelection: boolean;
228
/** The selection mode for the collection. */
229
selectionMode: SelectionMode;
230
/** Whether the collection is disabled. */
231
isDisabled: boolean;
232
/** Sets the selected keys. */
233
setSelected(key: Key, selected: boolean): void;
234
/** Toggles the selection state of an item. */
235
toggleKey(key: Key): void;
236
/** Replaces the selection with only the given key. */
237
selectKey(key: Key): void;
238
/** Selects all items in the collection. */
239
selectAll(): void;
240
/** Clears the selection. */
241
clearSelection(): void;
242
}
243
```
244
245
## State Management
246
247
Toggle button groups require state management via the `useToggleGroupState` hook from `@react-stately/toggle`:
248
249
```typescript
250
import { useToggleGroupState } from "@react-stately/toggle";
251
252
// Single selection mode (radio group behavior)
253
let state = useToggleGroupState({
254
selectionMode: 'single',
255
selectedKeys: ['option1'],
256
onChange: (keys) => console.log('Selected:', [...keys])
257
});
258
259
// Multiple selection mode (checkbox group behavior)
260
let state = useToggleGroupState({
261
selectionMode: 'multiple',
262
selectedKeys: ['option1', 'option3'],
263
onChange: (keys) => console.log('Selected:', [...keys])
264
});
265
266
// No selection allowed
267
let state = useToggleGroupState({
268
selectionMode: 'none'
269
});
270
```
271
272
## Selection Modes
273
274
### Single Selection Mode
275
- Behaves like a radio group
276
- Only one item can be selected at a time
277
- Selecting a new item deselects the previous one
278
- ARIA role="radiogroup" on container
279
- ARIA role="radio" on items
280
- Uses `aria-checked` instead of `aria-pressed`
281
282
### Multiple Selection Mode
283
- Behaves like a checkbox group
284
- Multiple items can be selected simultaneously
285
- Items can be toggled independently
286
- ARIA role="toolbar" on container
287
- ARIA role="button" on items
288
- Uses `aria-pressed` for selection state
289
290
### No Selection Mode
291
- Items cannot be selected
292
- Used for command buttons that trigger actions
293
- ARIA role="toolbar" on container
294
- No selection state management
295
296
## Accessibility Features
297
298
- **ARIA Roles**: Automatic role assignment based on selection mode
299
- **Keyboard Navigation**: Arrow key navigation between items
300
- **Selection States**: Proper ARIA attributes for selection
301
- **Screen Reader Support**: Clear group and item identification
302
- **Focus Management**: Roving tabindex for keyboard navigation
303
- **Disabled States**: Group and item level disabled support
304
305
## Orientation Support
306
307
Groups support both horizontal and vertical orientations:
308
309
- **Horizontal**: Left/Right arrow key navigation
310
- **Vertical**: Up/Down arrow key navigation
311
- **Automatic ARIA**: Proper `aria-orientation` attribute
312
313
## Integration with Toolbar
314
315
`useToggleButtonGroup` internally uses `useToolbar` from `@react-aria/toolbar` for:
316
317
- Keyboard navigation
318
- Focus management
319
- ARIA toolbar semantics
320
- Orientation handling
321
322
## Item Coordination
323
324
Group items automatically coordinate with the group state:
325
326
- **Selection Sync**: Item selection reflects group state
327
- **State Updates**: Item interactions update group state
328
- **Disabled Inheritance**: Items inherit group disabled state
329
- **Focus Management**: Shared focus management across items