0
# Singleton Tooltips
1
2
Singleton system for creating shared tooltips that can be displayed across multiple reference elements with smooth transitions and centralized management.
3
4
## Capabilities
5
6
### Create Singleton
7
8
Creates a single tooltip instance that can be shared across multiple reference elements, providing smooth transitions and consistent presentation.
9
10
```typescript { .api }
11
/**
12
* Creates a singleton tooltip that can be shared across multiple instances
13
* @param tippyInstances - Array of existing tippy instances to control
14
* @param optionalProps - Optional properties for the singleton
15
* @returns Enhanced singleton instance with additional methods
16
*/
17
function createSingleton<TProps = Props>(
18
tippyInstances: Instance[],
19
optionalProps?: Partial<CreateSingletonProps<TProps>>
20
): CreateSingletonInstance<CreateSingletonProps<TProps>>;
21
22
type CreateSingletonProps<TProps = Props> = TProps & {
23
/** Properties that can be overridden by individual instances */
24
overrides: Array<keyof TProps>;
25
};
26
27
interface CreateSingletonInstance<TProps = CreateSingletonProps> extends Instance<TProps> {
28
/** Update the controlled instances */
29
setInstances(instances: Instance[]): void;
30
/** Show tooltip for specific target */
31
show(target?: ReferenceElement | Instance | number): void;
32
/** Show tooltip for next instance in sequence */
33
showNext(): void;
34
/** Show tooltip for previous instance in sequence */
35
showPrevious(): void;
36
}
37
```
38
39
**Usage Examples:**
40
41
```typescript
42
import tippy, { createSingleton } from "tippy.js";
43
44
// Create individual instances (initially disabled)
45
const instances = [
46
tippy('#button1', { content: 'Button 1 content' }),
47
tippy('#button2', { content: 'Button 2 content' }),
48
tippy('#button3', { content: 'Button 3 content' })
49
];
50
51
// Create singleton to control them
52
const singleton = createSingleton(instances, {
53
delay: 500,
54
placement: 'top',
55
moveTransition: 'transform 0.2s ease-out',
56
overrides: ['content', 'placement'] // Allow individual overrides
57
});
58
59
// Singleton automatically shows appropriate content when hovering over any button
60
```
61
62
### Navigation Methods
63
64
Built-in navigation methods for programmatically controlling which tooltip is displayed.
65
66
```typescript { .api }
67
interface CreateSingletonInstance<TProps = CreateSingletonProps> {
68
/** Show tooltip for specific target by element, instance, or index */
69
show(target?: ReferenceElement | Instance | number): void;
70
/** Show tooltip for next instance in sequence */
71
showNext(): void;
72
/** Show tooltip for previous instance in sequence */
73
showPrevious(): void;
74
}
75
```
76
77
**Usage Examples:**
78
79
```typescript
80
import tippy, { createSingleton } from "tippy.js";
81
82
const instances = [
83
tippy('#step1', { content: 'Step 1: Introduction' }),
84
tippy('#step2', { content: 'Step 2: Configuration' }),
85
tippy('#step3', { content: 'Step 3: Completion' })
86
];
87
88
const singleton = createSingleton(instances, {
89
placement: 'bottom',
90
theme: 'tutorial'
91
});
92
93
// Programmatic navigation
94
function startTutorial() {
95
singleton.show(0); // Show first tooltip
96
}
97
98
function nextStep() {
99
singleton.showNext(); // Move to next tooltip
100
}
101
102
function previousStep() {
103
singleton.showPrevious(); // Move to previous tooltip
104
}
105
106
// Keyboard navigation
107
document.addEventListener('keydown', (e) => {
108
if (e.key === 'ArrowRight') nextStep();
109
if (e.key === 'ArrowLeft') previousStep();
110
if (e.key === 'Escape') singleton.hide();
111
});
112
```
113
114
### Instance Management
115
116
Dynamic management of controlled instances with the ability to add, remove, or replace instances.
117
118
```typescript { .api }
119
interface CreateSingletonInstance<TProps = CreateSingletonProps> {
120
/** Replace all controlled instances with new set */
121
setInstances(instances: Instance[]): void;
122
}
123
```
124
125
**Usage Examples:**
126
127
```typescript
128
import tippy, { createSingleton } from "tippy.js";
129
130
// Initial setup
131
let instances = [
132
tippy('#item1', { content: 'Item 1' }),
133
tippy('#item2', { content: 'Item 2' })
134
];
135
136
const singleton = createSingleton(instances);
137
138
// Add new instances dynamically
139
function addTooltipTarget(element, content) {
140
const newInstance = tippy(element, { content });
141
instances.push(newInstance);
142
singleton.setInstances(instances); // Update singleton
143
}
144
145
// Remove instances
146
function removeTooltipTarget(element) {
147
instances = instances.filter(instance => instance.reference !== element);
148
singleton.setInstances(instances); // Update singleton
149
}
150
151
// Replace all instances
152
function updateAllTargets(newElements) {
153
instances = newElements.map(el => tippy(el, {
154
content: el.getAttribute('data-tooltip')
155
}));
156
singleton.setInstances(instances);
157
}
158
```
159
160
### Property Overrides
161
162
Flexible override system allowing individual instances to customize specific properties while sharing common singleton behavior.
163
164
```typescript { .api }
165
type CreateSingletonProps<TProps = Props> = TProps & {
166
/** Array of property names that can be overridden by individual instances */
167
overrides: Array<keyof TProps>;
168
};
169
```
170
171
**Usage Examples:**
172
173
```typescript
174
import tippy, { createSingleton } from "tippy.js";
175
176
// Create instances with different placements and content
177
const instances = [
178
tippy('#top-button', {
179
content: 'Top button',
180
placement: 'bottom' // Will override singleton
181
}),
182
tippy('#side-button', {
183
content: 'Side button',
184
placement: 'left' // Will override singleton
185
}),
186
tippy('#main-button', {
187
content: 'Main button'
188
// Will use singleton placement
189
})
190
];
191
192
const singleton = createSingleton(instances, {
193
delay: 300,
194
duration: 200,
195
placement: 'top', // Default placement
196
theme: 'custom',
197
overrides: ['content', 'placement'], // Allow these to be overridden
198
// delay, duration, theme cannot be overridden
199
});
200
201
// Individual instances can override content and placement
202
// but share delay, duration, and theme from singleton
203
```
204
205
### Smooth Transitions
206
207
Built-in transition system for smooth movement between tooltip positions when switching targets.
208
209
```typescript { .api }
210
// Singleton props for transition control
211
interface CreateSingletonProps {
212
/** CSS transition for smooth movement between positions */
213
moveTransition: string;
214
}
215
```
216
217
**Usage Examples:**
218
219
```typescript
220
import tippy, { createSingleton } from "tippy.js";
221
222
const instances = [
223
tippy('.nav-item', { content: 'Navigation item' })
224
];
225
226
// Custom transition effects
227
const smoothSingleton = createSingleton(instances, {
228
moveTransition: 'transform 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
229
placement: 'bottom',
230
offset: [0, 8]
231
});
232
233
// Different transition for different contexts
234
const quickSingleton = createSingleton(instances, {
235
moveTransition: 'transform 0.1s ease-out', // Quick transitions
236
delay: 100
237
});
238
239
// No transition (instant movement)
240
const instantSingleton = createSingleton(instances, {
241
moveTransition: '', // Disable transitions
242
});
243
```
244
245
### Advanced Singleton Patterns
246
247
Complex singleton usage patterns for specialized use cases.
248
249
**Usage Examples:**
250
251
```typescript
252
import tippy, { createSingleton } from "tippy.js";
253
254
// Contextual help system
255
function createHelpSystem(containers) {
256
const allInstances = [];
257
258
containers.forEach(container => {
259
const helpElements = container.querySelectorAll('[data-help]');
260
const instances = Array.from(helpElements).map(el =>
261
tippy(el, {
262
content: el.dataset.help,
263
placement: el.dataset.placement || 'top'
264
})
265
);
266
allInstances.push(...instances);
267
});
268
269
return createSingleton(allInstances, {
270
theme: 'help-system',
271
delay: [600, 100],
272
moveTransition: 'transform 0.2s ease-out',
273
overrides: ['content', 'placement'],
274
interactive: true,
275
allowHTML: true
276
});
277
}
278
279
// Image gallery with captions
280
function createGalleryTooltips(gallery) {
281
const images = gallery.querySelectorAll('img[data-caption]');
282
const instances = Array.from(images).map(img =>
283
tippy(img, {
284
content: `
285
<div class="image-caption">
286
<h4>${img.alt}</h4>
287
<p>${img.dataset.caption}</p>
288
</div>
289
`,
290
allowHTML: true,
291
placement: 'bottom'
292
})
293
);
294
295
return createSingleton(instances, {
296
theme: 'gallery',
297
moveTransition: 'all 0.3s ease',
298
maxWidth: 300,
299
overrides: ['content']
300
});
301
}
302
303
// Keyboard-navigable tooltip tour
304
function createTooltipTour(steps) {
305
const instances = steps.map((step, index) =>
306
tippy(step.element, {
307
content: `
308
<div class="tour-step">
309
<div class="step-number">Step ${index + 1} of ${steps.length}</div>
310
<h3>${step.title}</h3>
311
<p>${step.description}</p>
312
</div>
313
`,
314
allowHTML: true,
315
placement: step.placement || 'top'
316
})
317
);
318
319
const tour = createSingleton(instances, {
320
theme: 'tour',
321
interactive: true,
322
hideOnClick: false,
323
trigger: 'manual',
324
overrides: ['content', 'placement']
325
});
326
327
// Add navigation controls
328
let currentStep = 0;
329
330
return {
331
start() {
332
currentStep = 0;
333
tour.show(0);
334
},
335
next() {
336
if (currentStep < instances.length - 1) {
337
currentStep++;
338
tour.show(currentStep);
339
}
340
},
341
previous() {
342
if (currentStep > 0) {
343
currentStep--;
344
tour.show(currentStep);
345
}
346
},
347
end() {
348
tour.hide();
349
}
350
};
351
}
352
```