React component wrapper for Tippy.js providing complete tooltip, popover, dropdown, and menu solution for the web
—
Singleton mode is a performance optimization technique that allows multiple tooltips to share a single instance, reducing memory usage and improving performance. This is particularly useful when you have many tooltips on a page that don't need to be shown simultaneously.
Creates a singleton configuration that can be shared across multiple Tippy components.
/**
* Hook for creating singleton tooltip configuration
* @param props - Optional singleton configuration
* @returns Tuple of [source, target] singleton objects
*/
function useSingleton(
props?: UseSingletonProps
): [SingletonObject, SingletonObject];
interface UseSingletonProps {
/** Disable singleton functionality */
disabled?: boolean;
/** Array of prop names that individual tooltips can override */
overrides?: Array<keyof Props>;
}
interface SingletonObject {
/** Internal singleton data */
data?: any;
/** Lifecycle hook function for singleton behavior */
hook(args: SingletonHookArgs): void;
}
interface SingletonHookArgs {
/** Tippy instance */
instance: Instance;
/** Tooltip content */
content: React.ReactNode;
/** Tippy props */
props: Props;
}Usage Examples:
import React from 'react';
import Tippy, { useSingleton } from '@tippyjs/react';
// Basic singleton usage
function BasicSingleton() {
const [source, target] = useSingleton();
return (
<>
{/* Source tooltip - the actual tooltip instance */}
<Tippy singleton={source} delay={500} />
{/* Target tooltips - these become "virtual" */}
<Tippy content="First tooltip" singleton={target}>
<button>Button 1</button>
</Tippy>
<Tippy content="Second tooltip" singleton={target}>
<button>Button 2</button>
</Tippy>
<Tippy content="Third tooltip" singleton={target}>
<button>Button 3</button>
</Tippy>
</>
);
}Configure singleton behavior with props and overrides.
interface UseSingletonProps {
/** Disable singleton functionality */
disabled?: boolean;
/** Props that individual tooltips can override */
overrides?: Array<keyof Props>;
}Usage Examples:
import React from 'react';
import Tippy, { useSingleton } from '@tippyjs/react';
// Singleton with configuration
function ConfiguredSingleton() {
const [source, target] = useSingleton({
disabled: false,
overrides: ['placement', 'theme'], // Allow individual tooltips to override these
});
return (
<>
<Tippy
singleton={source}
delay={300}
theme="dark"
placement="top"
/>
<Tippy content="Top tooltip" singleton={target}>
<button>Default (top, dark)</button>
</Tippy>
<Tippy
content="Bottom tooltip"
singleton={target}
placement="bottom" // Override allowed
>
<button>Bottom placement</button>
</Tippy>
<Tippy
content="Light tooltip"
singleton={target}
theme="light" // Override allowed
>
<button>Light theme</button>
</Tippy>
</>
);
}Use singleton mode with headless rendering for custom tooltip appearance.
// Headless singleton render function receives content as second parameter
interface HeadlessRenderFunction {
(
attrs: RenderAttrs,
content?: React.ReactNode,
instance?: Instance
): React.ReactNode;
}Usage Examples:
import React from 'react';
import Tippy, { useSingleton } from '@tippyjs/react/headless';
function HeadlessSingleton() {
const [source, target] = useSingleton();
return (
<>
<Tippy
singleton={source}
render={(attrs, content) => (
<div className="custom-tooltip" tabIndex={-1} {...attrs}>
{content}
</div>
)}
delay={500}
/>
<Tippy content="Hello" singleton={target}>
<button>Button 1</button>
</Tippy>
<Tippy content="World" singleton={target}>
<button>Button 2</button>
</Tippy>
</>
);
}Temporarily disable singleton behavior while keeping components mounted.
Usage Examples:
import React, { useState } from 'react';
import Tippy, { useSingleton } from '@tippyjs/react';
function DisableableSingleton() {
const [singletonDisabled, setSingletonDisabled] = useState(false);
const [source, target] = useSingleton({
disabled: singletonDisabled,
});
return (
<div>
<button onClick={() => setSingletonDisabled(!singletonDisabled)}>
{singletonDisabled ? 'Enable' : 'Disable'} Singleton
</button>
<Tippy singleton={source} delay={300} />
<Tippy content="Tooltip 1" singleton={target}>
<button>Button 1</button>
</Tippy>
<Tippy content="Tooltip 2" singleton={target}>
<button>Button 2</button>
</Tippy>
</div>
);
}Advanced singleton usage with dynamic content and state management.
Usage Examples:
import React, { useState } from 'react';
import Tippy, { useSingleton } from '@tippyjs/react';
interface User {
id: number;
name: string;
email: string;
role: string;
}
function UserList() {
const [source, target] = useSingleton({
overrides: ['content'], // Allow each tooltip to have different content
});
const users: User[] = [
{ id: 1, name: 'Alice', email: 'alice@example.com', role: 'Admin' },
{ id: 2, name: 'Bob', email: 'bob@example.com', role: 'User' },
{ id: 3, name: 'Charlie', email: 'charlie@example.com', role: 'Moderator' },
];
const renderUserTooltip = (user: User) => (
<div>
<strong>{user.name}</strong>
<br />
{user.email}
<br />
Role: {user.role}
</div>
);
return (
<>
<Tippy
singleton={source}
placement="top"
delay={[800, 200]}
interactive={true}
/>
<div className="user-list">
{users.map(user => (
<Tippy
key={user.id}
content={renderUserTooltip(user)}
singleton={target}
>
<div className="user-card">
{user.name}
</div>
</Tippy>
))}
</div>
</>
);
}Singleton mode provides several performance advantages:
overrides arraycontent prop on individual target tooltips is automatically included in overridesInstall with Tessl CLI
npx tessl i tessl/npm-tippyjs--react