Skip to main content
react-md
react-md - Tooltip - Demos

Tooltip

Tooltips are used to help add additional information to users when an element is hovered, keyboard focused, or long-touched and are generally used alongside icon buttons. The tooltips within react-md have been developed to follow the tooltip role even though it is still a work in progress. This means that the id prop will be required for the tooltip's container element as well as the tooltip so that an aria-describedby attribute can be correctly applied.

Once a tooltip becomes visible, it will automatically hide when:

  • the browser window is blurred
  • the user starts scrolling the page
  • an element on the page is clicked
  • escape key closes the tooltip (if the tooltip became visible via keyboard)

Tooltip Hook Example

Starting with react-md@2.8.0, the @react-md/tooltip package exports the useTooltip hook which allows you to implement custom tooltip behavior. The example below will show the most common use case for this hook.

You can also check out the TooltipHookOptions and TooltipHookReturnValue for additional documentation.

Simple Examples

You can use the Tooltipped component which will apply the required accessibility props and event handlers to show and hide the tooltip for you. The tooltip can be positioned "above", "below", "left", or "right" relative to the container element.

If you are on mobile, you will notice that the "left" and "right" tooltips below are positioned incorrectly or out of the viewport. Do not worry! Check out the next example about auto positioning tooltips.

Auto Positioning Tooltips

When using a tooltip, you can set the position manually by providing a position prop. One of the downsides to this is that if the container element is near the edge of the viewport and the tooltip is too big, the tooltip will not fit in the page! This is where auto positioning tooltips come in.

To use this feature, just remove the position prop or define a custom defaultPosition. The tooltip will now automatically determine the "best" location to render itself within the viewport relative to the container element. Sounds too good to be true, right? The way that it'll work is that if the position will swap between the same types:

  • horizontal: "left" | "right"
  • vertical: "above" | "below"

So here's a general flow:

  • defaultPosition="below"
  • tooltip show event is triggered
    • the tooltip container element's position within the viewport is checked. If it's within the lower bounds of the viewport (25% default), it'll swap the position to "top"
  • the tooltip animation starts
    • the tooltip's size is now added to the positioning calculation. If it wasn't swapped and it is now too big, it'll swap positions.
  • the tooltip is still too big?
    • this is a really uncommon case since tooltips should be fairly short, but if the tooltip can't be positioned within the viewport because it is larger than the viewport size, it'll be set to span the entire viewport with some margin instead.

This same flow will be applied to all positions and seems to work fairly nicely.

Dense Tooltips

Tooltips can also use a dense spec which will shrink the amount of padding and the font-size. This is actually enabled for the entire documentation site by default, but it can be used in two different ways:

  1. Using the rmd-tooltip-dense mixin along with a media query
  2. Providing the dense prop to the tooltip.

My recommended way is using the media query approach along with the @react-md/utils package:

12345678@import "~@react-md/tooltip/dist/mixins";
@import "~@react-md/utils/dist/mixins";

:root {
  @rmd-utils-desktop-media {
    @include rmd-tooltip-dense;
  }
}

Note that the dense spec is applied to the :root selector and not some class. This is because tooltips are portalled by default to fix overflow issues and making positioning within the viewport easier.

This is nice since you can also update a lot of the other components that have a dense spec in one area.

Using the dense prop can be used, but you will need to create a "global" state using React Context, redux, or your thing of choice and apply it to each element in your app. This also makes SSR a bit more difficult since if you "guessed" the device size incorrectly based on the user agent or something else, you'll have a DOM mismatch.

This example below will disable the auto dense mode that is enabled throughout the app and show the differences using the dense prop instead.

Normal
Dense

Large Tooltips

Tooltips will automatically have a max-width applied to them of 15rem by default. This value can always be updated by changing the $rmd-tooltip-max-width value or using the rmd-tooltip-update-var mixin.

This example will show how tooltips will automatically line-wrap if there is too much content. This is also a good example on mobile for how to handle tooltips that can't be positioned fully in the viewport above or below the container element.

Hover Mode

Tooltips can also be updated to have a "hover mode" so that subsequent tooltips are shown immediately instead of requiring the default delay. After no tooltips have been shown via mouse for a few seconds, the "hover mode" will be disabled and the initial hover delay will be used again. This feature is actually enabled throughout the app but disabled for these demos to help show the default tooltip behavior.

To hook into the hover mode, all you need to do is use the HoverModeProvider component from @react-md/utils as a parent of all the elements that have tooltips. The component can either be at the root of your app, or a small section so that only a few tooltips are "linked together" with this hover mode flow.

Common Patterns

Since tooltips are normally used with buttons, you will probably want to create a new Button component in your app that will automatically apply a tooltip if the tooltip prop is provided. Check out the example below with TooltippedButton component. You can apply this pattern to any other common component in your app to have tooltips when needed.

Advanced API and Gotchas

All the examples above might have seen like "magic" for how the tooltip events are added to the child component. The way the tooltip works is that it clones the child element and injects the required accessibility props and event handlers into it for convenience. This means that if your component doesn't accept the required event handlers and pass it down to a DOM node or the DOM node is not focusable, the tooltip won't work!

This normally happens when you create a custom component in your app, add a tooltip to some Text instead of a focusable element, or using Fragments. In these cases, you can use the "advanced API" of using the children renderer pattern. The examples below will show a few "gotchas" with the tooltips and an example of the children renderer pattern by printing out the props and adding the tooltip to a button.

Broken Tooltip

This text will have a tooltip, but it will be inaccessible for keyboard users.

Children Renderer
{
  "tooltip": "ReactNode",
  "id": "string",
  "aria-describedby": "string",
  "onClick": "function",
  "onMouseEnter": "function",
  "onMouseLeave": "function",
  "onFocus": "function",
  "onBlur": "function",
  "onKeyDown": "function",
  "onTouchStart": "function",
  "onContextMenu": "function"
}