Skip to content
Esc
navigateopen⌘Jpreview
On this page

Tooltip

A popup that displays information related to an element on hover or focus.

import { Button } from '@/components/ui/button';
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from '@/components/ui/tooltip';

export default function TooltipDemo() {
  return (
    <TooltipProvider>
      <Tooltip>
        <TooltipTrigger render={<Button variant="outline" />}>
          Hover me
        </TooltipTrigger>
        <TooltipContent>Add to library</TooltipContent>
      </Tooltip>
    </TooltipProvider>
  );
}

Install

npx shadcn@latest add @madeui/tooltip

Usage

import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from '@/components/ui/tooltip';

// Wrap your app (or a subtree) in <TooltipProvider> once.

Composition

<TooltipProvider>
  <Tooltip>
    <TooltipTrigger />
    <TooltipContent />
  </Tooltip>
</TooltipProvider>

Sides

import * as stylex from '@stylexjs/stylex';

import { space } from '@/lib/constants.stylex';

import { Button } from '@/components/ui/button';
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from '@/components/ui/tooltip';

const sides = ['top', 'right', 'bottom', 'left'] as const;

export default function TooltipSides() {
  return (
    <TooltipProvider>
      <div {...stylex.props(styles.row)}>
        {sides.map((side) => (
          <Tooltip key={side}>
            <TooltipTrigger render={<Button variant="outline" />}>
              {side}
            </TooltipTrigger>
            <TooltipContent side={side}>Tooltip on {side}</TooltipContent>
          </Tooltip>
        ))}
      </div>
    </TooltipProvider>
  );
}

const styles = stylex.create({
  row: {
    alignItems: 'center',
    display: 'flex',
    flexWrap: 'wrap',
    gap: space.s2,
  },
});

Disabled button

Native disabled buttons don’t fire pointer events, so the tooltip trigger has to be a wrapping element instead of the button itself.

import * as stylex from '@stylexjs/stylex';

import { Button } from '@/components/ui/button';
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from '@/components/ui/tooltip';

export default function TooltipDisabledButton() {
  return (
    <TooltipProvider>
      <Tooltip>
        <TooltipTrigger render={<span {...stylex.props(styles.trigger)} />}>
          <Button variant="outline" disabled>
            Submit
          </Button>
        </TooltipTrigger>
        <TooltipContent>Complete the form to submit</TooltipContent>
      </Tooltip>
    </TooltipProvider>
  );
}

const styles = stylex.create({
  // Disabled native buttons don't fire pointer events, so the tooltip
  // trigger has to be the wrapping span instead of the button itself.
  trigger: {
    display: 'inline-block',
  },
});

API reference

Built on Base UI Tooltip. The tables below cover the props this library adds or changes — every other prop is forwarded to the underlying Base UI part; see the Base UI Tooltip API reference for the full list.

TooltipContent

Prop Type Default Description
side 'top' | 'right' | 'bottom' | 'left' 'top'
sideOffset number 4 Distance from the trigger, in px.
align 'start' | 'center' | 'end' 'center'
alignOffset number 0
style StyleXStyles StyleX styles merged last — always win over the component’s own styles.

TooltipProvider

Prop Type Default Description
delay number 0 Hover delay before opening, in ms. Instant by default.

Tooltip (Root) and TooltipTrigger are Base UI parts re-exported unstyled; TooltipTrigger accepts render.

Was this page helpful?