You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
`@react-three/a11y` brings accessibility to WebGL, with easy to use components [react-three-fiber](https://github.com/pmndrs/react-three-fiber) components to enable focus indication, keyboard tab navigation, and screen reader support.
8
12
13
+
Live demo: https://n4rzi.csb.app
14
+
9
15
# How to use
10
16
11
-
## Initial setup
17
+
First, place the `A11yAnnouncer` component next to the R3F Canvas component. This is critical, because it will manage the screen-reader and help emulate focus!
12
18
13
-
Install the @react-three/a11y package
19
+
```jsx
20
+
import { A11yAnnouncer } from'@react-three/a11y'
14
21
15
-
```bash
16
-
npm install @react-three/a11y
22
+
functionApp() {
23
+
return (
24
+
<>
25
+
<Canvas />
26
+
<A11yAnnouncer />
27
+
</>
28
+
)
29
+
}
17
30
```
18
31
19
-
Now, you'll have to import the `A11yAnnouncer` component. We usually place it next to the R3F Canvas component.
32
+
To add accessibility features to your scene you'll have to wrap components you want to make focusable with the `A11y`component:
20
33
21
34
```jsx
22
-
import { A11yAnnouncer } from"@react-three/a11y"
23
-
{...}
24
-
<Canvas>
25
-
{...}
26
-
</Canvas>
27
-
<A11yAnnouncer />
28
-
```
29
-
30
-
This will both help us emulate focus inside the canvas and provide some text to screen readers when necessary.
31
-
32
-
To add some accessibility features to your 3D Objects/Groups you'll have to wrap the 3D objects you want to make focusable with the `A11y` component:
At this point both _My3DComponent_ and _AGroupOf3DComponent_ can receive focus.
52
-
More accurately, the emulated "focus" will be on the parent `A11y` that will act as a provider and let its children access the state.
53
-
But even if they're focusable, nothing will be displayed / read etc without a few more attributes.
42
+
`MyComponent` can now receive focus. More accurately, the emulated "focus" will handled at the `A11y` components which acts as a provider for children to access its state. But even if objects are focusable, nothing will be displayed or shown by default.
54
43
55
44
## Accessing the hover, focused & pressed state
56
45
57
-
For each child wrapped in a`A11y` component, you can access the `focus` / `hover`/`pressed` state like so:
46
+
For each child wrapped in the`A11y` component, you can access the `focus`, `hover`and`pressed` state like so:
<A11y role="content" description="A rotating red square">
144
-
//will read "A rotating red square" to screen readers on focus / hover
145
-
<My3DSquare />
146
-
</A11y>
147
-
{...}
148
-
<A11y role="content" description="A bouncing blue sphere" showAltText={true}>
149
-
//will read "A bouncing blue sphere" to screen readers on focus / hover while also showing it on mouseover
150
-
<My3DSphere />
151
-
</A11y>
152
-
{...}
153
-
</Canvas>
154
-
<A11yAnnouncer />
84
+
// Reads "A rotating red square" to screen readers on focus / hover
85
+
<A11y role="content" description="A rotating red square".../>
86
+
// Reads "A bouncing blue sphere" to screen readers on focus / hover while also showing it on mouseover
87
+
<A11y role="content" description="A bouncing blue sphere" showAltText .../>
155
88
```
156
89
157
90
If your `A11y` component has the `role="button"`, you can use three more props:
@@ -161,56 +94,56 @@ If your `A11y` component has the `role="button"`, you can use three more props:
161
94
-`pressedDescription`: When set, it turns your button in a togglable button. Which means it now has a on/off state. This description will replace the one passed via `description` when the toggle is active.
<A11y role="button" description="This button will send a thank you email to the team" activationMsg="Email is sending">
169
-
//will read the description on hover / focus then will read activationMsg if clicked / pressed
170
-
<My3DSquare />
171
-
</A11y>
172
-
{...}
173
-
<A11y
174
-
role="button"
175
-
description="This button can enable dark theme. Dark theme is off"
176
-
pressedDescription="This button can disable dark theme. Dark theme is on"
177
-
activationMsg="Dark theme enabled"
178
-
deactivationMsg="Dark theme disabled"
179
-
>
180
-
//will read the description on hover / focus then will read activationMsg if turned on or deactivationMsg if tuned off
181
-
<My3DSphere />
182
-
</A11y>
183
-
{...}
184
-
</Canvas>
185
-
<A11yAnnouncer />
97
+
// Reads the description on hover/focus then will read activationMsg if clicked/pressed
98
+
<A11y role="button" description="Sends a thank you email to the team" activationMsg="Email is sending".../>
99
+
// Reads the description on hover/focus then will read activationMsg if turned on or deactivationMsg if tuned off
100
+
<A11y
101
+
role="button"
102
+
description="This button can enable dark theme. Dark theme is off"
103
+
pressedDescription="This button can disable dark theme. Dark theme is on"
104
+
activationMsg="Dark theme enabled"
105
+
deactivationMsg="Dark theme disabled".../>
186
106
```
187
107
188
108
## The three roles of the `A11y` component
189
109
190
-
#### `content`
110
+
Like in HTML, you can focus different kind of elements and expect different things depending on what you're focusing.
191
111
192
-
`cursor: default`
193
-
This role is meant to provide information to screen readers or to serve as a step for a user to navigate your site using Tab for instance.
194
-
It's not meant to trigger anything on click or to be activable with the Keyboard.
195
-
Therefore it won't show a pointer cursor on hover.
112
+
#### Content
196
113
197
-
#### `button`
114
+
```jsx
115
+
<A11y role="content".../>
116
+
```
117
+
118
+
Uses the `default` cursor. This role is meant to provide information to screen readers or to serve as a step for a user to navigate your site using Tab for instance. It's not meant to trigger anything on click or to be activable with the Keyboard. Therefore it won't show a pointer cursor on hover.
119
+
120
+
#### Buttons
121
+
122
+
123
+
```jsx
124
+
<A11y
125
+
role="button"
126
+
activationMsg="Button activated"
127
+
deactivationMsg="Button deactivated"
128
+
pressedDescription="Button pressed".../>
129
+
```
130
+
131
+
Uses the `pointer` cursor. Special attributes: `activationMsg`, `deactivationMsg` and `pressedDescription`.
132
+
133
+
This role is meant to emulate the behaviour of a button or a togglable button. It will display a cursor pointer when your cursor is over the linked 3D object. It will call a function on click but also on any kind of action that would trigger a focused button (Enter, Double-Tap, ...). It is also actionnable by user using a screen reader.
198
134
199
-
`cursor: pointer`
200
-
Special attributes : activationMsg, deactivationMsg, pressedDescription
201
-
This role is meant to emulate the behaviour of a button or a togglable button.
202
-
It will display a cursor pointer when your cursor is over the linked 3D object.
203
-
It will call a function on click but also on any kind of action that would trigger a focused button ( Enter, Double-Tap .. )
204
-
It is also actionnable by user using a screen reader.
205
135
You can turn it into a button with aria-pressed by providing the following properties deactivationMsg, pressedDescription in addition to the usual description and activationMsg properties.
206
136
207
-
#### `link`
137
+
#### Links
138
+
208
139
209
-
`cursor: pointer`
210
-
`special attributes : href`
211
-
This role is meant to emulate the behaviour of a regular html link.
212
-
It should be used in combination with something that will trigger navigation on click.
213
-
Just like the button one, it is accessible to all kind of user.
140
+
```jsx
141
+
<A11y role="link" href="https://url.com".../>
142
+
```
143
+
144
+
Uses the `pointer` cursor. Special attributes: `href`.
145
+
146
+
This role is meant to emulate the behaviour of a regular html link. It should be used in combination with something that will trigger navigation on click.
214
147
215
148
```diff
216
149
- Don't forget to provide the href attribute as he is required for screen readers to read it correctly !
@@ -226,9 +159,7 @@ In order to provide informations to screen reader users and use this package at
226
159
Use a custom tabindex with for your A11y components by providing a number to the tabIndex attribute
227
160
228
161
```jsx
229
-
<A11y tabIndex={2}>
230
-
<My3DSquare />
231
-
</A11y>
162
+
<A11y tabIndex={2} .../>
232
163
```
233
164
234
165
More about the use of tabIndex on <ahref="https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex">developer.mozilla.org</a>
0 commit comments