Tooltip
Tooltips display informative text when users hover over, focus on, or tap an element.
Simple Example
A tooltip can be created by using the Tooltip component and the useTooltip
hook to handle controlling the visibility. The default behavior will be to show
the tooltip after hovering/focusing/touching for 1 second.
"use client";
import { Button } from "@react-md/core/button/Button";
import { Tooltip } from "@react-md/core/tooltip/Tooltip";
import { useTooltip } from "@react-md/core/tooltip/useTooltip";
import { type ReactElement } from "react";
export default function SimpleTooltipExample(): ReactElement {
const { elementProps, tooltipProps } = useTooltip();
return (
<>
<Button {...elementProps}>Button</Button>
<Tooltip {...tooltipProps}>Tooltip</Tooltip>
</>
);
}
Dense Tooltip
The tooltip can be rendered with a smaller size and spacing from the tooltipped
element by enabling the dense option.
"use client";
import { Button } from "@react-md/core/button/Button";
import { Tooltip } from "@react-md/core/tooltip/Tooltip";
import { useTooltip } from "@react-md/core/tooltip/useTooltip";
import { type ReactElement } from "react";
export default function DenseTooltipExample(): ReactElement {
const { elementProps, tooltipProps } = useTooltip({
dense: true,
});
return (
<>
<Button {...elementProps}>Button</Button>
<Tooltip {...tooltipProps}>Tooltip</Tooltip>
</>
);
}
Long Text Tooltip
Tooltips have a max-width set to 15rem by default but can be configured by
setting the core.$tooltip-max-width Sass variable or through CSS on the
tooltip.
"use client";
import { Button } from "@react-md/core/button/Button";
import { Tooltip } from "@react-md/core/tooltip/Tooltip";
import { useTooltip } from "@react-md/core/tooltip/useTooltip";
import { type ReactElement } from "react";
export default function LongTextTooltipExample(): ReactElement {
const { elementProps, tooltipProps } = useTooltip();
return (
<>
<Button {...elementProps}>Button</Button>
<Tooltip {...tooltipProps}>
Nam laoreet, felis ut commodo tristique, dui lorem iaculis metus, vitae
pharetra ipsum nulla sed mauris. Suspendisse ultrices vel dui id
posuere. Aenean pellentesque urna ac nisi elementum fringilla. Sed quis
vestibulum ex, in auctor lorem. Morbi a elit viverra, dignissim leo at,
accumsan ligula. Aliquam velit ligula, molestie a lorem ut, commodo
hendrerit est. Sed lobortis luctus orci quis ultricies. Nullam luctus
urna quis libero aliquet, non tincidunt augue sagittis. Duis eleifend
ultricies fermentum. Nulla volutpat tempor est, eget hendrerit nisi
sodales vitae.
</Tooltip>
</>
);
}
Tooltip Positioning
The Tooltip will automatically attempt to render itself within the viewport
either above or below the tooltipped element preferring below. The positioning
can be configured by providing the defaultPosition option to the useTooltip
hook as one of the following:
"below"(default) - renders the tooltip below the tooltipped element and swaps to above if near the bottom of the viewport"above"- renders the tooltip above the tooltipped element and swaps to below if near the top of the viewport"left"- renders the tooltip to the left of the tooltipped element and swaps to the right if near the left edge of the viewport"right"- renders the tooltip to the right of the tooltipped element and swaps to the left if near the right edge of the viewport
"use client";
import { Button } from "@react-md/core/button/Button";
import { Tooltip } from "@react-md/core/tooltip/Tooltip";
import { useTooltip } from "@react-md/core/tooltip/useTooltip";
import { type ReactElement } from "react";
export default function TooltipPositioningExample(): ReactElement {
const { elementProps, tooltipProps } = useTooltip({
// this is the default
defaultPosition: "below",
// defaultPosition: "above",
// defaultPosition: "left",
// defaultPosition: "right",
});
return (
<>
<Button {...elementProps}>Button</Button>
<Tooltip {...tooltipProps}>Tooltip</Tooltip>
</>
);
}
Forced Tooltip Position
A specific position can be forced by setting the position option instead.
"use client";
import { Button } from "@react-md/core/button/Button";
import { Tooltip } from "@react-md/core/tooltip/Tooltip";
import { useTooltip } from "@react-md/core/tooltip/useTooltip";
import { type ReactElement } from "react";
export default function ForcedTooltipPositionExample(): ReactElement {
const { elementProps, tooltipProps } = useTooltip({
// this is the default
position: "below",
// position: "above",
// position: "left",
// position: "right",
});
return (
<>
<Button {...elementProps}>Button</Button>
<Tooltip {...tooltipProps}>Tooltip</Tooltip>
</>
);
}
Tooltipped Button
Since Tooltips are normally used with Buttons, a simple helper component is
available to automatically render a tooltip when a tooltip prop is provided. The
TooltippedButton also defaults the buttonType to "icon" instead of "text"
like normal buttons.
import { TooltippedButton } from "@react-md/core/button/TooltippedButton";
import CloseIcon from "@react-md/material-icons/CloseIcon";
import FavoriteIcon from "@react-md/material-icons/FavoriteIcon";
import { type ReactElement } from "react";
export default function TooltippedButtonExample(): ReactElement {
return (
<>
<TooltippedButton aria-label="No tooltip">
<CloseIcon />
</TooltippedButton>
<TooltippedButton
aria-label="Favorite"
tooltip="Tooltip"
themeType="outline"
>
<FavoriteIcon />
</TooltippedButton>
<TooltippedButton
aria-label="Favorite"
tooltip={
<span>
<strong>Strong</strong> tooltip
</span>
}
theme="success"
>
<FavoriteIcon />
</TooltippedButton>
</>
);
}
Enabling 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 can be enabled for
all tooltips in the application or just a small group of tooltips by wrapping
the components in the TooltipHoverModeProvider.
"use client";
import { TooltippedButton } from "@react-md/core/button/TooltippedButton";
import { TooltipHoverModeProvider } from "@react-md/core/tooltip/TooltipHoverModeProvider";
import { type ReactElement } from "react";
export default function EnablingHoverModeExample(): ReactElement {
return (
<TooltipHoverModeProvider>
{Array.from({ length: 5 }, (_, i) => (
<TooltippedButton
key={i}
tooltip={`Tooltip ${i + 1}`}
buttonType="text"
>
Button {i + 1}
</TooltippedButton>
))}
</TooltipHoverModeProvider>
);
}
Configuring Tooltip Timeouts
The timeouts for showing and hiding the tooltips can be configured globally
using the TooltipHoverModeProvider or a tooltip-by-tooltip basis with the
useTooltip hook which would override the TooltipHoverModeProvider value.
hoverTimeout- The amount of time to wait in milliseconds before showing the tooltip. Defaults to1000leaveTimeout- The amount of time to wait in milliseconds before hiding the tooltip. Defaults to0disableTimeout(TooltipHoverModeProvider) - The amount of time to wait in milliseconds before disabling the hover mode functionality. Defaults to1000
"use client";
import { TooltippedButton } from "@react-md/core/button/TooltippedButton";
import { TooltipHoverModeProvider } from "@react-md/core/tooltip/TooltipHoverModeProvider";
import { type ReactElement } from "react";
export default function ConfiguringTooltipTimeoutsExample(): ReactElement {
return (
<TooltipHoverModeProvider
hoverTimeout={500}
leaveTimeout={300}
disableTimeout={10000}
>
{Array.from({ length: 5 }, (_, i) => (
<TooltippedButton
key={i}
tooltip={`Tooltip ${i + 1}`}
buttonType="text"
>
{`Button ${i + 1}`}
</TooltippedButton>
))}
<TooltippedButton
tooltip="Another tooltip"
// these are pass-through to the `useTooltip` hook
// i.e.
// useTooltip({ ...tooltipOptions, disabled: !tooltip || tooltipOptions?.disabled })
tooltipOptions={{
leaveTimeout: 1000,
hoverTimeout: 1500,
}}
buttonType="text"
>
Custom Timeout
</TooltippedButton>
</TooltipHoverModeProvider>
);
}
Overflow Only Tooltip
The useTooltip hook also supports an overflowOnly option that will display
the tooltip only while there is overflown content for the tooltipped element.
"use client";
import { Box } from "@react-md/core/box/Box";
import { cssUtils } from "@react-md/core/cssUtils";
import { Tooltip } from "@react-md/core/tooltip/Tooltip";
import { useTooltip } from "@react-md/core/tooltip/useTooltip";
import { type CSSProperties, type ReactElement } from "react";
const style: CSSProperties = {
width: "8rem",
};
export default function OverflowOnlyTooltipExample(): ReactElement {
const { elementProps, tooltipProps } = useTooltip<HTMLDivElement>({
overflowOnly: true,
});
return (
<Box stacked>
<div
{...elementProps}
style={style}
className={cssUtils({ textOverflow: "ellipsis" })}
>
No Overflow.
</div>
<div
{...elementProps}
style={style}
className={cssUtils({ textOverflow: "ellipsis" })}
>
There will be overflow here.
</div>
<Tooltip {...tooltipProps}>Tooltip!</Tooltip>
</Box>
);
}
Custom Overflow Element
If the tooltipped element is a flex or grid container, a child element will most
likely need to be updated to add the overflow styles. This would cause the
tooltip to never appear since the tooltipped element is not considered overflown
even though the child is truncated. In this case, add the overflowRef to the
truncated element and the tooltip will correctly appear.
Try commenting out the
refor changing thewidthso there is no truncated text in this example and hover the button.
"use client";
import { Button } from "@react-md/core/button/Button";
import { cssUtils } from "@react-md/core/cssUtils";
import { Tooltip } from "@react-md/core/tooltip/Tooltip";
import { useTooltip } from "@react-md/core/tooltip/useTooltip";
import { type ReactElement } from "react";
export default function CustomOverflowElementExample(): ReactElement {
const { elementProps, tooltipProps, overflowRef } = useTooltip({
overflowOnly: true,
});
return (
<>
<Button {...elementProps} style={{ width: "2rem" }}>
<span
ref={overflowRef}
className={cssUtils({ textOverflow: "ellipsis" })}
>
Some long content
</span>
</Button>
<Tooltip {...tooltipProps}>Tooltip!</Tooltip>
</>
);
}
Custom Tooltip
A Tooltip can be rendered without the useTooltip hook but will require some
additional styling for the correct positioning to work.
- Enable the
disablePortalprop so it renders inline - Add styles for
position: absolutepositioning - Wrap in a container element with
position: relative - Optionally set the
textOverflowprop to"nowrap"so that the width is not restricted to the wrapper element's width
Progressbar Tooltip Example
This demo just showcases a possible use-case for the custom tooltip by rendering it with a progressbar to show the current progress.
Accessibility
Tooltips follow the tooltip pattern and the tooltip role.