@ -142,18 +142,25 @@ we need to programmatically nudge the keyboard focus in the right direction. For
MDN Web Docs takes a look at this and describes how we can build [keyboard-navigable JavaScript widgets](https://developer.mozilla.org/en-US/docs/Web/Accessibility/Keyboard-navigable_JavaScript_widgets).
MDN Web Docs takes a look at this and describes how we can build [keyboard-navigable JavaScript widgets](https://developer.mozilla.org/en-US/docs/Web/Accessibility/Keyboard-navigable_JavaScript_widgets).
To set focus in React, we can use [Refs to DOM elements](refs-and-the-dom.html).
To set focus in React, we can use [Refs to DOM elements](/docs/refs-and-the-dom.html).
Using this, we first create a ref to an element in the JSX of a component class:
Using this, we first create a ref to an element in the JSX of a component class:
```javascript{2-3,7}
```javascript{4-5,8-9,13}
render() {
render() {
constructor(props) {
super(props);
// Create a ref to store the textInput DOM element
this.textInput = React.createRef();
}
// ...
// Use the `ref` callback to store a reference to the text input DOM
// Use the `ref` callback to store a reference to the text input DOM
// element in an instance field (for example, this.textInput).
// element in an instance field (for example, this.textInput).
return (
return (
<input
<input
type="text"
type="text"
ref={(input) => { this.textInput = input; }} />
ref={this.textInput}
/>
);
);
}
}
```
```
@ -163,33 +170,44 @@ Then we can focus it elsewhere in our component when needed:
```javascript
```javascript
focus() {
focus() {
// Explicitly focus the text input using the raw DOM API
// Explicitly focus the text input using the raw DOM API
this.textInput.focus();
// Note: we're accessing "current" to get the DOM node
this.textInput.current.focus();
}
}
```
```
Sometimes a parent component needs to set focus to an element in a child component. Although we can create [refs to class components](refs-and-the-dom.html#adding-a-ref-to-a-class-component),
Sometimes a parent component needs to set focus to an element in a child component. We can do this by [exposing DOM refs to parent components](/docs/refs-and-the-dom.html#exposing-dom-refs-to-parent-components)
we need a pattern that also works with functional components and when [using refs with HOCs](higher-order-components.html#refs-arent-passed-through).
through a special prop on the child component that forwards the parent's ref to the child's DOM node.
To ensure that our parent component can always access the ref, we pass a callback as a prop to the child component to [expose the ref to the parent component](refs-and-the-dom.html#exposing-dom-refs-to-parent-components).
```javascript{4,12,16}
```js
function CustomTextInput(props) {
// Expose the ref with a callback prop
return (
function Field({ inputRef, ...rest }) {
<div>
return <inputref={inputRef}{...rest}/>;
<inputref={props.inputRef}/>
</div>
);
}
}
// Inside a parent class component's render method...
class Parent extends React.Component {
<Field
constructor(props) {
inputRef={(inputEl) => {
super(props);
// This callback gets passed through as a regular prop
this.inputElement = React.createRef();
this.inputEl = inputEl
}
}}
render() {
return (
<CustomTextInputinputRef={this.inputElement}/>
);
}
}
/>
/>
// Now you can set focus when required.
// Now you can set focus when required.
this.inputEl.focus();
this.inputElement.current.focus();
```
```
A great focus management example is the [react-aria-modal](https://github.com/davidtheclark/react-aria-modal). This is a relatively rare example of a fully accessible modal window. Not only does it set initial focus on
When using a HOC to extend components, it is recommended to [forward the ref](/docs/forwarding-refs.html) to the wrapped component using the `forwardRef` function of React. If a third party HOC
does not implement ref forwarding, the above pattern can still be used as a fallback.
A great focus management example is the [react-aria-modal](https://github.com/davidtheclark/react-aria-modal). This is a relatively rare example of a fully accessible modal window. Not only does it set initial focus on
the cancel button (preventing the keyboard user from accidentally activating the success action) and trap keyboard focus inside the modal, it also resets focus back to the element that
the cancel button (preventing the keyboard user from accidentally activating the success action) and trap keyboard focus inside the modal, it also resets focus back to the element that
initially triggered the modal.
initially triggered the modal.
@ -203,7 +221,7 @@ initially triggered the modal.
A more complex user experience should not mean a less accessible one. Whereas accessibility is most easily achieved by coding as close to HTML as possible,
A more complex user experience should not mean a less accessible one. Whereas accessibility is most easily achieved by coding as close to HTML as possible,
even the most complex widget can be coded accessibly.
even the most complex widget can be coded accessibly.
Here we require knowledge of [ARIA Roles](https://www.w3.org/TR/wai-aria/#roles) as well as [ARIA States and Properties](https://www.w3.org/TR/wai-aria/#states_and_properties).
Here we require knowledge of [ARIA Roles](https://www.w3.org/TR/wai-aria/#roles) as well as [ARIA States and Properties](https://www.w3.org/TR/wai-aria/#states_and_properties).
These are toolboxes filled with HTML attributes that are fully supported in JSX and enable us to construct fully accessible, highly functional React components.
These are toolboxes filled with HTML attributes that are fully supported in JSX and enable us to construct fully accessible, highly functional React components.
Each type of widget has a specific design pattern and is expected to function in a certain way by users and user agents alike:
Each type of widget has a specific design pattern and is expected to function in a certain way by users and user agents alike:
@ -285,7 +303,7 @@ test the technical accessibility of your HTML.
#### aXe, aXe-core and react-axe
#### aXe, aXe-core and react-axe
Deque Systems offers [aXe-core](https://www.deque.com/products/axe-core/) for automated and end-to-end accessibility tests of your applications. This module includes integrations for Selenium.
Deque Systems offers [aXe-core](https://github.com/dequelabs/axe-core) for automated and end-to-end accessibility tests of your applications. This module includes integrations for Selenium.
[The Accessibility Engine](https://www.deque.com/products/axe/) or aXe, is an accessibility inspector browser extension built on `aXe-core`.
[The Accessibility Engine](https://www.deque.com/products/axe/) or aXe, is an accessibility inspector browser extension built on `aXe-core`.