apps/public-docsite-v9/src/Concepts/Accessibility/ComponentLabelling.mdx
import { Meta } from '@storybook/addon-docs/blocks'; import { ActionAvoidBad, ActionAvoidGood, ComponentTypeAvoidBad, ComponentTypeAvoidGood, StateAvoidBad, StateAvoidGood, CustomPositionAvoidBad, CustomPositionAvoidGood, TextRepeatAvoidBad, TextRepeatAvoidGood, FocusTextAvoidBad, FocusTextAvoidGood, ReuseVisibleTextBad, ReuseVisibleTextGood, } from './LabellingExamples/Examples.stories';
import { FormErrorLabelBad, FormErrorLabelGood } from './LabellingExamples/ExampleFormErrorsMessages.stories'; import { Link } from '@fluentui/react-components';
<Meta title="Concepts/Developer/Accessibility/Component labelling" />Label should be clear and sufficiently explain the purpose of the component. It should not contain component type, role, action, state, position and repeating text. To understand more right labelling please see examples below.
| Type of example | Code | Screen reader narration (JAWS) | Example |
|---|---|---|---|
| Bad | aria-label="Remove Robert Tolbert" applied on button | "Remove Robert Tolbert Button To activate press spacebar." | |
| Good |
id="userNameId" applied on the span element with user name.id="removeButtonId" applied on the "Remove" button.aria-labelledby="removeButtonId userNameId" applied on button.| "Remove Robert Tolbert Button To activate press spacebar." | |
Explanation
<ul> <li>Even though the screen reader narration is the same for both examples, implementation is different.</li> <li>In general, for labelling we should reuse information that is visible/displayed in the UI.</li> <li> In this particular example, the aria-label attribute was added to the "Remove" button, and then, using the aria-labelledby attribute on the same button, we can refer to the "Remove" button itself. </li> <li> The approach when a component refers to itself with the aria-labelledby attribute was taken from <Link href="https://www.w3.org/TR/accname-1.1/#terminology" inline> Accessible Name and Description Computation 1.1 page. </Link> To find the example on that page, go to "4.3.1 Terminology{'>'} 2B {'>'} Example" </li> </ul>| Type of example | Code | Screen reader narration (JAWS) | Example |
|---|---|---|---|
| Bad | Each form field is not connected to its corresponding error message. | Full name field with invalid content (type only mumbers): | |
| "Full name, Edit, Required, invalid entry, [field-content], Type in text." | |||
| Good | The "aria-describedby" applied on each input field and references the corresponding error message element. | Full name field with invalid content (type only mumbers): | |
| "Full name, Edit, Required, invalid entry, [field-content], Full name is invalid. It must: Contain only lowercase or uppercase letters, spaces or hyphens. Start and end wit letter." |
Explanation
<ul> <li> Each form field should be referencing the corresponding error message element using the "aria-describedby" attribute. This ensures that whenever the form field is focused, the error message is narrated by the screen reader. </li> </ul>| Type of example | Code | Screen reader narration (JAWS) | Example |
|---|---|---|---|
| Bad | aria-label="**Click here** to send message" | "**Click here** to send message button" | |
| Good | aria-label="Send message " | "Send message button" |
Explanation
| Type of example | Code | Screen reader narration (JAWS) | Example |
|---|---|---|---|
| Bad | aria-label="Mute microphone **button**" | "Mute microphone **button** button" | |
| Good | aria-label="Mute microphone" | "Mute microphone button" |
Explanation
| Type of example | Code | Screen reader narration (JAWS) | Example |
|---|---|---|---|
| Bad | aria-label="Files tab **is active**" applied on the "Files" tab | "Files tab **is active** tab selected 2 of 3" | |
| Good | no aria-label attribute is needed for the "Files" tab | "Files tab selected 2 of 3" |
Explanation
<ul> <li> Adding a custom hard-coded state to the accessible name of the component is not required, because this information will be provided by the screen reader if the component has the proper state attribute. </li> <li> If the state of component is not narrated by the screen reader, verify the proper ARIA state attribute is used, such as `aria-checked`, `aria-selected`, `aria-pressed`, `aria-current`, ... See latest* <Link href="https://www.w3.org/TR/wai-aria/" inline> aria documentation </Link> for these attributes. </li> </ul>*In time
| Type of example | Code | Screen reader narration (JAWS) | Example |
|---|---|---|---|
| Bad | A custom "X of Y" position information is hard-coded manually as the part of each menu item's "aria-label" attribute value. |
| | | Good | The "X of Y" position information is added automatically by the screen reader for each menu item because the correct ARIA role is used both for all individual menu item elements (role="menuitem") and the parent menu element (role="menu"). |
| |
Explanation
<ul> <li> Even though the screen reader narration might seem similar, don't hard-code a custom "X of Y" position information manually as the part of the accessible name of each individual item, but instead use proper ARIA roles and let the screen reader add the "X of Y" information for you. </li> <li> The JAWS screen reader currently supports the "X of Y" information for the following roles: "listbox", "menu", "tablist", "tree", "radiogroup", "grid", "treegrid", ... See the{' '} <a href="https://www.w3.org/TR/wai-aria/">ARIA specification</a> to learn which required owned elements (such as "option", "menuitem", "tab", "treeitem", etc.) should be used with these roles. </li> </ul>| Type of example | Code | Screen reader narration (JAWS) | Example |
|---|---|---|---|
| Bad | aria-label="**Meeting participant** [user name]" applied on each menu item element. |
| | | Good |
|
| |
Explanation
| Type of example | Code | Screen reader narration | Example |
|---|---|---|---|
| Bad | tabindex="0" applied on the text element. When the user presses the TAB key, the text receives focus. |
| | | Good |
{' '}* The text is not focusable anymore, because the "tabindex" attribute does not exist on the text element. **Example 1:** The text element has a unique id, like "notificationText".
|
{' '}* Example No. 2: "Summary of your order group
Buy Button"
| |
Explanation
<ul> <li> In general, elements (like text) that are not actionable should not receive focus, because it adds an additional TAB stop in the TAB order. </li> <li> {' '} Refer to the text element via the "aria-describedby" attribute, which ensures the text would be read by the screen reader whenever the actionable element which has the "aria-describedby" attribute is focused. </li> <li> Wrap the component with an element which has role="group" and use aria-label or aria-labelledby to set or reference the text you want to narrate. Then the element label will be narrated when the component is focused using the Tab key. </li> </ul>