Tooltip

Tooltips reveal contextual information about an element on hover.

GitHubStorybook
yarn add @workday/canvas-kit-react
Sources
GitHubStorybook
Install
yarn add @workday/canvas-kit-react

Anatomy

Image of a Tooltip

  1. Container: A rectangular frame that holds the tooltip text.
  2. Text: A description of what the element is in which the mouse pointer is hovering over.

Usage Guidance

  • Tooltips provide relevant and descriptive information about an element.
  • They appear when a user hovers over or interacts with the related element.
  • Tooltip text should be descriptive, yet short and succinct.
  • Tooltips should always be positioned next to the element it is connected to. The Tooltip’s position will vary depending on where the element is in relation to the edge of the screen.

When to Use

Examples

This component follows the W3 Tooltip specification. Tooltips are used to label buttons with icons and provide additional context to elements.

When to use tooltips

Use a tooltip when you want to display additional information for users to better understand the purpose, context, or interaction.

When not to use tooltips

When the visual text will be the exact same as what is visually displayed to the user without the tooltip being visible

  • Does this element need additional context or information?
    • No: Don't use a tooltip
    • Yes:
      • Is the tooltip text useful to screen reader users?
        • No: Use type="muted" which will not make the tooltip visible to screen reader users
        • Yes:
          • Is the tooltip text different from the visual text displayed to users?
            • No text: Use type="label" which will add aria-label like the icon example
            • Yes: Use type="describe" which will add aria-describedby
            • No: Don't use a tooltip

Basic Example

Here is a basic example of a TertiaryButton that renders an icon using a tooltip to label the icon. This labels the button for both sighted users and screen readers. A tooltip provides an aria-label to child elements for the accessibility tree and a visual tooltip during mouse hover and focus events.

Describing an Element

The default mode for a tooltip is to label content via aria-label. If a tooltip is meant to provide ancillary information, the type can be set to describe. This will add aria-describedby to the target element. This will allow screen reader users to hear the name of the control that is being focused and the ancillary tooltip information.

Muted Tooltips

If a tooltip does not need to be visible to screen reader users, or you handle accessibility of the tooltip yourself, you can set the type to muted. This will not add any special ARIA attributes to the target element.

Some text. The contents of the tooltip are invisible to screen reader users.

Custom Content

A tooltip can contain HTML, but should not contain any focusable elements or semantically meaningful formatting. The content will lose all semantic meaning when read by a screen reader. If complex content or a focusable element is needed by your UI, a tooltip is not a good choice. Consider using a dialog instead.

Delayed Tooltip

The default delay for showing and hiding a tooltip are 300ms and 100ms, respectively. You can control the length of the delay by providing custom showDelay and hideDelay in ms.

Placements

The tooltip allows for a placement configuration. The tooltip uses PopperJS to position tooltips, so any valid PopperJS placement is valid for tooltips.

top-start
top
top-end
left-start
left
left-end
right-start
right
right-end
bottom-start
bottom
bottom-end

Tooltips on overflowing content

The OverflowTooltip component can be applied to any element that has some type of overflow applied, or has a child element that has overflow applied. The most common and widely supported type of truncation is the ellipsis.

overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;

Note: Text truncation should be avoided if possible. A user should not have to activate a tooltip to access important content. If user-generated content is being truncated, the following situation might occur which is a bad user experience. Consider the following list:

  • Home Site A
  • Home Site B
  • Home Site C

If the list items get truncated via an ellipsis, this is what the user could see:

  • Home Sit...
  • Home Sit...
  • Home Sit...

Here are suggestions to try to avoid truncation:

  • Allow content to wrap instead
  • Limit character count in admin interfaces if possible to avoid need for truncation
  • Avoid fixed container sizes if possible to allow content to flow naturally

If truncation is required, here are a few guidelines to insure minimal impact on users:

  • Only truncate text of elements that naturally receive focus.
    • Keyboard users can only activate tooltips with focus. Adding tabindex=0 can give focus to non-focusable elements, but increase the amount of tab stops for keyboard users.
  • Provide the full content elsewhere in the UI

Canvas Kit Buttons have this style applied to the text inside them. OverflowTooltip in combination with a max-width can show a tooltip only when overflow is detected:

Line Clamp

The OverflowTooltip can support various types of overflow. The component will first look for text-overflow: ellipsis and -webkit-line-clamp, but will fall back to overflow: auto | scroll | clip | hidden. These properties will be used to determine which element is experiencing an overflow. Overflow detection is as follows where element is determined by the above style properties:

element.scrollWidth > element.clientWidth || element.scrollHeight > element.clientHeight;

Here's an example using the -webkit-line-clamp property (multi-line ellipsis which works in all browsers):

Other truncation techniques should be supported as well, even JavaScript ones as long as overflow is triggered somehow and detectable differences in scroll size and client size.

The UseTooltip Hook

The Tooltip component is a combination of the TooltipContainer (a styled element), Popper (which uses PopperJS and the popup stack), the useTooltip hook and some behavior. If custom behavior is required, these sub-components can be composed in a custom container element. This example uses those parts directly while being functionally equivalent to the original basic example.

Props

NameTypeDefaultDescription
title*ReactNodeThis should be a string in most cases. HTML is supported, but only text is understood by assistive technology. This is true for both `label` and `describe` modes.
children*ReactElement<any, string | JSXElementConstructor<any>>The target (anchor element) for the Tooltip. **Note:** This **must** be a single Element, StyledComponent, or any other component that forwards extra props to an Element. Tooltip works running `React.cloneElement` on the children and adds extra properties like aria attributes and event handlers. This is currently a limitation of the Tooltip component. Functionality will not work if this condition isn't met.
placementPlacement | undefinedtopSets the placement preference used by PopperJS.
type"label" | "describe" | "muted" | undefinedlabelDetermines the tooltip type for accessibility. - `label`: Sets the accessible name for the wrapped element. Use for icons or if tooltip `title` prop is the same as the text content of the wrapped element. E.g. TertiaryButtons that render an icon or Ellipsis tooltips. - `describe`: Sets `aria-describedby` of the wrapped element. Use if the tooltip has additional information about the target. - `muted`: No effort is made to make the tooltip accessible to screen readers. Use if the tooltip contents are not useful to a screen reader or if you have handled accessibility of the tooltip yourself. **Note**: Assistive technology may ignore `describe` techniques based on verbosity settings. Consider an alternate way to inform a user of additional important information.
showDelaynumber | undefined300Amount of time (in ms) to delay before showing the tooltip
hideDelaynumber | undefined100Amount of time (in ms) to delay before hiding the tooltip

Specifications

GivenWhenThen
the Default example is rendered
    • it should not have any axe-core errors
    the Default example is rendered
      • the button should have an aria-label of "Close"
      the Default example is rendered
      • the close icon is hovered
      • it should open the tooltip
      the Default example is rendered
      • the close icon is hovered
      • it should not have any axe-core errors
      the Default example is rendered
      • the close icon is hovered
      • AND THEN the tooltip is hovered
      • it should not close the tooltip
      the Default example is rendered
      • the close icon is hovered
      • AND THEN the Escape key is pressed
      • it should close the tooltip
      the Default example is rendered
      • the close icon is hovered
      • AND THEN the target is clicked
      • it should not close the tooltip
      the Default example is rendered
      • the close icon gains focus
      • it should open the tooltip
      the Default example is rendered
      • the close icon gains focus
      • AND THEN the close icon loses focus
      • it should close the tooltip
      the Default example is rendered
      • the close icon gains focus
      • AND THEN the Escape key is pressed
      • it should not remove focus from the close icon button
      the Default example is rendered
      • the close icon gains focus
      • AND THEN a click happens outside both tooltip and icon button
      • it should close immediately, not waiting for blur or intent
      the Describe Type example is rendered
        • it should not have any axe-core errors
        the Describe Type example is rendered
          • the "Delete" button should not have an aria-describedby
          the Describe Type example is rendered
          • the "Delete" button is hovered
          • it should show the tooltip
          the Describe Type example is rendered
          • the "Delete" button is hovered
          • it should not have any axe-core errors
          the Describe Type example is rendered
          • the "Delete" button is hovered
          • the "Delete" button should have an aria-describedby linking to the role="tooltip" element
          the Muted example is rendered
            • it should not have any axe-core errors
            the Muted example is rendered
              • the span element should not have an aria-describedby attribute
              the Muted example is rendered
                • the span element should not have an aria-label attribute
                the Muted example is rendered
                • the "Some Text" text is hovered
                • it should show the tooltip
                the Muted example is rendered
                • the "Some Text" text is hovered
                • it should not have any axe-core errors
                the Muted example is rendered
                • the "Some Text" text is hovered
                • the span element should not have an aria-describedby attribute
                the Muted example is rendered
                • the "Some Text" text is hovered
                • the span element should not have an aria-label attribute
                the Ellipsis example is rendered
                  • it should not have any axe-core errors
                  the Ellipsis example is rendered
                    • the button should not have an aria-label
                    the Ellipsis example is rendered
                    • the "Short Content" button is hovered
                    • it should not show the tooltip
                    the Ellipsis example is rendered
                    • the "Super Mega Ultra Long Content With Max Width On The Button" button is hovered
                    • it should show the tooltip
                    the Ellipsis example is rendered
                    • the "Super Mega Ultra Long Content With Max Width Custom" button is hovered
                    • it should show the tooltip
                    the Ellipsis example is rendered
                    • the "Short Content" button is focused
                    • it should not show the tooltip
                    the Ellipsis example is rendered
                    • the "Super Mega Ultra Long Content With Max Width On The Button" button is focused
                    • it should show the tooltip
                    the Ellipsis example is rendered
                    • the "Super Mega Ultra Long Content With Max Width Custom" button is focused
                    • it should show the tooltip
                    the Non Interactive example is rendered
                    • the "Non-interactive Tooltip" text is hovered
                    • it should open the tooltip
                    the Non Interactive example is rendered
                    • the "Non-interactive Tooltip" text is hovered
                    • AND THEN the "Non-interactive Tooltip" text is clicked
                    • it should not close the tooltip
                    the Overflow example is rendered
                    • the = button is hovered
                    • it should open the tooltip
                    Source: Tooltip.spec.ts

                    Accessibility Guidelines

                    • The Tooltip must be displayed when a user interacts with the related element.
                    • Tooltip text must be announced to a screen reader user when a user interacts with the related element.

                    Content Guidelines

                    Keep tooltips brief. Tooltips should not text wrap or span more than a single line. Try to keep Tooltips understandable and clear for users by adding context to the element through simple combinations of nouns and verbs, such as “Add Item” over a Plus icon or “Close” over an X icon. For more information on writing Tooltip text, see the Tooltips and Toasts section of the content style guide.

                    Do

                    Use simple language and avoid text wrapping for Tooltip text.

                    Don't

                    Use confusing language such as present perfect tense or include unnecessary words when ‘expense submitted’ provides enough context for the action.

                    Can't Find What You Need?

                    Check out our FAQ section which may help you find the information you're looking for.

                    FAQ Section