0
# Accessibility Features
1
2
Full accessibility support with ARIA compliance, keyboard navigation, and focus management for screen readers and assistive technologies.
3
4
## Core Imports
5
6
```javascript
7
import { Tabs, TabList, Tab, TabPanel } from "react-tabs";
8
```
9
10
## Capabilities
11
12
### ARIA Compliance
13
14
Complete ARIA implementation following WAI-ARIA authoring practices for tab interfaces.
15
16
```typescript { .api }
17
/**
18
* ARIA attributes automatically applied:
19
* - Tabs: container with data-rttabs identifier
20
* - TabList: role="tablist"
21
* - Tab: role="tab", aria-selected, aria-disabled, aria-controls
22
* - TabPanel: role="tabpanel", aria-labelledby
23
*/
24
interface ARIAAttributes {
25
/** Applied to TabList component */
26
'role': 'tablist';
27
/** Applied to Tab components */
28
'role': 'tab';
29
'aria-selected': 'true' | 'false';
30
'aria-disabled': 'true' | 'false';
31
'aria-controls': string; // References panel ID
32
/** Applied to TabPanel components */
33
'role': 'tabpanel';
34
'aria-labelledby': string; // References tab ID
35
}
36
```
37
38
**ARIA Structure Example:**
39
40
```html
41
<!-- Generated HTML structure with ARIA attributes -->
42
<div class="react-tabs" data-rttabs>
43
<ul role="tablist" class="react-tabs__tab-list">
44
<li role="tab"
45
id="tab0"
46
aria-selected="true"
47
aria-disabled="false"
48
aria-controls="panel0"
49
tabindex="0">
50
Tab 1
51
</li>
52
<li role="tab"
53
id="tab1"
54
aria-selected="false"
55
aria-disabled="false"
56
aria-controls="panel1"
57
tabindex="-1">
58
Tab 2
59
</li>
60
</ul>
61
<div role="tabpanel"
62
id="panel0"
63
aria-labelledby="tab0">
64
Panel 1 Content
65
</div>
66
<div role="tabpanel"
67
id="panel1"
68
aria-labelledby="tab1">
69
Panel 2 Content
70
</div>
71
</div>
72
```
73
74
### Keyboard Navigation
75
76
Full keyboard navigation support following standard tab interface patterns.
77
78
```typescript { .api }
79
interface KeyboardNavigationProps {
80
/** Disable up/down arrow key navigation */
81
disableUpDownKeys?: boolean; // Default: false
82
/** Disable left/right arrow key navigation */
83
disableLeftRightKeys?: boolean; // Default: false
84
/** Text direction for navigation */
85
direction?: 'rtl' | 'ltr'; // Default: 'ltr'
86
}
87
88
/**
89
* Supported keyboard interactions:
90
* - Arrow Left/Up: Previous tab (respects RTL)
91
* - Arrow Right/Down: Next tab (respects RTL)
92
* - Home: First tab
93
* - End: Last tab
94
* - Enter/Space: Activate focused tab
95
* - Tab: Move to tab panel content
96
*/
97
interface KeyboardEvents {
98
ArrowLeft: () => void;
99
ArrowRight: () => void;
100
ArrowUp: () => void;
101
ArrowDown: () => void;
102
Home: () => void;
103
End: () => void;
104
Enter: () => void;
105
Space: () => void;
106
}
107
```
108
109
**Keyboard Navigation Examples:**
110
111
```javascript
112
// Standard keyboard navigation
113
<Tabs>
114
<TabList>
115
<Tab>Home</Tab>
116
<Tab>About</Tab>
117
<Tab>Contact</Tab>
118
</TabList>
119
<TabPanel>Home Content</TabPanel>
120
<TabPanel>About Content</TabPanel>
121
<TabPanel>Contact Content</TabPanel>
122
</Tabs>
123
124
// Disable vertical arrow keys (horizontal tabs only)
125
<Tabs disableUpDownKeys={true}>
126
<TabList>
127
<Tab>Tab 1</Tab>
128
<Tab>Tab 2</Tab>
129
</TabList>
130
<TabPanel>Content 1</TabPanel>
131
<TabPanel>Content 2</TabPanel>
132
</Tabs>
133
134
// RTL support with reversed navigation
135
<Tabs direction="rtl">
136
<TabList>
137
<Tab>علامة التبويب 1</Tab>
138
<Tab>علامة التبويب 2</Tab>
139
</TabList>
140
<TabPanel>المحتوى 1</TabPanel>
141
<TabPanel>المحتوى 2</TabPanel>
142
</Tabs>
143
144
// Disable all arrow key navigation
145
<Tabs disableUpDownKeys={true} disableLeftRightKeys={true}>
146
<TabList>
147
<Tab>Tab 1</Tab>
148
<Tab>Tab 2</Tab>
149
</TabList>
150
<TabPanel>Content 1</TabPanel>
151
<TabPanel>Content 2</TabPanel>
152
</Tabs>
153
```
154
155
### Focus Management
156
157
Comprehensive focus management for optimal keyboard and screen reader experience.
158
159
```typescript { .api }
160
interface FocusManagementProps {
161
/** Focus the selected tab on initial render */
162
defaultFocus?: boolean; // Default: false
163
/** Focus tab when clicked */
164
focusTabOnClick?: boolean; // Default: true
165
/** Window environment for SSR compatibility */
166
environment?: Window;
167
}
168
169
/**
170
* Focus behavior:
171
* - Only selected tab is focusable (tabindex="0")
172
* - Other tabs have tabindex="-1"
173
* - Focus moves with selection via keyboard
174
* - Click focus can be disabled
175
*/
176
interface FocusBehavior {
177
selectedTabIndex: 0;
178
otherTabsIndex: -1;
179
movesFocusWithSelection: boolean;
180
respectsReducedMotion: boolean;
181
}
182
```
183
184
**Focus Management Examples:**
185
186
```javascript
187
// Auto-focus selected tab on mount
188
<Tabs defaultFocus={true}>
189
<TabList>
190
<Tab>Tab 1</Tab>
191
<Tab>Tab 2</Tab>
192
</TabList>
193
<TabPanel>Content 1</TabPanel>
194
<TabPanel>Content 2</TabPanel>
195
</Tabs>
196
197
// Disable focus on click (for custom focus handling)
198
<Tabs focusTabOnClick={false}>
199
<TabList>
200
<Tab>Tab 1</Tab>
201
<Tab>Tab 2</Tab>
202
</TabList>
203
<TabPanel>Content 1</TabPanel>
204
<TabPanel>Content 2</TabPanel>
205
</Tabs>
206
207
// Custom focus handling with refs
208
function CustomFocusExample() {
209
const tabsRef = useRef();
210
211
const focusTab = (index) => {
212
const tab = tabsRef.current.querySelector(`[aria-controls="panel${index}"]`);
213
if (tab) tab.focus();
214
};
215
216
return (
217
<Tabs
218
domRef={(node) => tabsRef.current = node}
219
focusTabOnClick={false}
220
>
221
<TabList>
222
<Tab>Tab 1</Tab>
223
<Tab>Tab 2</Tab>
224
</TabList>
225
<TabPanel>Content 1</TabPanel>
226
<TabPanel>Content 2</TabPanel>
227
</Tabs>
228
);
229
}
230
```
231
232
### Disabled Tab Support
233
234
Accessible disabled tab implementation with proper ARIA attributes and navigation skipping.
235
236
```typescript { .api }
237
interface DisabledTabProps {
238
/** Whether the tab is disabled */
239
disabled?: boolean; // Default: false
240
/** CSS class for disabled tabs */
241
disabledClassName?: string; // Default: "react-tabs__tab--disabled"
242
}
243
244
/**
245
* Disabled tab behavior:
246
* - aria-disabled="true" attribute
247
* - Skipped during keyboard navigation
248
* - Visual disabled styling applied
249
* - Click events prevented
250
*/
251
interface DisabledTabBehavior {
252
'aria-disabled': 'true';
253
clickable: false;
254
keyboardNavigable: false;
255
screenReaderAccessible: true;
256
}
257
```
258
259
**Disabled Tab Examples:**
260
261
```javascript
262
// Individual disabled tabs
263
<TabList>
264
<Tab>Available</Tab>
265
<Tab disabled>Coming Soon</Tab>
266
<Tab>Available</Tab>
267
</TabList>
268
269
// Conditional disabled state
270
<TabList>
271
<Tab>Public</Tab>
272
<Tab disabled={!user.isAdmin}>Admin Only</Tab>
273
<Tab disabled={!user.isPremium}>Premium Feature</Tab>
274
</TabList>
275
276
// Custom disabled styling
277
<Tabs disabledTabClassName="custom-disabled">
278
<TabList>
279
<Tab>Enabled</Tab>
280
<Tab disabled disabledClassName="special-disabled">
281
Special Disabled
282
</Tab>
283
</TabList>
284
<TabPanel>Enabled Content</TabPanel>
285
<TabPanel>This won't show</TabPanel>
286
</Tabs>
287
```
288
289
### Screen Reader Support
290
291
Optimized experience for screen readers with proper announcements and navigation.
292
293
```typescript { .api }
294
/**
295
* Screen reader optimizations:
296
* - Proper role attributes for semantic meaning
297
* - Live region updates for dynamic content
298
* - Descriptive labels and associations
299
* - Tab count and position announcements
300
*/
301
interface ScreenReaderFeatures {
302
semanticRoles: boolean;
303
liveRegionSupport: boolean;
304
labelAssociations: boolean;
305
positionAnnouncements: boolean;
306
}
307
```
308
309
**Screen Reader Enhancement Examples:**
310
311
```javascript
312
// Enhanced labeling for screen readers
313
<Tabs>
314
<TabList aria-label="Main navigation tabs">
315
<Tab aria-describedby="tab1-desc">
316
Dashboard
317
<span id="tab1-desc" className="sr-only">
318
Overview of your account
319
</span>
320
</Tab>
321
<Tab aria-describedby="tab2-desc">
322
Settings
323
<span id="tab2-desc" className="sr-only">
324
Account preferences and configuration
325
</span>
326
</Tab>
327
</TabList>
328
<TabPanel>
329
<h2>Dashboard</h2>
330
<p>Welcome to your account dashboard.</p>
331
</TabPanel>
332
<TabPanel>
333
<h2>Settings</h2>
334
<p>Manage your account settings.</p>
335
</TabPanel>
336
</Tabs>
337
338
// Dynamic content with live regions
339
function DynamicTabsExample() {
340
const [tabData, setTabData] = useState([]);
341
342
return (
343
<Tabs>
344
<TabList>
345
{tabData.map((tab, index) => (
346
<Tab key={tab.id}>
347
{tab.title}
348
{tab.hasUpdates && (
349
<span aria-live="polite" className="sr-only">
350
New updates available
351
</span>
352
)}
353
</Tab>
354
))}
355
</TabList>
356
{tabData.map((tab, index) => (
357
<TabPanel key={tab.id}>
358
<div aria-live="polite">
359
{tab.content}
360
</div>
361
</TabPanel>
362
))}
363
</Tabs>
364
);
365
}
366
```
367
368
### RTL Support
369
370
Right-to-left text direction support with appropriate keyboard navigation reversal.
371
372
```typescript { .api }
373
interface RTLProps {
374
/** Text direction for RTL languages */
375
direction?: 'rtl' | 'ltr'; // Default: 'ltr'
376
}
377
378
/**
379
* RTL behavior:
380
* - Reverses left/right arrow key meanings
381
* - Maintains logical tab order
382
* - Compatible with CSS dir attribute
383
* - Preserves up/down navigation
384
*/
385
interface RTLBehavior {
386
arrowLeftAction: 'next' | 'previous'; // Depends on direction
387
arrowRightAction: 'next' | 'previous'; // Depends on direction
388
visualOrder: 'ltr' | 'rtl';
389
logicalOrder: 'consistent';
390
}
391
```
392
393
**RTL Support Examples:**
394
395
```javascript
396
// Arabic/Hebrew interface
397
<div dir="rtl">
398
<Tabs direction="rtl">
399
<TabList>
400
<Tab>الرئيسية</Tab>
401
<Tab>حول</Tab>
402
<Tab>اتصل</Tab>
403
</TabList>
404
<TabPanel>محتوى الرئيسية</TabPanel>
405
<TabPanel>محتوى حول</TabPanel>
406
<TabPanel>محتوى اتصل</TabPanel>
407
</Tabs>
408
</div>
409
410
// Dynamic direction based on content
411
function MultiLanguageTabs({ language }) {
412
const isRTL = ['ar', 'he', 'fa'].includes(language);
413
414
return (
415
<div dir={isRTL ? 'rtl' : 'ltr'}>
416
<Tabs direction={isRTL ? 'rtl' : 'ltr'}>
417
<TabList>
418
<Tab>{translations[language].home}</Tab>
419
<Tab>{translations[language].about}</Tab>
420
</TabList>
421
<TabPanel>{translations[language].homeContent}</TabPanel>
422
<TabPanel>{translations[language].aboutContent}</TabPanel>
423
</Tabs>
424
</div>
425
);
426
}
427
```
428
429
### Environment Support
430
431
Server-side rendering and custom environment support for accessibility features.
432
433
```typescript { .api }
434
interface EnvironmentProps {
435
/** Window environment for SSR compatibility */
436
environment?: Window;
437
}
438
439
/**
440
* Environment handling for different runtime contexts:
441
* - SSR compatibility with no DOM access during server rendering
442
* - Custom window object support for iframe/popup contexts
443
* - IE compatibility workarounds for document.activeElement access bugs
444
* - Focus detection in non-standard environments
445
*/
446
interface EnvironmentSupport {
447
SSRCompatible: boolean;
448
customWindowSupport: boolean;
449
activeElementDetection: boolean;
450
IECompatibility: boolean;
451
}
452
```
453
454
**Environment Support Examples:**
455
456
```javascript
457
// Custom environment (e.g., iframe or popup window)
458
const iframeWindow = document.getElementById('myFrame').contentWindow;
459
<Tabs environment={iframeWindow}>
460
<TabList>
461
<Tab>Tab 1</Tab>
462
<Tab>Tab 2</Tab>
463
</TabList>
464
<TabPanel>Content 1</TabPanel>
465
<TabPanel>Content 2</TabPanel>
466
</Tabs>
467
468
// IE compatibility workaround (fixes activeElement access in iframes)
469
const safeEnvironment = (() => {
470
try {
471
return window.document.activeElement ? window : undefined;
472
} catch (e) {
473
// IE throws error accessing activeElement in iframes
474
return undefined;
475
}
476
})();
477
478
<Tabs environment={safeEnvironment}>
479
{/* components */}
480
</Tabs>
481
482
// SSR-safe implementation
483
function SSRSafeTabs() {
484
const [mounted, setMounted] = useState(false);
485
486
useEffect(() => {
487
setMounted(true);
488
}, []);
489
490
return (
491
<Tabs
492
environment={mounted ? window : undefined}
493
defaultFocus={false} // Avoid auto-focus on SSR
494
>
495
<TabList>
496
<Tab>Tab 1</Tab>
497
<Tab>Tab 2</Tab>
498
</TabList>
499
<TabPanel>Content 1</TabPanel>
500
<TabPanel>Content 2</TabPanel>
501
</Tabs>
502
);
503
}
504
```