or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

accessibility.mdcomponents.mdindex.mdstate-management.mdstyling.md

accessibility.mddocs/

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

```