Tooltip

Tooltips reveal contextual information about an element on hover.

yarn add @workday/canvas-kit-react
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.

Component API

Tooltip

Props

Props extend from div. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
titleReactNode

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

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

placement

Sets the placement preference used by PopperJS.

'top'
fallbackPlacements[]

Define fallback placements by providing a list of in array (in order of preference). The default preference is following the order of top, right, bottom, and left. Once the initial and opposite placements are not available, the fallback placements will be in use. Use an empty array to disable the fallback placements.

type 'label' 'describe' 'muted'

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

'label'
showDelaynumber

Amount of time (in ms) to delay before showing the tooltip

300
hideDelaynumber

Amount of time (in ms) to delay before hiding the tooltip

100
asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

div
refReact.Ref<R = div>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

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
                    the TooltipWithFallbackPlacements example is rendered
                    • check the fallback placements the preferred placement is set to top
                    • it should show the fallback placement: bottom
                    the TooltipWithFallbackPlacements example is rendered
                    • check the fallback placements the preferred placement is set to left
                    • it should show the fallback placement: right
                    the TooltipWithFallbackPlacements example is rendered
                    • check the fallback placements the preferred placement is set to left
                    • it should show the fallback placement: bottom
                    Source: Tooltip.spec.ts

                    Accessibility Guidelines

                    How Tooltips Impact the Accessible Experience

                    Tooltip “hover” text is a great way to help users understand the intent of ambiguous icons, and provide further detail about some elements in a design. A hovering interaction however, is not going to be available to all users at all times. Mobile devices don’t support hovering interactions, and desktop users may not be willing or able to use a pointing device to hover on an element.

                    Alternatives to the hover interaction must be considered, and tooltip content must be displayed visually on keyboard focus. Tooltips can be used for showing truncated text, but only in scenarios where the keyboard can focus the component. Applying tooltips to truncated heading or paragraph text will lead to accessibility problems.

                    Refer to tooltips and toasts for more information about writing tooltip content.

                    Keyboard Interaction

                    Tooltips must only be used on elements that can be focused with the keyboard. Sighted users must be able to access the content in a tooltip without the use of a mouse.

                    Tooltips must support the following keyboard interactions:

                    • Tab: focuses an element, tooltip displays when element is focused
                    • Esc: dismiss tooltip

                    Screen Reader Interaction

                    Tooltips must communicate the following to users:

                    • The text content of the tooltip as the name of an element (default)
                    • The text content of the tooltip as an element’s description (describe)
                    • Nothing, when the tooltip text content matches text content already on screen. (muted)

                    Design Annotations Needed

                    • Specify which tooltip variant should be used: default, describe, or muted.

                    Implementation Markup Needed

                    • [Included in component] Default tooltips will set an aria-label string to the element.
                    • [Included in component] Describe variant will instead set an aria-describedby attribute to the element, referencing an id of the tooltip text content.
                    • [Included in component] Muted variant will be hidden from screen readers and other assistive technology.

                    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