# rc-component/tooltip: a positioned React tooltip with one trigger layer

> @rc-component/tooltip is a small TypeScript React component that shows positioned popups on hover, focus, click or controlled visibility, with placements, delays, arrows, motion and semantic class and style slots. It fits teams building their own design system on React and willing to own the styling.

**react-component/tooltip** — 💡 Positioned React tooltip for hover, focus, click, and controlled popup flows.

- Repository: https://github.com/react-component/tooltip
- Website: https://react-component.github.io/tooltip
- Stars: 943 · Forks: 199
- Language: TypeScript
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/react-component-tooltip

## Hover, focus, click and controlled visibility share one trigger layer

The headline claim of this component is that hover, focus, click and controlled visibility are all handled through one trigger layer, and that is the design decision worth understanding before you adopt it.

A tooltip that only works on hover fails a whole category of interaction. Keyboard users reach a control by focusing it, touch users tap it, and an application that owns the state, say a popover that must open when a server response arrives, needs the visible prop to drive it. The README lists all four of these as supported triggers, and the trigger prop accepts either a single action or an array of them, defaulting to ['hover'].

That default is the first thing to look at when you install it. A tooltip that appears on hover only is a tooltip that never appears for a keyboard user, and the component does give you the means to fix that by adding focus to the trigger list, but the default does not do it for you.

The audience is React developers assembling a component library rather than a consumer picking a themed widget. The package name and the Ant Design ecosystem badge in the README say as much: this is infrastructure, and it is meant to be styled by whoever depends on it. The published description is plain: a tooltip UI component for React.

The consequence is that the component gives you geometry, timing, motion and accessibility wiring, and leaves every visible decision to you.

## Positioning is delegated to @rc-component/trigger

The package does not implement its own overlay engine. Looking at the dependency list, the tooltip builds on @rc-component/trigger at version 3.10.0 or later, alongside @rc-component/util and clsx. The trigger package is the positioning layer, and the API reflects that separation.

Several props are typed against trigger types rather than as plain values. builtinPlacements is described as the placement map passed to trigger, align is extra popup alignment config, motion is the trigger popup motion config, and onPopupAlign is called after popup alignment. The README also exposes unique as an experimental unique container reuse config, and popup motion and z-index for stacking.

For a basic case, none of that is needed. The default placement is 'right', and the prop is a plain string, so the common case is a single keyword. The default prefixCls is 'rc-tooltip', which is the class name prefix you override if you need your own namespace in a shared stylesheet.

Two container props matter for layout. getTooltipContainer takes a node and resolves the container the popup is rendered into, and destroyOnHidden destroys the popup DOM when hidden, which matters if you are animating many tooltips in a long list and do not want detached nodes accumulating. The fresh prop, by contrast, keeps popup content fresh when closed, which is the opposite choice, and the two together tell you the component is aware that mount cost and content freshness are different problems.

The arrow is configurable too. showArrow accepts a boolean or an arrow config, defaulting to true, and arrowContent takes custom arrow content, so a design system can replace the shape without reimplementing the placement.

## Delays are in seconds and the leave delay is the default you notice

Two props govern the timing of the hover interaction: mouseEnterDelay, a delay in seconds before showing on mouse enter, defaulting to 0, and mouseLeaveDelay, a delay in seconds before hiding on mouse leave, defaulting to 0.1.

The asymmetry is the point. Showing instantly is usually right, because a tooltip that lags on arrival feels broken. Hiding needs a moment of grace, because moving the pointer onto the tooltip itself, or across a gap between two elements, would otherwise make it vanish. A tenth of a second is short enough to feel immediate and long enough to survive a stray mouse movement.

The units are worth internalising. These are seconds, not milliseconds, which is a common source of confusion when copying a value from a design specification, and it means a hover delay of 0.2 is two hundred milliseconds. Both props are typed as plain numbers, so nothing in the type system will catch a value that is off by a factor of a thousand.

The same timing problem applies to focus, and the README does not document a separate focus delay, so a focused control shows and hides on the same schedule as a hovered one. If your tooltip contains interactive content and you want it to stay open while the pointer is inside it, that behaviour has to come from the trigger configuration rather than from the delay props, and the component does not offer a built-in hoverable option for it.

## classNames and styles are semantic slots, not a single className prop

The API exposes semantic classNames and styles slots for the root, the arrow and the container nodes, and the types are Partial records keyed by a SemanticName union.

That is a small design choice with real consequences. The older pattern of a single className prop that the component concatenates onto one wrapper forces consumers to either accept the generated markup or fight it with specificity. Slots mean a design system can target the arrow separately from the root, restyle the container without touching the tooltip, and write selectors that survive internal markup changes as long as the slot names hold.

The prefixCls default of 'rc-tooltip' sits alongside this. A component that renders semantic slots and a class prefix is designed to be themed from outside, which fits its role in a component ecosystem.

The styles prop takes the same shape, Partial records of SemanticName to React.CSSProperties, so inline style objects can be applied per slot when a design system prefers that over stylesheets. The package also publishes a bootstrap_white.css in its assets folder, and the usage example imports it directly, which tells you the styling story is bring-your-own with a reference sheet, not a themed component.

The example in the README is worth reading in full, because it is the entire quick start:

## The minimal usage is one import, one stylesheet and one child element

The usage block from the README, trimmed to the parts that matter, is the whole integration:

```ts
import Tooltip from '@rc-component/tooltip';
import '@rc-component/tooltip/assets/bootstrap_white.css';

export default () => (
  <Tooltip placement="top" overlay={<span>Tooltip content</span>}>
    <button type="button">Hover me</button>
  </Tooltip>
);
```

The API is small in practice. The overlay prop is the content, accepting a React node or a function returning one, so the content can be resolved lazily at open time. The children prop is a required trigger element, and the README documents it as a React.ReactElement, which means a single element rather than a string.

The child is what gets the hover, and that has a consequence for styling: the tooltip wraps the trigger rather than replacing it, so a button that needs the hover state has to be the child. The README's own example uses a plain button with a type attribute, which is the minimum you need for a real control.

To install the package:

```bash
npm install @rc-component/tooltip
```

For the interactive examples, the README documents a local dumi site:

```bash
npm install
npm start
```

and then to open http://localhost:8000 in the browser. The repository root has a .dumirc.ts and a .dumi/ directory for the site config, and the online preview of the same examples is published as well.

## Accessibility comes from generated ids and aria-describedby

The README states that accessibility wiring is kept through generated tooltip ids and aria-describedby, and the API supports it with an id prop whose default is a generated id, described as the tooltip id used for accessibility.

The mechanism is standard for a tooltip that describes an existing control. The trigger element receives an aria-describedby pointing at the tooltip element, and the tooltip element carries the matching id. Because the id is generated when you do not supply one, the wiring works without the consumer managing ids, and because you can supply one, you can control it when a test or a design system needs determinism.

The content prop that makes this work is the overlay, and the trap is that the described text has to be there at the time the attribute is read. The fresh prop, which keeps popup content fresh when closed, is the option that addresses content that changes over time, and destroyOnHidden, which removes the popup DOM when hidden, works against that by taking the node out of the document entirely.

The disabled prop is described as temporarily hiding the tooltip while preserving visible state, which is a slightly unusual contract worth noticing: disabling does not reset a controlled visible value, it just stops the tooltip from being shown. For an application that turns tooltips off globally, such as a kiosk mode, that difference matters.

Visibility control comes in three forms. visible is the controlled state, defaultVisible is the initial uncontrolled state, and onVisibleChange and afterVisibleChange report changes, the first when the change happens and the second after the popup has finished moving. Having both is what lets a consumer coordinate with animation.

## MIT licensed, moving versions, and an ecosystem dependency chain

The licence is MIT, recorded in package.json and in the LICENSE file at the repository root, and the published files array includes lib, es, and the assets stylesheets in css and less form. That is a permissive licence with no obligation on how you use the component, though as always you should read the file yourself before shipping.

The release cadence is quick. Version 1.5.0 was published on 2026-07-10, 1.5.1 on 2026-08-27 in the early hours, and 1.5.2 the same day later. The repository is not archived and the last push was on 2026-09-07, so the work is current, and CHANGELOG.md at the root is the place to read what changed between those patch versions.

The operational cost sits in the dependencies rather than in the code. The tooltip depends on @rc-component/trigger, and the trigger package is where the positioning, the container handling and the popup motion actually live, so an upgrade of the tooltip can pull a new trigger along with it. The repository also depends on a broader toolchain for its own development: father for the build, dumi for the documentation site, lessc to compile the Less stylesheets, rc-test for the test suite, husky for the git hooks, and ESLint and Prettier for linting and formatting. The npm scripts show the whole pipeline, from compile through docs:build to the gh-pages deployment.

The alternative to this component, and it is a serious one, is the native title attribute on an element. It costs nothing, it needs no dependency, and it is announced by assistive technology, but it cannot be positioned, styled, given a delay, opened on focus or click, or kept on screen while the pointer rests on it. The difference in approach is exactly the boundary of what this package adds: a native tooltip is a text hint with no behaviour, while this is a controlled, animated, accessible overlay that you are expected to style.

## Conclusion

Adopt @rc-component/tooltip if you are building a React design system and want full control over placement, delays, motion and class names, and if you are comfortable wiring your own CSS, since the package ships an assets folder of styles and a bootstrap_white.css example rather than a themed design. Do not adopt it if the native title attribute is good enough, if you want a drop-in themed tooltip, or if a moving dependency chain is a problem, because the tooltip builds on @rc-component/trigger and @rc-component/util and those versions move. Before upgrading, read CHANGELOG.md and note that the last push was on 2026-09-07 with version 1.5.2 published on 2026-08-27.

## FAQ

### How do I install and use @rc-component/tooltip?

Install it with npm install @rc-component/tooltip, then render it with an overlay prop for the content and a single child element as the trigger, for example a Tooltip with placement="top" wrapping a button. The package also publishes a bootstrap_white.css in its assets folder that the usage example imports.

### How do I make the tooltip appear on keyboard focus as well as hover?

The trigger prop accepts a single action or an array of actions and defaults to ['hover']. The README lists focus and click among the supported actions, and states that hover, focus, click and controlled visibility are all handled through one trigger layer.

### What are the default delays for showing and hiding the tooltip?

mouseEnterDelay defaults to 0 and mouseLeaveDelay defaults to 0.1. Both are delays in seconds before showing on mouse enter and before hiding on mouse leave, so the leave delay is a tenth of a second.

### How does the tooltip handle accessibility?

The README states that accessibility wiring is kept through generated tooltip ids and aria-describedby, and the id prop defaults to a generated id used for accessibility. The overlay prop carries the description and the trigger element is what the tooltip describes.

### What licence is @rc-component/tooltip published under?

MIT, recorded in the package metadata and in the LICENSE file at the repository root. The published files array includes lib, es, and the assets stylesheets in css and less form.

## Sources

- [License: MIT](https://github.com/react-component/tooltip/blob/master/LICENSE)
- [Project website](https://react-component.github.io/tooltip)
- [react-component/tooltip on GitHub](https://github.com/react-component/tooltip)
- [README](https://github.com/react-component/tooltip/blob/master/README.md)
- [Releases](https://github.com/react-component/tooltip/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/react-component-tooltip
