@mshafiqyajid/react-tooltip
Headless tooltip hook and styled component for React. Accessible, keyboard-friendly, smart flip positioning when near viewport edges, animated, SSR-safe, fully typed.
Playground #
Props
TSX
import { TooltipStyled } from "@mshafiqyajid/react-tooltip/styled";
import "@mshafiqyajid/react-tooltip/styles.css";
<TooltipStyled
content="Copy to clipboard"
/>Install #
npm install @mshafiqyajid/react-tooltip Quick start #
import { TooltipStyled } from "@mshafiqyajid/react-tooltip/styled";
import "@mshafiqyajid/react-tooltip/styles.css";
export function App() {
return (
<TooltipStyled content="Copy to clipboard" placement="top">
<button>Copy</button>
</TooltipStyled>
);
} Placements #
The tooltip defaults to top but automatically flips to the opposite side if it would overflow the viewport.
<TooltipStyled content="Top" placement="top">...</TooltipStyled>
<TooltipStyled content="Bottom" placement="bottom">...</TooltipStyled>
<TooltipStyled content="Left" placement="left">...</TooltipStyled>
<TooltipStyled content="Right" placement="right">...</TooltipStyled> Tones #
<TooltipStyled content="Neutral" tone="neutral">...</TooltipStyled>
<TooltipStyled content="Primary" tone="primary">...</TooltipStyled>
<TooltipStyled content="Success" tone="success">...</TooltipStyled>
<TooltipStyled content="Danger" tone="danger">...</TooltipStyled> Rich content #
Pass any JSX to content. Use multiline to allow text to wrap.
<TooltipStyled
multiline
content={
<span>
<strong>⌘ + C</strong> to copy
</span>
}
>
<button>Copy</button>
</TooltipStyled> Delay #
Show delay defaults to 0 (instant). Increase for less sensitive triggers.
<TooltipStyled content="Appears after 500ms" delay={500}>...</TooltipStyled> Headless #
Use useTooltip to build a fully custom tooltip with your own markup and styles.
import { useTooltip } from "@mshafiqyajid/react-tooltip";
function MyTooltip({ content, children }) {
const { triggerProps, tooltipProps, placement, isVisible } = useTooltip({
placement: "top",
delay: 300,
});
return (
<div style={{ position: "relative", display: "inline-flex" }}>
<div {...triggerProps}>{children}</div>
<div
{...tooltipProps}
data-placement={placement}
style={{
position: "absolute",
bottom: "calc(100% + 8px)",
left: "50%",
translate: "-50% 0",
opacity: isVisible ? 1 : 0,
transition: "opacity 140ms ease",
background: "#18181b",
color: "#fff",
padding: "4px 10px",
borderRadius: "6px",
fontSize: "0.78rem",
whiteSpace: "nowrap",
pointerEvents: "none",
}}
>
{content}
</div>
</div>
);
} API #
| Prop | Type | Default | Description |
|---|---|---|---|
| content | ReactNode | — | Tooltip text or JSX content |
| placement | "top" | "bottom" | "left" | "right" | "top" | Preferred placement (auto-flips near viewport edges) |
| size | "sm" | "md" | "lg" | "md" | Size of the tooltip bubble |
| tone | "neutral" | "primary" | "success" | "danger" | "neutral" | Color tone |
| delay | number | 0 | Show delay in ms |
| multiline | boolean | false | Allow content to wrap (useful for rich HTML content) |
| disabled | boolean | false | Disable the tooltip entirely |