npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@rentnerkev/tooltips

v2.0.1

Published

A lightweight, customizable React tooltip component powered by Radix UI.

Readme

@rentnerkev/tooltips

A lightweight, customizable React tooltip component built on Radix UI. The package provides a shared provider, trigger, portal, collision handling, and the accessible tooltip relationship. Standalone tooltips remain supported.

Installation

npm install @rentnerkev/tooltips

Or with Bun:

bun add @rentnerkev/tooltips

Quick start

import { CustomTooltip, TooltipProvider } from '@rentnerkev/tooltips'

export function Example() {
    return (
        <TooltipProvider delayDuration={200}>
            <CustomTooltip content="Helpful information" side="top">
                <button type="button">Hover me</button>
            </CustomTooltip>
        </TooltipProvider>
    )
}

Use one TooltipProvider around a section that contains multiple tooltips. A CustomTooltip inside that provider reuses it instead of creating another Radix provider. Standalone CustomTooltip usage creates a fallback provider with the default 200 ms delay.

The trigger must be a single React element. For keyboard support, it should be focusable, such as a button or link. Custom trigger components must forward the props and ref provided by Radix. Radix handles hover, focus, touch, and ARIA behavior.

API

CustomTooltip

| Prop | Type | Default | Description | | -------------------------- | ------------------------------------------- | --------------- | ------------------------------------------------------------------- | | children | ReactElement | – | A single element that triggers the tooltip. | | content | ReactNode | – | The accessible content of the tooltip. | | disabled | boolean | false | Returns the trigger without any tooltip behavior. | | disabledTrigger | boolean | false | Wraps a disabled control in a hoverable, focusable trigger. | | disabledTriggerClassName | string | undefined | Adds classes to the disabled-trigger wrapper. | | delayDuration | number | Provider value | Overrides the provider delay for this tooltip. | | disableHoverableContent | boolean | Provider value | Closes the tooltip when the pointer leaves the trigger. | | open | boolean | undefined | Controls the open state. | | defaultOpen | boolean | undefined | Sets the uncontrolled initial open state. | | onOpenChange | (open: boolean) => void | undefined | Receives open-state changes. | | side | 'top' \| 'right' \| 'bottom' \| 'left' | 'top' | The preferred position. | | sideOffset | number | 8 | Distance from the trigger in pixels. | | align | 'start' \| 'center' \| 'end' | 'center' | Alignment along the selected side. | | alignOffset | number | 0 | Offset from the selected alignment. | | avoidCollisions | boolean | true | Allows Radix to move content away from boundaries. | | collisionBoundary | Element \| null \| Array<Element \| null> | [] | Custom collision boundary or boundaries. | | collisionPadding | number \| SidePadding | 0 | Space kept between content and collision boundaries. | | arrowPadding | number | 0 | Space kept between the arrow and content edges. | | sticky | 'partial' \| 'always' | 'partial' | Controls how content behaves at a boundary. | | hideWhenDetached | boolean | false | Hides content when its trigger is detached. | | portalContainer | Element \| DocumentFragment \| null | document.body | Custom portal destination. | | customDesign | TooltipCustomDesign | Default design | Overrides individual classes for the content, animation, and arrow. |

disabledTrigger is intended for native disabled controls, which cannot receive pointer or keyboard events themselves. It keeps the original control disabled, applies pointer-events: none to it, and makes an outer span focusable so the explanatory tooltip remains available:

<CustomTooltip
    content="Only administrators can delete this entry."
    disabledTrigger
>
    <button type="button" disabled>
        Delete
    </button>
</CustomTooltip>

Use disabled instead when the tooltip itself should not be active.

TooltipProvider

| Prop | Type | Default | Description | | ------------------------- | ----------- | ------- | -------------------------------------------------------------- | | children | ReactNode | – | The subtree that shares provider settings. | | delayDuration | number | 200 | Delay before a tooltip opens. | | skipDelayDuration | number | 300 | Time window for moving between tooltips without another delay. | | disableHoverableContent | boolean | false | Closes content when the pointer leaves its trigger. |

Nested package providers reuse the nearest outer provider, so they do not create additional Radix provider instances. Use CustomTooltip.delayDuration when one tooltip needs a local delay override.

Collision and portal configuration

<CustomTooltip
    content="Kept inside the panel"
    side="right"
    collisionBoundary={panelElement}
    collisionPadding={{ top: 8, right: 12, bottom: 8, left: 12 }}
    portalContainer={overlayElement}
>
    <button type="button">Details</button>
</CustomTooltip>

The collision and portal types are derived from the installed Radix Tooltip version, so all accepted boundary and padding shapes stay type-safe.

TooltipProps, TooltipProviderProps, and TooltipCustomDesign are exported TypeScript types. defaultTooltipDesign is also exported for extending the default design.

import { CustomTooltip, defaultTooltipDesign } from '@rentnerkev/tooltips'

const design = {
    ...defaultTooltipDesign,
    contentClasses: 'max-w-xs text-center',
}

export function StyledExample() {
    return (
        <CustomTooltip content="Custom styling" customDesign={design}>
            <button type="button">Learn more</button>
        </CustomTooltip>
    )
}

Styling

The package ships an opt-in Tailwind entry. Import it after Tailwind CSS in your main stylesheet:

@import 'tailwindcss';
@import '@rentnerkev/tooltips/tailwind.css';

The entry scans only the published JavaScript files under dist. It provides the shared primary, primary-hover, background-dark, surface-dark, input-dark, border-dark, secondary-text, and muted-foreground theme tokens plus the package's transform/opacity enter animation. The animation uses motion-safe: and is disabled automatically for reduced-motion users. Override the tokens with a later @theme block when needed.

If you do not use Tailwind, override the design classes through customDesign with classes from your own stylesheet.

Public exports

  • CustomTooltip
  • TooltipProvider
  • defaultTooltipDesign
  • TooltipProps
  • TooltipProviderProps
  • TooltipCustomDesign

Development

bun install --frozen-lockfile
bun run verify

bun run verify checks types, Oxlint, Oxfmt, unit tests, browser tests, the build, and the published package contents with bun pm pack --dry-run. Install the Playwright browser once with bunx playwright install chromium.

Playground

The interactive positioning bench demonstrates provider reuse, opening delay, collision boundaries, a custom portal container, disabled tooltips, and disabled native controls. Its built-in theme switch validates the Tailwind-first design in both light and dark modes.

bun run playground:install
bun run playground:dev

License

MIT