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:
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.
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.
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:
"left" | "right"
"above" | "below"
So here's a general flow:
defaultPosition="below"
"top"
This same flow will be applied to all positions and seems to work fairly nicely.
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:
rmd-tooltip-dense
mixin along with a media querydense
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.
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.
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.
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.
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 Fragment
s. 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.
This text will have a tooltip, but it will be inaccessible for keyboard users.
{
"tooltip": "ReactNode",
"id": "string",
"aria-describedby": "string",
"onClick": "function",
"onMouseEnter": "function",
"onMouseLeave": "function",
"onFocus": "function",
"onBlur": "function",
"onKeyDown": "function",
"onTouchStart": "function",
"onContextMenu": "function"
}