Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(Tooltip): add a11y docs #2892

Merged
merged 7 commits into from
Jul 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 164 additions & 0 deletions packages/v4/patternfly-docs/content/accessibility/tooltip/tooltip.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
---
id: Tooltip
section: components
---

import { Checkbox, List, ListItem } from '@patternfly/react-core';

## Accessibility

To implement an accessible PatternFly **tooltip**:

- Avoid using tooltips on static elements such as a `div` or `span`, except in cases of truncation.

For the PatternFly React library:

- Pass in `aria="labelledby"` to the tooltip component when the tooltip should act as the primary label for its trigger:
```noLive
<Tooltip content="Copy to clipboard" aria="labelledby">
<button>
<CopyIcon />
</button>
</Tooltip>
```

For the HTML/CSS library:

- Pass in `role="tooltip"` to the element acting as the tooltip component.
- Pass in the `aria-labelledby` attribute to the trigger when the tooltip should act as the primary label for its trigger:
```noLive
<div class="pf-c-tooltip pf-m-top" role="tooltip">
<div class="pf-c-tooltip__arrow"></div>
<div class="pf-c-tooltip__content" id="tooltip-label-content">
Copy to clipboard
</div>
</div>
<button aria-labelledby="tooltip-label-content">
<CopyIcon />
</button>
```
- Pass in the `aria-describedby` attribute to the trigger when the tooltip should act as supplementary information:

```noLive
<div class="pf-c-tooltip pf-m-top" role="tooltip">
<div class="pf-c-tooltip__arrow"></div>
<div class="pf-c-tooltip__content" id="tooltip-description-content">
Supplementary information within a tooltip
</div>
</div>
<button aria-describedby="tooltip-description-content">
Button text label
</button>
```

## Testing

At a minimumm, a tooltip should meet the following criteria:

<List isPlain>
<ListItem>
<Checkbox id="tooltip-a11y-checkbox-1" label="Unless it is a case of truncation, the tooltip is not placed on a static element." />
</ListItem>
<ListItem>
<Checkbox id="tooltip-a11y-checkbox-2" label={<span>The tooltip component has the <code class="ws-code">role="tooltip"</code> attribute.</span>} />
</ListItem>
<ListItem>
<Checkbox id="tooltip-a11y-checkbox-3" label={<span>If the tooltip is meant to act as a primary label, the trigger has the <code class="ws-code">aria-labelledby</code> attribute linked to the tooltip contents.</span>} description="One use-case for this is when a button contains only an icon and no visible text label." />
</ListItem>
<ListItem>
<Checkbox id="tooltip-a11y-checkbox-4" label={<span>If the tooltip is meant to act as supplementary information, the trigger has the <code class="ws-code">aria-describedby</code> attribute linked to the tooltip contents.</span>} />
</ListItem>
<ListItem>
<Checkbox id="tooltip-a11y-checkbox-5" label="Using a mouse to hover over the triggering element causes the tooltip to trigger, and the tooltip persists while hovering over the trigger or the tooltip itself." />
</ListItem>
<ListItem>
<Checkbox id="tooltip-a11y-checkbox-6" label="The triggering element can receive focus via keyboard in order to trigger the tooltip, and the tooltip persists as long as the triggering element has focus." />
</ListItem>
<ListItem>
<Checkbox id="tooltip-a11y-checkbox-7" label="Users navigating via screen reader have the contents of the tooltip announced to them when it is triggered." description="This is best achieved by wrapping the tooltip component around the trigger. This is best checked by using a screen reader." />
</ListItem>
<ListItem>
<Checkbox id="tooltip-a11y-checkbox-8" label="The tooltip can be dismissed without having to move the mouse pointer or remove focus from the trigger." description={<span>This is commonly done by pressing <kbd>Escape</kbd>.</span>} />
</ListItem>
<ListItem>
<Checkbox id="tooltip-a11y-checkbox-9" label="If the tooltip content is no longer valid, the tooltip automatically gets dismissed." />
</ListItem>
</List>

## React customization

Various React props have been provided for more fine-tuned control over accessibility.

| Prop | Applied to | Reason |
|---|---|---|
| `aria-live` | `Tooltip` | When a value of "polite" is passed in, allows assistive technologies to announce the tooltip contents when it is expected or intended to dynamically update, such as in response to a user action. This should only be passed in when the `children` prop is also used on the tooltip. <br/><br/> `aria-live="polite"` is set by default when using the `reference` prop in order to allow assistive technologies to correctly announce tooltip contents regardless if it will dynamically update or not. |
| `aria` | `Tooltip` | When a value of "describedby" (default behavior) or "labelledby" is passed in, allows assistive technologies to announce the tooltip contents when it is triggered. A value of "describedby" sets the trigger's `aria-describedby` attribute and should be used when the tooltip should act as supplementary information. A value of "labelledby" sets the trigger's `aria-labelledby` attribute and should be used when the tooltip should act as a primary label. <br/><br/> When a value of "none" is passed in, prevents `aria-labelledby` and `aria-describedby` from being set on the trigger. Only pass in a value of "none" when either `aria-labelledby` or `aria-describedby` is manually set on the trigger and the `id` prop is manually passed into the tooltip. <br/><br/> This prop should only be passed in when the `children` prop is also used on the tooltip. |
| `id` | `Tooltip` | Sets the `id` attribute on the tooltip, which can be passed in as the value to a trigger's `aria-labelledby` or `aria-describedby` attribute. **Required** when either `aria-labelledby` or `aria-describedby` is manually set on the trigger or when the `reference` prop is passed into the tooltip. |
| `reference` | `Tooltip` | Links the tooltip to a trigger when the `children` prop cannot be used. When passing in this prop, the `id` prop must also be passed in, and either `aria-labelledby` or `aria-describedby` must be set on the trigger with a value of the tooltip's `id`. |

### Aria-live

The following code block shows how you should generally use the `aria-live` prop when the tooltip contents is intended or expected to dynamically update.

```noLive
const [tooltipContent, setTooltipContent] = React.useState("Copy to clipboard");

const onClick = () => {
setTooltipContent('Successfully copied to clipboard!")
}

<Tooltip aria-live="polite" content={tooltipContent}>
<button onClick={onClick}>
<CopyIcon />
</button>
</Tooltip>
```

### Aria

When passing in `aria="none"` in the following code block, the `id` is passed into the tooltip and `aria-labelledby` is passed into the trigger with a value of the tooltip's `id`.

```noLive
<Tooltip id="tooltip-without-aria" aria="none" content="Copy to clipboard">
<button aria-labelledby="tooltip-without-aria">
<CopyIcon />
</button>
</Tooltip>
```

### Reference

When using the `reference` prop in the following code block, a React ref is created and passed into the tooltip and the trigger as the `reference` and `ref` props, respectively. Additionally, the `id` is passed into the tooltip and `aria-labelledby` is passed into the trigger with a value of the tooltip's `id`.

```noLive
const tooltipRef = React.useRef();

<Tooltip id="tooltip-with-reference" content="Copy to clipboard" reference={tooltipRef} />
<button ref={tooltipRef} aria-labelledby="tooltip-with-reference">
<CopyIcon />
</button>
```

## HTML/CSS customization

Various HTML attributes and PatternFly classes can be used for more fine-tuned control over accessibility.

| Attribute or class | Applied to | Reason |
|---|---|---|
| `aria-live="polite"` | `.pf-c-tooltip` | Allows assistive technologies to announce the tooltip contents when it is expected or intended to dynamically update, such as in response to a user action. |
| `id` | `.pf-c-tooltip` | Used to link the tooltip to a trigger by passing in the tooltip's `id` as the value to the trigger's `aria-describedby` or `aria-labelledby` attribute. **Required**. |
| `role="tooltip"` | `.pf-c-tooltip` | Adds a tooltip role to the component. **Required**. |
| `aria-describedby` | element that triggers the tooltip | Allows assistive technologies to announce the tooltip contents when it is triggered. **Required** when the tooltip should act as supplementary information. |
| `aria-labelledby` | element that triggers the tooltip | Allows assistive technologies to announce the tooltip contents when it is triggered. **Required** when the tooltip should act as the primarly label of the trigger. |

## Additional considerations

Consumers must ensure they take any additional considerations when customizing a tooltip, using it in a way not described or recommended by PatternFly, or in various other specific use-cases not outlined elsewhere on this page.

- If a tooltip is added to a trigger that is disabled, the trigger must still be able to receive focus. This can often be achieved by using the `aria-disabled` attribute instead of the `disabled` attribute.

## Further reading

To read more about accessibility with tooltips, refer to the following resources:

- [ARIA Authoring Practices Guide - Tooltip widget](https://www.w3.org/WAI/ARIA/apg/patterns/tooltip/)
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ Both tooltips and [popovers](/components/popover/design-guidelines) provide more
- Don’t use tooltips with question-circle icons to present contextual information in forms and other areas. Instead, use a [popover](/components/popover/design-guidelines).

## Accessibility
Every time a user with a screen reader tabs into a field with a tooltip, the screen reader reads the tooltip aloud.

For information regarding accessibility, visit the [tooltip accessibility](/components/tooltip/accessibility) tab.



Expand Down