Getting Started
Components
- Advanced Toast
- ArrowButton
- Arrows
- Avatar
- Backdrop
- Basic Toast
- Breadcrumb
- Button
- CardBackground
- Card
- Carousel
- ChatButton
- ChatInput
- ChatMessage
- ChatTypingIndicator
- ChatWindow
- CheckboxSelect
- Checkbox
- Checkboxes
- Chip
- ChoiceExpander
- Clickable
- Date Field
- Dropdown
- ElasticHeight
- ExpandableCard
- Filter
- Form Control
- Form Label
- Frame
- HamburgerIcon
- Heading
- Image
- Link
- Loader
- Number Field
- Pagination
- Password
- Phone Field
- Popin
- Portal
- Prose
- Radio Group
- Radio
- Range
- Scrollbar
- Select
- SidebarLayout
- SliderFrame
- Spinner
- Switch
- Tabs
- Tag
- TextField
- Tooltip
- ValidationMessage
DARK MODELIGHT MODEPOSITIONS
Click me
Click me
'use client';
import { useState } from 'react';
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from '@/ui/Tooltip';
import { Clickable } from '@/ui/Clickable';
export function TooltipDemo() {
const [clickTooltipOpen, setClickTooltipOpen] = useState(false);
return (
<div className="flex flex-col gap-24 h-300">
<TooltipProvider>
DARK MODE
<div className="flex gap-48 items-center">
<Tooltip>
<TooltipTrigger className="underline decoration-dashed cursor-help">
Hover me
</TooltipTrigger>
<TooltipContent>This is a helpful tooltip</TooltipContent>
</Tooltip>
<Tooltip open={clickTooltipOpen}>
<TooltipTrigger
render={
<Clickable
className="rounded-lg border-2 border-dashed border-gray-300 p-6 text-center hover:border-gray-400 hover:bg-gray-50"
onClick={() => setClickTooltipOpen(!clickTooltipOpen)}
>
Click me
</Clickable>
}
></TooltipTrigger>
<TooltipContent>This tooltip opens on click</TooltipContent>
</Tooltip>
{/* Always open */}
<Tooltip open>
<TooltipTrigger className="underline decoration-dashed cursor-help">
Always open
</TooltipTrigger>
<TooltipContent>This tooltip is always open</TooltipContent>
</Tooltip>
</div>
LIGHT MODE
<div className="flex gap-48 items-center">
<Tooltip>
<TooltipTrigger className="underline decoration-dashed cursor-help">
Hover me
</TooltipTrigger>
<TooltipContent theme="light">This is a helpful tooltip</TooltipContent>
</Tooltip>
<Tooltip open={clickTooltipOpen}>
<TooltipTrigger
render={
<Clickable
className="rounded-lg border-2 border-dashed border-gray-300 p-6 text-center hover:border-gray-400 hover:bg-gray-50"
onClick={() => setClickTooltipOpen(!clickTooltipOpen)}
>
Click me
</Clickable>
}
></TooltipTrigger>
<TooltipContent theme="light">This tooltip opens on click</TooltipContent>
</Tooltip>
{/* Always open */}
<Tooltip open>
<TooltipTrigger className="underline decoration-dashed cursor-help">
Always open
</TooltipTrigger>
<TooltipContent theme="light">This tooltip is always open</TooltipContent>
</Tooltip>
</div>
POSITIONS
<div className="flex gap-48 items-center">
<Tooltip>
<TooltipTrigger className="underline decoration-dashed cursor-help">
Hover me
</TooltipTrigger>
<TooltipContent side="top">This tooltip is on the top</TooltipContent>
<TooltipContent side="bottom">This tooltip is on the bottom</TooltipContent>
<TooltipContent side="right">This tooltip is on the right</TooltipContent>
<TooltipContent side="left">This tooltip is on the left</TooltipContent>
</Tooltip>
</div>
</TooltipProvider>
</div>
);
}
Usage
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from '@clubmed/trident-ui';
export function Component() {
return (
<TooltipProvider>
<Tooltip>
<TooltipTrigger className="underline decoration-dashed cursor-help">
Hover me
</TooltipTrigger>
<TooltipContent>This is a helpful tooltip</TooltipContent>
</Tooltip>
</TooltipProvider>
);
}With Button
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from '@clubmed/trident-ui';
import { Button } from '@clubmed/trident-ui';
export function Component() {
return (
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button variant="circle" icon="InfoCircle" size="small">
<span className="sr-only">More information</span>
</Button>
</TooltipTrigger>
<TooltipContent>Click for more details</TooltipContent>
</Tooltip>
</TooltipProvider>
);
}With Delay
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from '@clubmed/trident-ui';
export function Component() {
return (
<TooltipProvider delay={600}>
<Tooltip>
<TooltipTrigger>Hover me</TooltipTrigger>
<TooltipContent>Appears after 600ms</TooltipContent>
</Tooltip>
</TooltipProvider>
);
}Rich Content
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from '@clubmed/trident-ui';
export function Component() {
return (
<TooltipProvider>
<Tooltip>
<TooltipTrigger>Keyboard shortcut</TooltipTrigger>
<TooltipContent>
<div className="flex items-center gap-8">
<span>Save document</span>
<kbd
data-slot="kbd"
className="bg-background text-foreground px-6 py-2 rounded text-xs font-mono"
>
⌘S
</kbd>
</div>
</TooltipContent>
</Tooltip>
</TooltipProvider>
);
}In Forms
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from '@clubmed/trident-ui';
export function Component() {
return (
<TooltipProvider>
<form>
<div className="flex items-center gap-8">
<label htmlFor="username">Username</label>
<Tooltip>
<TooltipTrigger>ⓘ</TooltipTrigger>
<TooltipContent>Username must be 3-20 characters</TooltipContent>
</Tooltip>
</div>
<input id="username" type="text" />
</form>
</TooltipProvider>
);
}Light Theme
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from '@clubmed/trident-ui';
export function Component() {
return (
<TooltipProvider>
<Tooltip>
<TooltipTrigger className="underline decoration-dashed cursor-help">
Hover me
</TooltipTrigger>
<TooltipContent theme="light">Light themed tooltip</TooltipContent>
</Tooltip>
</TooltipProvider>
);
}API Reference
TooltipProvider
Wraps tooltip instances and provides shared configuration.
| Prop | Type | Default | Description |
|---|---|---|---|
delay | number | 0 | Delay in milliseconds before tooltip appears |
children | ReactNode | undefined | Tooltip components |
Tooltip
The root tooltip component that manages state.
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | undefined | Controlled open state |
defaultOpen | boolean | false | Initial open state |
onOpenChange | (open: boolean) => void | undefined | Callback when open state changes |
children | ReactNode | undefined | Trigger and content components |
TooltipTrigger
The element that triggers the tooltip display.
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | Merge props onto child instead of wrapping |
children | ReactNode | undefined | Trigger element |
...props | button props | - | Standard button attributes for the trigger |
TooltipContent
The popup content with positioning and styling.
| Prop | Type | Default | Description |
|---|---|---|---|
side | 'top' | 'right' | 'bottom' | 'left' | 'top' | Placement side relative to trigger |
sideOffset | number | 4 | Distance from trigger in pixels |
align | 'start' | 'center' | 'end' | 'center' | Alignment relative to trigger |
alignOffset | number | 0 | Offset along the alignment axis (px) |
theme | 'dark' | 'light' | 'dark' | Color theme (dark or light) |
className | string | undefined | Additional CSS classes |
children | ReactNode | undefined | Tooltip content |
Positioning
The tooltip can be positioned on any side of the trigger with various alignment options:
// Position on different sides
<TooltipContent side="top">Top</TooltipContent>
<TooltipContent side="right">Right</TooltipContent>
<TooltipContent side="bottom">Bottom</TooltipContent>
<TooltipContent side="left">Left</TooltipContent>
// Align relative to trigger
<TooltipContent align="start">Start aligned</TooltipContent>
<TooltipContent align="center">Center aligned</TooltipContent>
<TooltipContent align="end">End aligned</TooltipContent>
// Custom offsets
<TooltipContent sideOffset={20} alignOffset={10}>
Custom offset
</TooltipContent>Styling
The tooltip comes with default styling using Tailwind classes. Customize by adding your own classes:
<TooltipContent className="bg-turquoise text-white">
Custom colored tooltip
</TooltipContent>Default Styles
Dark theme (default):
- Background:
bg-black - Text:
text-white
Light theme:
- Background:
bg-lightGrey - Text:
text-black
Shared styles:
- Border radius:
rounded-8 - Padding:
p-8 - Max width:
max-w-xs - Font size:
text-xs - Z-index:
z-50 - Includes animated arrow pointer that matches the theme
Accessibility
The Tooltip component follows WAI-ARIA guidelines:
- ✅ Keyboard navigation support (focus/blur triggers)
- ✅ Screen reader support
- ✅ Proper ARIA attributes
- ✅ Automatic ID management
Keyboard Interactions
- Tab - Focus trigger element, showing tooltip
- Shift+Tab - Move focus away, hiding tooltip
Best Practices
- Keep content concise - Tooltips should be brief (under 50 characters when possible)
- Don't hide critical information - Tooltips are supplementary; critical info should be visible
- Make triggers keyboard accessible - Use focusable elements (buttons, links, etc.)
- Avoid interactive content - Don't put buttons or links in tooltips (use Popover instead)
- Provide appropriate delays - 200-600ms is recommended for better UX
// Good: Accessible trigger
<TooltipTrigger asChild>
<button aria-label="More information">
<Icon name="InfoCircle" />
</button>
</TooltipTrigger>
// Bad: Non-focusable trigger
<TooltipTrigger>
<div>Hover me</div>
</TooltipTrigger>Notes
- The tooltip uses Base UI's
@base-ui/react/tooltipprimitives for reliable positioning and accessibility - Tooltips are rendered in a portal to prevent stacking context issues
- Animations are CSS-based for optimal performance
- Multiple tooltips can share the same
TooltipProviderfor consistent delay settings - The arrow automatically adjusts position based on the tooltip's placement