0
# Radix UI React Toggle
1
2
Radix UI React Toggle is a fully accessible two-state button component that can be pressed/unpressed. Built on Radix UI's primitive foundation, it provides comprehensive accessibility features, keyboard navigation, and flexible state management patterns for React applications.
3
4
## Package Information
5
6
- **Package Name**: @radix-ui/react-toggle
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install @radix-ui/react-toggle`
10
- **Peer Dependencies**: React 16.8+ (`npm install react@^16.8.0`)
11
12
## Core Imports
13
14
```typescript
15
import { Toggle, Root } from "@radix-ui/react-toggle";
16
import type { ToggleProps } from "@radix-ui/react-toggle";
17
```
18
19
For CommonJS:
20
21
```javascript
22
const { Toggle, Root } = require("@radix-ui/react-toggle");
23
```
24
25
## Basic Usage
26
27
```typescript
28
import { Toggle } from "@radix-ui/react-toggle";
29
30
// Uncontrolled toggle with default state
31
function BasicToggle() {
32
return (
33
<Toggle defaultPressed={false} onPressedChange={(pressed) => console.log(pressed)}>
34
Toggle Me
35
</Toggle>
36
);
37
}
38
39
// Controlled toggle
40
function ControlledToggle() {
41
const [isPressed, setIsPressed] = useState(false);
42
43
return (
44
<Toggle pressed={isPressed} onPressedChange={setIsPressed}>
45
{isPressed ? "On" : "Off"}
46
</Toggle>
47
);
48
}
49
```
50
51
## Architecture
52
53
The Toggle component provides a clean, accessible interface for two-state interactions:
54
55
- **HTML Button Foundation**: Built on semantic button elements for maximum compatibility
56
- **State Management**: Supports both controlled and uncontrolled component patterns
57
- **Event Handling**: Proper event composition and disabled state management
58
- **Accessibility**: Automatic ARIA attributes and semantic data attributes
59
- **Composition**: Supports `asChild` prop for flexible element composition
60
61
## Capabilities
62
63
### Toggle Component
64
65
The main toggle component that renders as a button with press/unpress functionality.
66
67
```typescript { .api }
68
/**
69
* Toggle component - A two-state button that can be pressed/unpressed
70
*/
71
const Toggle: React.ForwardRefExoticComponent<
72
ToggleProps & React.RefAttributes<HTMLButtonElement>
73
>;
74
75
/**
76
* Root component - Alias for Toggle following Radix UI naming conventions
77
*/
78
const Root: React.ForwardRefExoticComponent<
79
ToggleProps & React.RefAttributes<HTMLButtonElement>
80
>;
81
```
82
83
**Usage Examples:**
84
85
```typescript
86
// Basic uncontrolled usage
87
<Toggle defaultPressed onPressedChange={(pressed) => console.log(pressed)}>
88
Like
89
</Toggle>
90
91
// Controlled usage
92
<Toggle pressed={isPressed} onPressedChange={setIsPressed}>
93
{isPressed ? "Liked" : "Like"}
94
</Toggle>
95
96
// With custom styling via data attributes
97
<Toggle
98
className="toggle-button"
99
data-testid="like-button"
100
>
101
<HeartIcon />
102
</Toggle>
103
104
// Using asChild for custom element
105
<Toggle asChild>
106
<button className="custom-toggle-button">
107
Custom Toggle
108
</button>
109
</Toggle>
110
111
// Using Root alias
112
<Toggle.Root pressed={isPressed}>
113
Toggle Content
114
</Toggle.Root>
115
```
116
117
### Toggle Props Interface
118
119
Complete props interface extending standard HTML button attributes.
120
121
```typescript { .api }
122
interface ToggleProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
123
/**
124
* The controlled state of the toggle
125
*/
126
pressed?: boolean;
127
128
/**
129
* The state of the toggle when initially rendered
130
* Use when you do not need to control the state
131
* @defaultValue false
132
*/
133
defaultPressed?: boolean;
134
135
/**
136
* Callback that fires when the state of the toggle changes
137
*/
138
onPressedChange?: (pressed: boolean) => void;
139
140
/**
141
* When true, merges props into the child element instead of rendering a button
142
* Enables the slot pattern for custom element composition
143
*/
144
asChild?: boolean;
145
146
/**
147
* All standard HTML button attributes are supported:
148
* - Event handlers: onClick, onMouseDown, onMouseUp, onDoubleClick, etc.
149
* - Form attributes: type, disabled, form, name, value, etc.
150
* - Accessibility: aria-*, role, tabIndex, etc.
151
* - Styling: className, style, data-*, etc.
152
* - Standard attributes: id, title, lang, dir, etc.
153
*/
154
}
155
```
156
157
158
## State Management Patterns
159
160
### Controlled Pattern
161
162
When you need to manage the toggle state externally:
163
164
```typescript
165
function ControlledExample() {
166
const [isPressed, setIsPressed] = useState(false);
167
168
// External state updates
169
useEffect(() => {
170
if (someCondition) {
171
setIsPressed(true);
172
}
173
}, [someCondition]);
174
175
return (
176
<Toggle
177
pressed={isPressed}
178
onPressedChange={setIsPressed}
179
>
180
{isPressed ? "Active" : "Inactive"}
181
</Toggle>
182
);
183
}
184
```
185
186
### Uncontrolled Pattern
187
188
When the toggle manages its own state internally:
189
190
```typescript
191
function UncontrolledExample() {
192
return (
193
<Toggle
194
defaultPressed={false}
195
onPressedChange={(pressed) => {
196
// React to state changes without controlling the state
197
console.log("Toggle is now:", pressed ? "pressed" : "unpressed");
198
}}
199
>
200
Toggle Me
201
</Toggle>
202
);
203
}
204
```
205
206
## Accessibility Features
207
208
The Toggle component provides comprehensive accessibility features:
209
210
### ARIA Attributes (Automatic)
211
212
```typescript
213
// When pressed=false or unpressed
214
<button aria-pressed="false" data-state="off">...</button>
215
216
// When pressed=true or pressed
217
<button aria-pressed="true" data-state="on">...</button>
218
219
// When disabled
220
<button disabled data-disabled="">...</button>
221
```
222
223
### Keyboard Navigation
224
225
- **Space Key**: Toggles the pressed state
226
- **Enter Key**: Toggles the pressed state (standard button behavior)
227
- **Tab Navigation**: Follows standard focus order
228
- **Focus Management**: Proper focus handling when disabled
229
230
### Screen Reader Support
231
232
- Announces current state via `aria-pressed` attribute
233
- Compatible with all major screen readers
234
- Proper role semantics as a toggle button
235
236
## Data Attributes for Styling
237
238
The component automatically applies data attributes for CSS styling:
239
240
```css
241
/* Target different states */
242
.toggle-button[data-state="on"] {
243
background-color: blue;
244
color: white;
245
}
246
247
.toggle-button[data-state="off"] {
248
background-color: gray;
249
color: black;
250
}
251
252
.toggle-button[data-disabled] {
253
opacity: 0.5;
254
cursor: not-allowed;
255
}
256
```
257
258
## Advanced Usage
259
260
### Custom Element Composition (asChild)
261
262
Use the `asChild` prop to merge toggle functionality into custom elements:
263
264
```typescript
265
function CustomToggle() {
266
return (
267
<Toggle asChild pressed={isPressed} onPressedChange={setIsPressed}>
268
<div className="custom-toggle-div" role="button" tabIndex={0}>
269
<Icon name={isPressed ? "heart-filled" : "heart-outline"} />
270
<span>{isPressed ? "Liked" : "Like"}</span>
271
</div>
272
</Toggle>
273
);
274
}
275
```
276
277
### Event Handler Composition
278
279
Toggle properly composes event handlers when extending functionality:
280
281
```typescript
282
function EnhancedToggle() {
283
const handleClick = (event) => {
284
console.log("Custom click handler");
285
// Toggle's internal handler will still run unless preventDefault() is called
286
};
287
288
return (
289
<Toggle
290
onClick={handleClick}
291
onPressedChange={(pressed) => console.log("State changed:", pressed)}
292
>
293
Enhanced Toggle
294
</Toggle>
295
);
296
}
297
```
298
299
### Form Integration
300
301
Toggle works seamlessly with forms:
302
303
```typescript
304
function FormToggle() {
305
return (
306
<form>
307
<Toggle
308
name="notifications"
309
value="enabled"
310
defaultPressed
311
onPressedChange={(pressed) => {
312
// Update form state or trigger validation
313
}}
314
>
315
Enable Notifications
316
</Toggle>
317
</form>
318
);
319
}
320
```
321
322
## Types
323
324
```typescript { .api }
325
/**
326
* Complete props interface for Toggle component
327
*/
328
interface ToggleProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
329
pressed?: boolean;
330
defaultPressed?: boolean;
331
onPressedChange?: (pressed: boolean) => void;
332
asChild?: boolean;
333
}
334
```