Back to Fluentui

Component labelling

apps/public-docsite-v9/src/Concepts/Accessibility/ComponentLabelling.mdx

4.40.2-hotfix213.1 KB
Original Source

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" />

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.

Prefer reusing visible text for labels

Type of exampleCodeScreen reader narration (JAWS)Example
Badaria-label="Remove Robert Tolbert" applied on button"Remove Robert Tolbert Button To activate press spacebar."
Good
  • The id="userNameId" applied on the span element with user name.
  • The id="removeButtonId" applied on the "Remove" button.
  • The 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>

Form fields labelling

Type of exampleCodeScreen reader narration (JAWS)Example
BadEach 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."
GoodThe "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>

Avoid action in accessibility name

Type of exampleCodeScreen reader narration (JAWS)Example
Badaria-label="**Click here** to send message""**Click here** to send message button"
Goodaria-label="Send message ""Send message button"

Explanation

  • Adding the action instruction (such as "Click here to...") to the component accessible name prolongs the name narration by the screen reader when the component is focused. This information is already known to the screen reader user based on the type of component beeing used, i.e. a button in this case.
  • Verify the component uses the proper HTML element or the proper ARIA role, so that the component type can be recognized by the screen reader.

Avoid component type in accessibility name

Type of exampleCodeScreen reader narration (JAWS)Example
Badaria-label="Mute microphone **button**""Mute microphone **button** button"
Goodaria-label="Mute microphone""Mute microphone button"

Explanation

  • Adding the component type (such as "button") to the component accessible name duplicates information that is already automatically narrated by the screen reader when the component is focused.
  • Verify the component uses the proper HTML element or the proper ARIA role, so that the component type can be recognized and automatically narrated by the screen reader.

Avoid state in accessibility name

Type of exampleCodeScreen reader narration (JAWS)Example
Badaria-label="Files tab **is active**" applied on the "Files" tab"Files tab **is active** tab selected 2 of 3"
Goodno 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

Avoid position in accessibility name

Type of exampleCodeScreen reader narration (JAWS)Example
BadA custom "X of Y" position information is hard-coded manually as the part of each menu item's "aria-label" attribute value.
  • "Profile menu Account settings..., **first item of four.** To move through items press up or down arrow."{' '} {' '}* "Change status message..., **second item of four**"
  • "Help, **third item of four**"
  • "Sign out, **fourth item of four**"

| | | 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"). |

  • "Profile menu Account settings..., 1 of 4. To move through items press up or down arrow."
  • "Change status message..., 2 of 4"
  • "Help, 3 of 4"
  • "Sign out, 4 of 4"

| |

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>

Avoid repeating text for component inner items

Type of exampleCodeScreen reader narration (JAWS)Example
Badaria-label="**Meeting participant** [user name]" applied on each menu item element.
  • "Participants menu **Meeting participant** Robert Tolbert 1 of 3 To move through items press up or down arrow."
  • "**Meeting participant** Celeste Burton 2 of 3"
  • "**Meeting participant** Cecil Folk 3 of 3"

| | | Good |

  • No "aria-label" attribute is needed for each menu item element.
  • The aria-label="Meeting participants" applied on the menu element.

|

  • "Meeting participants menu Robert Tolbert 1 of 3 To move through items press up or down arrow."
  • "Celeste Burton 2 of 3"
  • "Cecil Folk 3 of 3"

| |

Explanation

  • Adding a repeating text as a part of the accessible name of each item in the component prolongs the name narration by the screen reader so the user needs to wait for the important content to be narrated.
  • Recommendation would be to label the component (menu in our example) with appropriate name.
  • This general principle is valid as well for other components like Tree, List, Listbox, Toolbar, etc.

Avoid making text focusable

Type of exampleCodeScreen reader narrationExample
Badtabindex="0" applied on the text element. When the user presses the TAB key, the text receives focus.
  • the text is focused: "With this option, notifications won’t be displayed anymore. You can miss information about latest news."{' '} {' '}* the button is focused: "Submit Button To activate press Enter. "

| | | 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".

  • The `button` has the aria-describedby="notificationText" attribute. **Example 2:** `Button` is wrapped with the `div` element. It has role="group" and label. {' '}

|

  • {' '} Example No. 1: "Submit Button
    Display notification check box not checked
    With this option, notifications won’t be displayed anymore. You can miss information about latest news."

{' '}* 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>