or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

focus-navigation.mdfocus-ring.mdfocus-scope.mdindex.mdvirtual-focus.md

focus-ring.mddocs/

0

# Visual Focus Indicators

1

2

Visual focus indicators provide keyboard-only focus rings that respect user input modality. Focus rings are shown only when users are navigating with keyboard, not when using mouse, touch, or other input methods.

3

4

## Capabilities

5

6

### FocusRing Component

7

8

A utility component that applies CSS classes when an element has keyboard focus, with intelligent detection of interaction modality.

9

10

```typescript { .api }

11

/**

12

* A utility component that applies a CSS class when an element has keyboard focus.

13

* Focus rings are visible only when the user is interacting with a keyboard,

14

* not with a mouse, touch, or other input methods.

15

*/

16

function FocusRing(props: FocusRingProps): ReactElement;

17

18

interface FocusRingProps {

19

/** Child element to apply CSS classes to. */

20

children: ReactElement;

21

/** CSS class to apply when the element is focused. */

22

focusClass?: string;

23

/** CSS class to apply when the element has keyboard focus. */

24

focusRingClass?: string;

25

/**

26

* Whether to show the focus ring when something

27

* inside the container element has focus (true), or

28

* only if the container itself has focus (false).

29

* @default false

30

*/

31

within?: boolean;

32

/** Whether the element is a text input. */

33

isTextInput?: boolean;

34

/** Whether the element will be auto focused. */

35

autoFocus?: boolean;

36

}

37

```

38

39

**Usage Examples:**

40

41

```typescript

42

import React from "react";

43

import { FocusRing } from "@react-aria/focus";

44

45

// Basic button with focus ring

46

function Button({ children, ...props }) {

47

return (

48

<FocusRing focusRingClass="focus-visible">

49

<button className="btn" {...props}>

50

{children}

51

</button>

52

</FocusRing>

53

);

54

}

55

56

// Input with different focus classes

57

function TextInput({ label, ...props }) {

58

return (

59

<div>

60

<label>{label}</label>

61

<FocusRing

62

focusClass="input-focused"

63

focusRingClass="input-focus-ring"

64

isTextInput

65

>

66

<input type="text" {...props} />

67

</FocusRing>

68

</div>

69

);

70

}

71

72

// Container with focus-within behavior

73

function Card({ children }) {

74

return (

75

<FocusRing

76

focusRingClass="card-focus-ring"

77

within

78

>

79

<div className="card">

80

{children}

81

</div>

82

</FocusRing>

83

);

84

}

85

86

// Auto-focused element

87

function AutoFocusButton({ children, ...props }) {

88

return (

89

<FocusRing focusRingClass="focus-visible" autoFocus>

90

<button {...props}>

91

{children}

92

</button>

93

</FocusRing>

94

);

95

}

96

```

97

98

### useFocusRing Hook

99

100

Determines whether a focus ring should be shown and provides focus state information with modality detection.

101

102

```typescript { .api }

103

/**

104

* Determines whether a focus ring should be shown to indicate keyboard focus.

105

* Focus rings are visible only when the user is interacting with a keyboard,

106

* not with a mouse, touch, or other input methods.

107

*/

108

function useFocusRing(props?: AriaFocusRingProps): FocusRingAria;

109

110

interface AriaFocusRingProps {

111

/**

112

* Whether to show the focus ring when something

113

* inside the container element has focus (true), or

114

* only if the container itself has focus (false).

115

* @default false

116

*/

117

within?: boolean;

118

/** Whether the element is a text input. */

119

isTextInput?: boolean;

120

/** Whether the element will be auto focused. */

121

autoFocus?: boolean;

122

}

123

124

interface FocusRingAria {

125

/** Whether the element is currently focused. */

126

isFocused: boolean;

127

/** Whether keyboard focus should be visible. */

128

isFocusVisible: boolean;

129

/** Props to apply to the container element with the focus ring. */

130

focusProps: DOMAttributes;

131

}

132

```

133

134

**Usage Examples:**

135

136

```typescript

137

import React from "react";

138

import { useFocusRing } from "@react-aria/focus";

139

import clsx from "clsx";

140

141

// Custom button with focus ring logic

142

function CustomButton({ children, className, ...props }) {

143

const { isFocused, isFocusVisible, focusProps } = useFocusRing();

144

145

return (

146

<button

147

{...props}

148

{...focusProps}

149

className={clsx(className, {

150

'is-focused': isFocused,

151

'focus-visible': isFocusVisible

152

})}

153

>

154

{children}

155

</button>

156

);

157

}

158

159

// Input with custom focus ring behavior

160

function CustomInput({ isTextInput = true, ...props }) {

161

const { isFocused, isFocusVisible, focusProps } = useFocusRing({

162

isTextInput

163

});

164

165

return (

166

<input

167

{...props}

168

{...focusProps}

169

data-focused={isFocused}

170

data-focus-visible={isFocusVisible}

171

style={{

172

outline: isFocusVisible ? '2px solid blue' : 'none',

173

borderColor: isFocused ? '#007acc' : '#ccc'

174

}}

175

/>

176

);

177

}

178

179

// Container with focus-within behavior

180

function FocusWithinContainer({ children }) {

181

const { isFocused, isFocusVisible, focusProps } = useFocusRing({

182

within: true

183

});

184

185

return (

186

<div

187

{...focusProps}

188

className={clsx('container', {

189

'has-focus-within': isFocused,

190

'focus-within-visible': isFocusVisible

191

})}

192

>

193

{children}

194

</div>

195

);

196

}

197

198

// Conditional focus ring display

199

function ConditionalFocusRing({ showFocusRing = true, children }) {

200

const { isFocused, isFocusVisible, focusProps } = useFocusRing();

201

202

return (

203

<div

204

{...focusProps}

205

style={{

206

outline: showFocusRing && isFocusVisible ? '2px solid orange' : 'none'

207

}}

208

>

209

Focus state: {isFocused ? 'focused' : 'not focused'}

210

<br />

211

Focus visible: {isFocusVisible ? 'visible' : 'not visible'}

212

{children}

213

</div>

214

);

215

}

216

```

217

218

## Focus Ring Behavior

219

220

### Interaction Modality Detection

221

222

The focus ring system automatically detects user interaction modality:

223

224

- **Keyboard Navigation**: Focus rings are shown when users navigate with Tab, Arrow keys, or other keyboard interactions

225

- **Mouse/Touch Interaction**: Focus rings are hidden when users interact with mouse clicks or touch gestures

226

- **Programmatic Focus**: Focus rings are shown when focus is moved programmatically (e.g., via `focus()` calls)

227

- **Auto Focus**: Elements with `autoFocus={true}` show focus rings by default

228

229

### Text Input Considerations

230

231

When `isTextInput={true}`:

232

- Focus rings follow different visibility rules optimized for text input fields

233

- Accounts for the fact that text inputs often maintain focus during typing

234

- Provides appropriate visual feedback for screen reader users

235

236

### Focus Within Mode

237

238

When `within={true}`:

239

- The focus ring is shown when any descendant element has focus

240

- Useful for card components, form groups, or other containers

241

- Combines focus-within CSS behavior with modality detection

242

243

### CSS Integration

244

245

The focus ring components work with CSS to provide visual feedback:

246

247

```css

248

/* Example CSS for focus rings */

249

.focus-visible {

250

outline: 2px solid #007acc;

251

outline-offset: 2px;

252

}

253

254

.input-focused {

255

border-color: #007acc;

256

}

257

258

.input-focus-ring {

259

box-shadow: 0 0 0 2px rgba(0, 122, 204, 0.3);

260

}

261

262

.card-focus-ring {

263

box-shadow: 0 0 0 2px rgba(0, 122, 204, 0.2);

264

}

265

266

/* Hide default browser focus outlines when using custom focus rings */

267

button:focus,

268

input:focus {

269

outline: none;

270

}

271

```

272

273

### Accessibility Considerations

274

275

- Focus rings are essential for keyboard users and screen reader users

276

- Never completely hide focus indicators - always provide some visual indication

277

- Ensure sufficient color contrast for focus ring colors

278

- Test focus ring visibility in both light and dark themes

279

- Consider users with visual impairments who may need high contrast focus indicators