or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

date-time.mddrag-drop.mdfocus-management.mdform-controls.mdindex.mdinteractions.mdinternationalization.mdlayout-navigation.mdoverlays-modals.mdselection-controls.mdtags.mdtoast-notifications.mdutilities.md

focus-management.mddocs/

0

# Focus Management

1

2

Advanced focus management including focus rings, focus scopes, focus restoration, and keyboard navigation. These hooks and components provide comprehensive focus control for accessible applications.

3

4

## Capabilities

5

6

### Focus Ring

7

8

Provides focus ring visualization with keyboard-only display and customizable styling.

9

10

```typescript { .api }

11

/**

12

* Focus ring component that automatically shows/hides based on interaction method

13

* @param props - Focus ring configuration

14

* @returns Focus ring element

15

*/

16

function FocusRing(props: FocusRingProps): JSX.Element;

17

18

/**

19

* Provides focus ring behavior and state

20

* @param props - Focus ring configuration

21

* @returns Focus ring result with state and props

22

*/

23

function useFocusRing(props?: AriaFocusRingProps): FocusRingAria;

24

25

interface FocusRingProps {

26

/** Children render prop receiving focus ring state */

27

children: (states: { isFocusVisible: boolean; focusProps: DOMAttributes<Element> }) => ReactNode;

28

/** Whether focus ring is disabled */

29

isDisabled?: boolean;

30

/** Auto-focus behavior */

31

autoFocus?: boolean;

32

/** Focus ring class name when visible */

33

focusClass?: string;

34

/** Focus ring styles when visible */

35

focusStyle?: React.CSSProperties;

36

}

37

38

interface AriaFocusRingProps {

39

/** Whether focus ring is disabled */

40

isDisabled?: boolean;

41

/** Auto-focus behavior */

42

autoFocus?: boolean;

43

/** Within focus scope */

44

within?: boolean;

45

}

46

47

interface FocusRingAria {

48

/** Whether focus should be visible */

49

isFocusVisible: boolean;

50

/** Props to spread on the target element */

51

focusProps: DOMAttributes<Element>;

52

}

53

```

54

55

### Focus Scope

56

57

Provides focus containment and restoration for modal dialogs and other containers.

58

59

```typescript { .api }

60

/**

61

* Focus scope component that contains focus within its children

62

* @param props - Focus scope configuration

63

* @returns Focus scope container

64

*/

65

function FocusScope(props: FocusScopeProps): JSX.Element;

66

67

interface FocusScopeProps {

68

/** Children to contain focus within */

69

children: ReactNode;

70

/** Whether focus containment is active */

71

contain?: boolean;

72

/** Whether to restore focus when scope unmounts */

73

restoreFocus?: boolean;

74

/** Whether to auto-focus first element */

75

autoFocus?: boolean;

76

/** Element type to render as container */

77

elementType?: React.ElementType;

78

/** Whether focus should be contained */

79

isDisabled?: boolean;

80

}

81

```

82

83

### Focus Manager

84

85

Provides programmatic focus management within a focus scope.

86

87

```typescript { .api }

88

/**

89

* Provides focus management within a focus scope

90

* @returns Focus manager with navigation methods

91

*/

92

function useFocusManager(): FocusManager;

93

94

interface FocusManager {

95

/** Move focus to the next focusable element */

96

focusNext(opts?: FocusManagerOptions): HTMLElement | null;

97

/** Move focus to the previous focusable element */

98

focusPrevious(opts?: FocusManagerOptions): HTMLElement | null;

99

/** Move focus to the first focusable element */

100

focusFirst(opts?: FocusManagerOptions): HTMLElement | null;

101

/** Move focus to the last focusable element */

102

focusLast(opts?: FocusManagerOptions): HTMLElement | null;

103

}

104

105

interface FocusManagerOptions {

106

/** Whether to wrap focus at boundaries */

107

wrap?: boolean;

108

/** Tabbable elements only */

109

tabbable?: boolean;

110

/** From element to start search */

111

from?: Element;

112

/** Accept function to filter elements */

113

accept?: (element: Element) => boolean;

114

}

115

```

116

117

### Focusable

118

119

Provides focusable element behavior with proper tab order management.

120

121

```typescript { .api }

122

/**

123

* Provides focusable element behavior

124

* @param props - Focusable configuration

125

* @param ref - Ref to the focusable element

126

* @returns Focusable result with props and state

127

*/

128

function useFocusable(props: FocusableOptions, ref: RefObject<Element>): FocusableAria;

129

130

interface FocusableOptions {

131

/** Whether element should be excluded from tab order */

132

excludeFromTabOrder?: boolean;

133

/** Whether element is disabled */

134

isDisabled?: boolean;

135

/** Auto-focus behavior */

136

autoFocus?: boolean;

137

}

138

139

interface FocusableAria {

140

/** Props to spread on the focusable element */

141

focusableProps: DOMAttributes<Element>;

142

}

143

```

144

145

**Usage Examples:**

146

147

```typescript

148

import { useFocusable } from "react-aria";

149

150

// Basic focusable element

151

function CustomButton(props) {

152

const ref = useRef();

153

const { focusableProps } = useFocusable(props, ref);

154

155

return (

156

<button {...focusableProps} ref={ref}>

157

{props.children}

158

</button>

159

);

160

}

161

162

// Focusable with auto-focus

163

function AutoFocusButton(props) {

164

const ref = useRef();

165

const { focusableProps } = useFocusable({

166

autoFocus: true,

167

isDisabled: props.isDisabled

168

}, ref);

169

170

return (

171

<button {...focusableProps} ref={ref}>

172

{props.children}

173

</button>

174

);

175

}

176

177

// Focusable excluded from tab order

178

function SkipTabButton(props) {

179

const ref = useRef();

180

const { focusableProps } = useFocusable({

181

excludeFromTabOrder: true

182

}, ref);

183

184

return (

185

<button {...focusableProps} ref={ref}>

186

{props.children}

187

</button>

188

);

189

}

190

```

191

192

### Focus Utilities

193

194

Additional focus-related utilities for managing focus behavior.

195

196

```typescript { .api }

197

/**

198

* Get all focusable elements within a container

199

* @param element - Container element to search within

200

* @param opts - Options for filtering focusable elements

201

* @returns Array of focusable elements

202

*/

203

function getFocusableElements(element: Element, opts?: {

204

/** Include only tabbable elements */

205

tabbable?: boolean;

206

/** Accept function to filter elements */

207

accept?: (element: Element) => boolean;

208

}): HTMLElement[];

209

210

/**

211

* Check if an element is focusable

212

* @param element - Element to check

213

* @param opts - Options for focusability check

214

* @returns Whether element is focusable

215

*/

216

function isFocusable(element: Element, opts?: {

217

/** Check if tabbable instead of just focusable */

218

tabbable?: boolean;

219

}): boolean;

220

221

/**

222

* Focus an element with appropriate timing

223

* @param element - Element to focus

224

* @param preventScroll - Whether to prevent scrolling to element

225

*/

226

function focusElement(element: HTMLElement | null, preventScroll?: boolean): void;

227

228

/**

229

* Restore focus to a previously focused element

230

* @param element - Element to restore focus to

231

* @param opts - Options for focus restoration

232

*/

233

function restoreFocus(element: HTMLElement | null, opts?: {

234

/** Whether to prevent scrolling */

235

preventScroll?: boolean;

236

}): void;

237

```

238

239

### Focus Visible Detection

240

241

Provides focus-visible detection for styling keyboard-focused elements.

242

243

```typescript { .api }

244

/**

245

* Get the current focus-visible state globally

246

* @returns Whether focus should be visible

247

*/

248

function isFocusVisible(): boolean;

249

250

/**

251

* Set up global focus-visible detection

252

* This is called automatically by React Aria components

253

*/

254

function setupFocusVisible(): void;

255

256

/**

257

* Determine if focus should be visible for an element

258

* @param element - Element to check

259

* @param modality - Current input modality

260

* @returns Whether focus should be visible

261

*/

262

function shouldShowFocusRing(element: Element, modality?: string): boolean;

263

```

264

265

### Focus Event Handling

266

267

Advanced focus event handling utilities.

268

269

```typescript { .api }

270

/**

271

* Create a focus event handler that respects focus visible state

272

* @param onFocus - Handler to call when focus should be visible

273

* @param onBlur - Handler to call when focus is lost

274

* @returns Combined focus event handlers

275

*/

276

function createFocusHandler(

277

onFocus?: (e: FocusEvent) => void,

278

onBlur?: (e: FocusEvent) => void

279

): {

280

onFocus: (e: FocusEvent) => void;

281

onBlur: (e: FocusEvent) => void;

282

};

283

284

/**

285

* Wrap focus events to handle focus-visible state

286

* @param target - Target element

287

* @param onFocusVisible - Handler for focus visible changes

288

* @returns Cleanup function

289

*/

290

function trackFocusVisible(

291

target: Element,

292

onFocusVisible: (isFocusVisible: boolean) => void

293

): () => void;

294

```

295

296

**Usage Examples:**

297

298

```typescript

299

import { FocusRing, FocusScope, useFocusManager } from "react-aria";

300

301

// Focus ring with custom styling

302

function StyledButton(props) {

303

return (

304

<FocusRing focusClass="focus-visible">

305

{({ isFocusVisible, focusProps }) => (

306

<button

307

{...focusProps}

308

className={`btn ${isFocusVisible ? 'focus-visible' : ''}`}

309

>

310

{props.children}

311

</button>

312

)}

313

</FocusRing>

314

);

315

}

316

317

// Modal dialog with focus containment

318

function Modal({ isOpen, onClose, children }) {

319

if (!isOpen) return null;

320

321

return (

322

<div className="modal-backdrop">

323

<FocusScope contain restoreFocus autoFocus>

324

<div className="modal">

325

<button onClick={onClose}>×</button>

326

{children}

327

</div>

328

</FocusScope>

329

</div>

330

);

331

}

332

333

// Custom navigation with focus manager

334

function CustomToolbar() {

335

const focusManager = useFocusManager();

336

337

const handleKeyDown = (e) => {

338

switch (e.key) {

339

case 'ArrowRight':

340

focusManager.focusNext({ wrap: true });

341

break;

342

case 'ArrowLeft':

343

focusManager.focusPrevious({ wrap: true });

344

break;

345

case 'Home':

346

focusManager.focusFirst();

347

break;

348

case 'End':

349

focusManager.focusLast();

350

break;

351

}

352

};

353

354

return (

355

<div role="toolbar" onKeyDown={handleKeyDown}>

356

<button>Cut</button>

357

<button>Copy</button>

358

<button>Paste</button>

359

</div>

360

);

361

}

362

```

363

364

## Advanced Focus Patterns

365

366

### Virtual Focus

367

368

For complex widgets like grids and trees, React Aria supports virtual focus patterns.

369

370

```typescript { .api }

371

/**

372

* Implement virtual focus for grid-like components

373

* @param props - Virtual focus configuration

374

* @returns Virtual focus state and handlers

375

*/

376

function useVirtualFocus<T>(props: VirtualFocusProps<T>): VirtualFocusResult<T>;

377

378

interface VirtualFocusProps<T> {

379

/** Current collection */

380

collection: Collection<Node<T>>;

381

/** Currently focused key */

382

focusedKey?: Key;

383

/** Default focused key */

384

defaultFocusedKey?: Key;

385

/** Handler for focus changes */

386

onFocusChange?: (key: Key) => void;

387

/** Whether virtual focus is disabled */

388

isDisabled?: boolean;

389

}

390

391

interface VirtualFocusResult<T> {

392

/** Currently focused key */

393

focusedKey: Key | null;

394

/** Set the focused key */

395

setFocusedKey(key: Key): void;

396

/** Focus the next item */

397

focusNext(): void;

398

/** Focus the previous item */

399

focusPrevious(): void;

400

/** Focus the first item */

401

focusFirst(): void;

402

/** Focus the last item */

403

focusLast(): void;

404

}

405

```

406

407

### Focus Restoration

408

409

Advanced focus restoration patterns for complex interactions.

410

411

```typescript { .api }

412

/**

413

* Track and restore focus across component lifecycles

414

* @param props - Focus restoration configuration

415

* @returns Focus restoration handlers

416

*/

417

function useFocusRestoration(props: FocusRestorationProps): FocusRestorationResult;

418

419

interface FocusRestorationProps {

420

/** Whether focus restoration is enabled */

421

isEnabled?: boolean;

422

/** Element to restore focus to */

423

restoreTarget?: HTMLElement | null;

424

/** Whether to restore focus on unmount */

425

restoreOnUnmount?: boolean;

426

}

427

428

interface FocusRestorationResult {

429

/** Save the current focus */

430

saveFocus(): void;

431

/** Restore the saved focus */

432

restoreFocus(): void;

433

/** Clear the saved focus */

434

clearSavedFocus(): void;

435

}

436

```

437

438

## Types

439

440

```typescript { .api }

441

type FocusStrategy = 'first' | 'last' | 'restore';

442

443

interface FocusableElement extends HTMLElement {

444

/** Whether element supports focus */

445

focus(options?: FocusOptions): void;

446

/** Tab index of the element */

447

tabIndex: number;

448

}

449

450

interface FocusOptions {

451

/** Whether to prevent scrolling to the element */

452

preventScroll?: boolean;

453

}

454

455

interface FocusEvent {

456

/** Type of focus event */

457

type: 'focus' | 'blur' | 'focusin' | 'focusout';

458

/** Target element */

459

target: Element;

460

/** Related target (element losing/gaining focus) */

461

relatedTarget: Element | null;

462

/** Whether event bubbles */

463

bubbles: boolean;

464

/** Whether event is cancelable */

465

cancelable: boolean;

466

}

467

468

interface FocusState {

469

/** Whether element has focus */

470

isFocused: boolean;

471

/** Whether focus should be visible */

472

isFocusVisible: boolean;

473

/** Whether element is within a focused container */

474

isFocusWithin: boolean;

475

}

476

```