@telegraph/tooltip 0.0.53 → 0.0.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/README.md +710 -7
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.mjs +1595 -1583
- package/dist/esm/index.mjs.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,17 +1,720 @@
|
|
|
1
|
-
|
|
1
|
+
# 💬 Tooltip
|
|
2
|
+
|
|
3
|
+
> Contextual information overlay component with smart positioning, customizable content, and comprehensive accessibility support.
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+

|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
[](https://www.npmjs.com/package/@telegraph/tooltip)
|
|
8
|
+
[](https://bundlephobia.com/result?p=@telegraph/tooltip)
|
|
9
|
+
[](https://github.com/knocklabs/telegraph/blob/main/LICENSE)
|
|
7
10
|
|
|
8
|
-
## Installation
|
|
11
|
+
## Installation
|
|
9
12
|
|
|
10
|
-
```
|
|
13
|
+
```bash
|
|
11
14
|
npm install @telegraph/tooltip
|
|
12
15
|
```
|
|
13
16
|
|
|
14
17
|
### Add stylesheet
|
|
18
|
+
|
|
19
|
+
Pick one:
|
|
20
|
+
|
|
21
|
+
Via CSS (preferred):
|
|
22
|
+
|
|
23
|
+
```css
|
|
24
|
+
@import "@telegraph/tooltip";
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Via Javascript:
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
import "@telegraph/tooltip/default.css";
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
> Then, include `className="tgph"` on the farthest parent element wrapping the telegraph components
|
|
34
|
+
|
|
35
|
+
## Quick Start
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
import { Button } from "@telegraph/button";
|
|
39
|
+
import { Tooltip } from "@telegraph/tooltip";
|
|
40
|
+
import { Info } from "lucide-react";
|
|
41
|
+
|
|
42
|
+
export const TooltipExample = () => (
|
|
43
|
+
<div>
|
|
44
|
+
{/* Basic tooltip */}
|
|
45
|
+
<Tooltip content="This button saves your changes">
|
|
46
|
+
<Button>Save</Button>
|
|
47
|
+
</Tooltip>
|
|
48
|
+
|
|
49
|
+
{/* Rich content tooltip */}
|
|
50
|
+
<Tooltip
|
|
51
|
+
content={
|
|
52
|
+
<div>
|
|
53
|
+
<strong>Pro Tip:</strong>
|
|
54
|
+
<br />
|
|
55
|
+
Use Ctrl+S to save quickly
|
|
56
|
+
</div>
|
|
57
|
+
}
|
|
58
|
+
>
|
|
59
|
+
<Button icon={{ icon: Info, alt: "Info" }}>Help</Button>
|
|
60
|
+
</Tooltip>
|
|
61
|
+
</div>
|
|
62
|
+
);
|
|
15
63
|
```
|
|
16
|
-
|
|
64
|
+
|
|
65
|
+
## API Reference
|
|
66
|
+
|
|
67
|
+
### `<Tooltip>`
|
|
68
|
+
|
|
69
|
+
The main tooltip component that wraps content and provides contextual information on hover or focus.
|
|
70
|
+
|
|
71
|
+
| Prop | Type | Default | Description |
|
|
72
|
+
| ------------------------- | ---------------------------------------- | ----------- | ------------------------------------------------------------ |
|
|
73
|
+
| `content` | `ReactNode` | - | **Required.** Content to display in the tooltip |
|
|
74
|
+
| `side` | `"top" \| "right" \| "bottom" \| "left"` | `"top"` | Preferred placement side |
|
|
75
|
+
| `align` | `"start" \| "center" \| "end"` | `"center"` | Alignment relative to the trigger |
|
|
76
|
+
| `sideOffset` | `number` | `4` | Distance from the trigger element |
|
|
77
|
+
| `alignOffset` | `number` | `0` | Offset along the alignment axis |
|
|
78
|
+
| `delayDuration` | `number` | `700` | Delay before showing tooltip (ms) |
|
|
79
|
+
| `skipDelayDuration` | `number` | `300` | Skip delay if another tooltip was recently shown |
|
|
80
|
+
| `disableHoverableContent` | `boolean` | `false` | Prevent tooltip from staying open when hovering over content |
|
|
81
|
+
| `avoidCollisions` | `boolean` | `true` | Automatically flip tooltip to avoid viewport edges |
|
|
82
|
+
| `sticky` | `"partial" \| "always"` | `"partial"` | How tooltip follows the cursor |
|
|
83
|
+
| `hideWhenDetached` | `boolean` | `false` | Hide tooltip when trigger is not visible |
|
|
84
|
+
|
|
85
|
+
## Usage Patterns
|
|
86
|
+
|
|
87
|
+
### Basic Tooltip
|
|
88
|
+
|
|
89
|
+
```tsx
|
|
90
|
+
import { Button } from "@telegraph/button";
|
|
91
|
+
import { Tooltip } from "@telegraph/tooltip";
|
|
92
|
+
|
|
93
|
+
export const BasicTooltip = () => (
|
|
94
|
+
<Tooltip content="Click to save your work">
|
|
95
|
+
<Button>Save</Button>
|
|
96
|
+
</Tooltip>
|
|
97
|
+
);
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Different Positions
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
import { Button } from "@telegraph/button";
|
|
104
|
+
import { Tooltip } from "@telegraph/tooltip";
|
|
105
|
+
|
|
106
|
+
export const PositionedTooltips = () => (
|
|
107
|
+
<div>
|
|
108
|
+
<Tooltip content="Tooltip on top" side="top">
|
|
109
|
+
<Button>Top</Button>
|
|
110
|
+
</Tooltip>
|
|
111
|
+
|
|
112
|
+
<Tooltip content="Tooltip on right" side="right">
|
|
113
|
+
<Button>Right</Button>
|
|
114
|
+
</Tooltip>
|
|
115
|
+
|
|
116
|
+
<Tooltip content="Tooltip on bottom" side="bottom">
|
|
117
|
+
<Button>Bottom</Button>
|
|
118
|
+
</Tooltip>
|
|
119
|
+
|
|
120
|
+
<Tooltip content="Tooltip on left" side="left">
|
|
121
|
+
<Button>Left</Button>
|
|
122
|
+
</Tooltip>
|
|
123
|
+
</div>
|
|
124
|
+
);
|
|
17
125
|
```
|
|
126
|
+
|
|
127
|
+
### Rich Content
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
import { Button } from "@telegraph/button";
|
|
131
|
+
import { Tooltip } from "@telegraph/tooltip";
|
|
132
|
+
import { Mail, Phone, User } from "lucide-react";
|
|
133
|
+
|
|
134
|
+
export const RichContentTooltip = () => (
|
|
135
|
+
<Tooltip
|
|
136
|
+
content={
|
|
137
|
+
<div className="user-tooltip">
|
|
138
|
+
<div className="user-header">
|
|
139
|
+
<User size={20} />
|
|
140
|
+
<strong>John Doe</strong>
|
|
141
|
+
</div>
|
|
142
|
+
<div className="user-details">
|
|
143
|
+
<div>
|
|
144
|
+
<Mail size={16} /> john@example.com
|
|
145
|
+
</div>
|
|
146
|
+
<div>
|
|
147
|
+
<Phone size={16} /> +1 (555) 123-4567
|
|
148
|
+
</div>
|
|
149
|
+
</div>
|
|
150
|
+
</div>
|
|
151
|
+
}
|
|
152
|
+
>
|
|
153
|
+
<Button variant="ghost">View Profile</Button>
|
|
154
|
+
</Tooltip>
|
|
155
|
+
);
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Custom Delays
|
|
159
|
+
|
|
160
|
+
```tsx
|
|
161
|
+
import { Button } from "@telegraph/button";
|
|
162
|
+
import { Tooltip } from "@telegraph/tooltip";
|
|
163
|
+
|
|
164
|
+
export const CustomDelayTooltips = () => (
|
|
165
|
+
<div>
|
|
166
|
+
{/* Instant tooltip */}
|
|
167
|
+
<Tooltip content="Shows immediately" delayDuration={0}>
|
|
168
|
+
<Button>Instant</Button>
|
|
169
|
+
</Tooltip>
|
|
170
|
+
|
|
171
|
+
{/* Slow tooltip */}
|
|
172
|
+
<Tooltip content="Takes time to show" delayDuration={1500}>
|
|
173
|
+
<Button>Slow</Button>
|
|
174
|
+
</Tooltip>
|
|
175
|
+
</div>
|
|
176
|
+
);
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Disabled Elements
|
|
180
|
+
|
|
181
|
+
```tsx
|
|
182
|
+
import { Button } from "@telegraph/button";
|
|
183
|
+
import { Tooltip } from "@telegraph/tooltip";
|
|
184
|
+
|
|
185
|
+
export const DisabledTooltip = () => (
|
|
186
|
+
<Tooltip content="This action is not available right now">
|
|
187
|
+
<span>
|
|
188
|
+
{" "}
|
|
189
|
+
{/* Wrapper needed for disabled elements */}
|
|
190
|
+
<Button disabled>Disabled Action</Button>
|
|
191
|
+
</span>
|
|
192
|
+
</Tooltip>
|
|
193
|
+
);
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Advanced Usage
|
|
197
|
+
|
|
198
|
+
### Conditional Tooltips
|
|
199
|
+
|
|
200
|
+
```tsx
|
|
201
|
+
import { Button } from "@telegraph/button";
|
|
202
|
+
import { Tooltip } from "@telegraph/tooltip";
|
|
203
|
+
|
|
204
|
+
export const ConditionalTooltip = ({ showTooltip, user }) => (
|
|
205
|
+
<Tooltip content={showTooltip ? `Hello, ${user.name}!` : undefined}>
|
|
206
|
+
<Button>{user.isLoggedIn ? "Dashboard" : "Sign In"}</Button>
|
|
207
|
+
</Tooltip>
|
|
208
|
+
);
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Interactive Tooltips
|
|
212
|
+
|
|
213
|
+
```tsx
|
|
214
|
+
import { Button } from "@telegraph/button";
|
|
215
|
+
import { Tooltip } from "@telegraph/tooltip";
|
|
216
|
+
import { Link } from "next/link";
|
|
217
|
+
|
|
218
|
+
export const InteractiveTooltip = () => (
|
|
219
|
+
<Tooltip
|
|
220
|
+
content={
|
|
221
|
+
<div className="interactive-tooltip">
|
|
222
|
+
<p>Need help with this feature?</p>
|
|
223
|
+
<div className="tooltip-actions">
|
|
224
|
+
<Link href="/docs">
|
|
225
|
+
<Button size="0" variant="ghost">
|
|
226
|
+
View Docs
|
|
227
|
+
</Button>
|
|
228
|
+
</Link>
|
|
229
|
+
<Button size="0" variant="outline">
|
|
230
|
+
Contact Support
|
|
231
|
+
</Button>
|
|
232
|
+
</div>
|
|
233
|
+
</div>
|
|
234
|
+
}
|
|
235
|
+
disableHoverableContent={false} // Allow hovering over tooltip content
|
|
236
|
+
delayDuration={300}
|
|
237
|
+
>
|
|
238
|
+
<Button variant="ghost" icon={{ icon: HelpCircle, alt: "Help" }}>
|
|
239
|
+
Help
|
|
240
|
+
</Button>
|
|
241
|
+
</Tooltip>
|
|
242
|
+
);
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Form Field Tooltips
|
|
246
|
+
|
|
247
|
+
```tsx
|
|
248
|
+
import { Input } from "@telegraph/input";
|
|
249
|
+
import { Tooltip } from "@telegraph/tooltip";
|
|
250
|
+
import { HelpCircle } from "lucide-react";
|
|
251
|
+
|
|
252
|
+
export const FormWithTooltips = () => (
|
|
253
|
+
<form className="form-with-tooltips">
|
|
254
|
+
<div className="form-field">
|
|
255
|
+
<label htmlFor="username">
|
|
256
|
+
Username
|
|
257
|
+
<Tooltip
|
|
258
|
+
content="Username must be 3-20 characters long and contain only letters, numbers, and underscores"
|
|
259
|
+
side="right"
|
|
260
|
+
>
|
|
261
|
+
<HelpCircle size={16} className="help-icon" />
|
|
262
|
+
</Tooltip>
|
|
263
|
+
</label>
|
|
264
|
+
<Input id="username" placeholder="Enter username" />
|
|
265
|
+
</div>
|
|
266
|
+
|
|
267
|
+
<div className="form-field">
|
|
268
|
+
<label htmlFor="email">
|
|
269
|
+
Email Address
|
|
270
|
+
<Tooltip
|
|
271
|
+
content="We'll use this email for account notifications and password recovery"
|
|
272
|
+
side="right"
|
|
273
|
+
>
|
|
274
|
+
<HelpCircle size={16} className="help-icon" />
|
|
275
|
+
</Tooltip>
|
|
276
|
+
</label>
|
|
277
|
+
<Input id="email" type="email" placeholder="Enter email" />
|
|
278
|
+
</div>
|
|
279
|
+
</form>
|
|
280
|
+
);
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Tooltip with Arrow Positioning
|
|
284
|
+
|
|
285
|
+
```tsx
|
|
286
|
+
import { Button } from "@telegraph/button";
|
|
287
|
+
import { Tooltip } from "@telegraph/tooltip";
|
|
288
|
+
|
|
289
|
+
export const ArrowTooltips = () => (
|
|
290
|
+
<div className="tooltip-demo-grid">
|
|
291
|
+
<Tooltip content="Aligned to start" align="start">
|
|
292
|
+
<Button>Start</Button>
|
|
293
|
+
</Tooltip>
|
|
294
|
+
|
|
295
|
+
<Tooltip content="Centered alignment" align="center">
|
|
296
|
+
<Button>Center</Button>
|
|
297
|
+
</Tooltip>
|
|
298
|
+
|
|
299
|
+
<Tooltip content="Aligned to end" align="end">
|
|
300
|
+
<Button>End</Button>
|
|
301
|
+
</Tooltip>
|
|
302
|
+
</div>
|
|
303
|
+
);
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### Data Visualization Tooltips
|
|
307
|
+
|
|
308
|
+
```tsx
|
|
309
|
+
import { Tooltip } from "@telegraph/tooltip";
|
|
310
|
+
|
|
311
|
+
export const ChartTooltip = ({ dataPoint }) => (
|
|
312
|
+
<Tooltip
|
|
313
|
+
content={
|
|
314
|
+
<div className="chart-tooltip">
|
|
315
|
+
<div className="tooltip-title">{dataPoint.label}</div>
|
|
316
|
+
<div className="tooltip-value">
|
|
317
|
+
<span className="value">{dataPoint.value}</span>
|
|
318
|
+
<span className="unit">{dataPoint.unit}</span>
|
|
319
|
+
</div>
|
|
320
|
+
<div className="tooltip-change">
|
|
321
|
+
<span
|
|
322
|
+
className={`change ${dataPoint.change >= 0 ? "positive" : "negative"}`}
|
|
323
|
+
>
|
|
324
|
+
{dataPoint.change >= 0 ? "+" : ""}
|
|
325
|
+
{dataPoint.change}%
|
|
326
|
+
</span>
|
|
327
|
+
<span className="period">vs last period</span>
|
|
328
|
+
</div>
|
|
329
|
+
</div>
|
|
330
|
+
}
|
|
331
|
+
side="top"
|
|
332
|
+
sideOffset={8}
|
|
333
|
+
>
|
|
334
|
+
<div className="chart-bar" style={{ height: `${dataPoint.value}%` }} />
|
|
335
|
+
</Tooltip>
|
|
336
|
+
);
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Keyboard Navigation Tooltips
|
|
340
|
+
|
|
341
|
+
```tsx
|
|
342
|
+
import { Kbd } from "@telegraph/kbd";
|
|
343
|
+
import { Tooltip } from "@telegraph/tooltip";
|
|
344
|
+
|
|
345
|
+
export const KeyboardTooltips = () => (
|
|
346
|
+
<div className="keyboard-shortcuts">
|
|
347
|
+
<Tooltip
|
|
348
|
+
content={
|
|
349
|
+
<div>
|
|
350
|
+
Quick save: <Kbd>Ctrl</Kbd> + <Kbd>S</Kbd>
|
|
351
|
+
</div>
|
|
352
|
+
}
|
|
353
|
+
>
|
|
354
|
+
<Button>Save Document</Button>
|
|
355
|
+
</Tooltip>
|
|
356
|
+
|
|
357
|
+
<Tooltip
|
|
358
|
+
content={
|
|
359
|
+
<div>
|
|
360
|
+
Copy: <Kbd>Ctrl</Kbd> + <Kbd>C</Kbd>
|
|
361
|
+
<br />
|
|
362
|
+
Paste: <Kbd>Ctrl</Kbd> + <Kbd>V</Kbd>
|
|
363
|
+
</div>
|
|
364
|
+
}
|
|
365
|
+
>
|
|
366
|
+
<Button>Edit</Button>
|
|
367
|
+
</Tooltip>
|
|
368
|
+
</div>
|
|
369
|
+
);
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### Status Indicator Tooltips
|
|
373
|
+
|
|
374
|
+
```tsx
|
|
375
|
+
import { Tooltip } from "@telegraph/tooltip";
|
|
376
|
+
import { AlertCircle, CheckCircle, Clock, XCircle } from "lucide-react";
|
|
377
|
+
|
|
378
|
+
export const StatusTooltips = ({ status }) => {
|
|
379
|
+
const statusConfig = {
|
|
380
|
+
success: {
|
|
381
|
+
icon: CheckCircle,
|
|
382
|
+
color: "green",
|
|
383
|
+
message: "Operation completed successfully",
|
|
384
|
+
},
|
|
385
|
+
warning: {
|
|
386
|
+
icon: AlertCircle,
|
|
387
|
+
color: "yellow",
|
|
388
|
+
message: "Operation completed with warnings",
|
|
389
|
+
},
|
|
390
|
+
error: {
|
|
391
|
+
icon: XCircle,
|
|
392
|
+
color: "red",
|
|
393
|
+
message: "Operation failed. Please try again",
|
|
394
|
+
},
|
|
395
|
+
pending: {
|
|
396
|
+
icon: Clock,
|
|
397
|
+
color: "blue",
|
|
398
|
+
message: "Operation is still in progress",
|
|
399
|
+
},
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
const config = statusConfig[status];
|
|
403
|
+
|
|
404
|
+
return (
|
|
405
|
+
<Tooltip content={config.message}>
|
|
406
|
+
<config.icon size={20} className={`status-icon status-${config.color}`} />
|
|
407
|
+
</Tooltip>
|
|
408
|
+
);
|
|
409
|
+
};
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### Multi-level Tooltips
|
|
413
|
+
|
|
414
|
+
```tsx
|
|
415
|
+
import { Button } from "@telegraph/button";
|
|
416
|
+
import { Tooltip } from "@telegraph/tooltip";
|
|
417
|
+
import { Settings, User } from "lucide-react";
|
|
418
|
+
|
|
419
|
+
export const NestedTooltips = () => (
|
|
420
|
+
<div className="nested-tooltip-example">
|
|
421
|
+
<Tooltip content="User account settings">
|
|
422
|
+
<Button icon={{ icon: User, alt: "User" }}>Profile</Button>
|
|
423
|
+
</Tooltip>
|
|
424
|
+
|
|
425
|
+
<Tooltip
|
|
426
|
+
content={
|
|
427
|
+
<div>
|
|
428
|
+
<div>Advanced Settings</div>
|
|
429
|
+
<div className="nested-actions">
|
|
430
|
+
<Tooltip content="Manage account preferences" side="right">
|
|
431
|
+
<Button size="0" variant="ghost">
|
|
432
|
+
Preferences
|
|
433
|
+
</Button>
|
|
434
|
+
</Tooltip>
|
|
435
|
+
<Tooltip content="Security and privacy settings" side="right">
|
|
436
|
+
<Button size="0" variant="ghost">
|
|
437
|
+
Security
|
|
438
|
+
</Button>
|
|
439
|
+
</Tooltip>
|
|
440
|
+
</div>
|
|
441
|
+
</div>
|
|
442
|
+
}
|
|
443
|
+
disableHoverableContent={false}
|
|
444
|
+
>
|
|
445
|
+
<Button icon={{ icon: Settings, alt: "Settings" }}>Settings</Button>
|
|
446
|
+
</Tooltip>
|
|
447
|
+
</div>
|
|
448
|
+
);
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
## Accessibility
|
|
452
|
+
|
|
453
|
+
- ✅ **Keyboard Navigation**: Full keyboard support with proper focus management
|
|
454
|
+
- ✅ **Screen Reader Support**: Proper ARIA attributes and announcements
|
|
455
|
+
- ✅ **Focus Management**: Tooltips appear on focus for keyboard users
|
|
456
|
+
- ✅ **High Contrast**: Compatible with high contrast modes
|
|
457
|
+
- ✅ **Reduced Motion**: Respects user's motion preferences
|
|
458
|
+
|
|
459
|
+
### Keyboard Shortcuts
|
|
460
|
+
|
|
461
|
+
| Key | Action |
|
|
462
|
+
| ----------------- | --------------------------------------------- |
|
|
463
|
+
| `Tab` | Show tooltip when element receives focus |
|
|
464
|
+
| `Escape` | Hide tooltip when focused |
|
|
465
|
+
| `Space` / `Enter` | Activate trigger element (button, link, etc.) |
|
|
466
|
+
|
|
467
|
+
### ARIA Attributes
|
|
468
|
+
|
|
469
|
+
- `role="tooltip"` - Applied to tooltip content
|
|
470
|
+
- `aria-describedby` - Links trigger to tooltip content
|
|
471
|
+
- `aria-hidden` - Properly manages tooltip visibility for screen readers
|
|
472
|
+
- `id` - Unique identifier linking tooltip to trigger
|
|
473
|
+
|
|
474
|
+
### Best Practices
|
|
475
|
+
|
|
476
|
+
1. **Concise Content**: Keep tooltip text brief and informative
|
|
477
|
+
2. **Essential Information**: Only include truly helpful information
|
|
478
|
+
3. **Avoid Interactive Content**: Use sparingly for complex interactions
|
|
479
|
+
4. **Keyboard Access**: Ensure tooltips work with keyboard navigation
|
|
480
|
+
5. **Mobile Considerations**: Consider touch interaction patterns
|
|
481
|
+
|
|
482
|
+
## Examples
|
|
483
|
+
|
|
484
|
+
### Basic Example
|
|
485
|
+
|
|
486
|
+
```tsx
|
|
487
|
+
import { Button } from "@telegraph/button";
|
|
488
|
+
import { Tooltip } from "@telegraph/tooltip";
|
|
489
|
+
|
|
490
|
+
export const BasicExample = () => (
|
|
491
|
+
<Tooltip content="This will save your current work">
|
|
492
|
+
<Button>Save Changes</Button>
|
|
493
|
+
</Tooltip>
|
|
494
|
+
);
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
### Advanced Example
|
|
498
|
+
|
|
499
|
+
```tsx
|
|
500
|
+
import { Badge } from "@telegraph/badge";
|
|
501
|
+
import { Button } from "@telegraph/button";
|
|
502
|
+
import { Tooltip } from "@telegraph/tooltip";
|
|
503
|
+
import { Calendar, Mail, MapPin, User } from "lucide-react";
|
|
504
|
+
|
|
505
|
+
export const UserProfileTooltip = ({ user }) => (
|
|
506
|
+
<Tooltip
|
|
507
|
+
content={
|
|
508
|
+
<div className="user-profile-tooltip">
|
|
509
|
+
<div className="user-header">
|
|
510
|
+
<div className="user-avatar">
|
|
511
|
+
<User size={24} />
|
|
512
|
+
</div>
|
|
513
|
+
<div className="user-info">
|
|
514
|
+
<h4>{user.name}</h4>
|
|
515
|
+
<Badge variant="soft" color="green">
|
|
516
|
+
Online
|
|
517
|
+
</Badge>
|
|
518
|
+
</div>
|
|
519
|
+
</div>
|
|
520
|
+
|
|
521
|
+
<div className="user-details">
|
|
522
|
+
<div className="detail-item">
|
|
523
|
+
<Mail size={14} />
|
|
524
|
+
<span>{user.email}</span>
|
|
525
|
+
</div>
|
|
526
|
+
<div className="detail-item">
|
|
527
|
+
<MapPin size={14} />
|
|
528
|
+
<span>{user.location}</span>
|
|
529
|
+
</div>
|
|
530
|
+
<div className="detail-item">
|
|
531
|
+
<Calendar size={14} />
|
|
532
|
+
<span>Joined {user.joinDate}</span>
|
|
533
|
+
</div>
|
|
534
|
+
</div>
|
|
535
|
+
|
|
536
|
+
<div className="user-actions">
|
|
537
|
+
<Button size="0" variant="outline">
|
|
538
|
+
View Profile
|
|
539
|
+
</Button>
|
|
540
|
+
<Button size="0" variant="ghost">
|
|
541
|
+
Send Message
|
|
542
|
+
</Button>
|
|
543
|
+
</div>
|
|
544
|
+
</div>
|
|
545
|
+
}
|
|
546
|
+
side="right"
|
|
547
|
+
align="start"
|
|
548
|
+
disableHoverableContent={false}
|
|
549
|
+
>
|
|
550
|
+
<div className="user-mention">@{user.username}</div>
|
|
551
|
+
</Tooltip>
|
|
552
|
+
);
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
### Real-world Example
|
|
556
|
+
|
|
557
|
+
```tsx
|
|
558
|
+
import { Badge } from "@telegraph/badge";
|
|
559
|
+
import { Button } from "@telegraph/button";
|
|
560
|
+
import { Tooltip } from "@telegraph/tooltip";
|
|
561
|
+
import {
|
|
562
|
+
Bell,
|
|
563
|
+
CreditCard,
|
|
564
|
+
HelpCircle,
|
|
565
|
+
LogOut,
|
|
566
|
+
Settings,
|
|
567
|
+
Shield,
|
|
568
|
+
User,
|
|
569
|
+
Zap,
|
|
570
|
+
} from "lucide-react";
|
|
571
|
+
|
|
572
|
+
export const ApplicationHeader = ({ user, notifications }) => (
|
|
573
|
+
<header className="app-header">
|
|
574
|
+
<div className="header-brand">
|
|
575
|
+
<h1>MyApp</h1>
|
|
576
|
+
</div>
|
|
577
|
+
|
|
578
|
+
<nav className="header-nav">
|
|
579
|
+
<Tooltip content="View all notifications">
|
|
580
|
+
<Button variant="ghost" icon={{ icon: Bell, alt: "Notifications" }}>
|
|
581
|
+
{notifications.length > 0 && (
|
|
582
|
+
<Badge variant="solid" color="red" size="0">
|
|
583
|
+
{notifications.length}
|
|
584
|
+
</Badge>
|
|
585
|
+
)}
|
|
586
|
+
</Button>
|
|
587
|
+
</Tooltip>
|
|
588
|
+
|
|
589
|
+
<Tooltip
|
|
590
|
+
content={
|
|
591
|
+
<div className="feature-tooltip">
|
|
592
|
+
<div className="tooltip-header">
|
|
593
|
+
<Zap size={16} />
|
|
594
|
+
<strong>Premium Features</strong>
|
|
595
|
+
</div>
|
|
596
|
+
<ul>
|
|
597
|
+
<li>Advanced analytics</li>
|
|
598
|
+
<li>Priority support</li>
|
|
599
|
+
<li>Custom integrations</li>
|
|
600
|
+
</ul>
|
|
601
|
+
<Button size="0" variant="outline">
|
|
602
|
+
Upgrade Now
|
|
603
|
+
</Button>
|
|
604
|
+
</div>
|
|
605
|
+
}
|
|
606
|
+
side="bottom"
|
|
607
|
+
align="end"
|
|
608
|
+
disableHoverableContent={false}
|
|
609
|
+
>
|
|
610
|
+
<Button variant="ghost" icon={{ icon: Zap, alt: "Premium" }}>
|
|
611
|
+
Premium
|
|
612
|
+
</Button>
|
|
613
|
+
</Tooltip>
|
|
614
|
+
|
|
615
|
+
<Tooltip
|
|
616
|
+
content={
|
|
617
|
+
<div className="help-tooltip">
|
|
618
|
+
<div className="help-section">
|
|
619
|
+
<h4>Need Help?</h4>
|
|
620
|
+
<div className="help-links">
|
|
621
|
+
<a href="/docs">Documentation</a>
|
|
622
|
+
<a href="/support">Contact Support</a>
|
|
623
|
+
<a href="/tutorials">Video Tutorials</a>
|
|
624
|
+
</div>
|
|
625
|
+
</div>
|
|
626
|
+
<div className="help-shortcuts">
|
|
627
|
+
<h5>Keyboard Shortcuts</h5>
|
|
628
|
+
<div className="shortcut">
|
|
629
|
+
<Kbd>Ctrl</Kbd> + <Kbd>K</Kbd> - Command palette
|
|
630
|
+
</div>
|
|
631
|
+
<div className="shortcut">
|
|
632
|
+
<Kbd>?</Kbd> - Show all shortcuts
|
|
633
|
+
</div>
|
|
634
|
+
</div>
|
|
635
|
+
</div>
|
|
636
|
+
}
|
|
637
|
+
side="bottom"
|
|
638
|
+
disableHoverableContent={false}
|
|
639
|
+
>
|
|
640
|
+
<Button variant="ghost" icon={{ icon: HelpCircle, alt: "Help" }} />
|
|
641
|
+
</Tooltip>
|
|
642
|
+
|
|
643
|
+
<Tooltip
|
|
644
|
+
content={
|
|
645
|
+
<div className="user-menu-tooltip">
|
|
646
|
+
<div className="user-info">
|
|
647
|
+
<div className="user-avatar">
|
|
648
|
+
<User size={20} />
|
|
649
|
+
</div>
|
|
650
|
+
<div>
|
|
651
|
+
<div className="user-name">{user.name}</div>
|
|
652
|
+
<div className="user-email">{user.email}</div>
|
|
653
|
+
<Badge
|
|
654
|
+
variant="soft"
|
|
655
|
+
color={user.plan === "premium" ? "purple" : "gray"}
|
|
656
|
+
size="0"
|
|
657
|
+
>
|
|
658
|
+
{user.plan}
|
|
659
|
+
</Badge>
|
|
660
|
+
</div>
|
|
661
|
+
</div>
|
|
662
|
+
|
|
663
|
+
<div className="menu-divider" />
|
|
664
|
+
|
|
665
|
+
<div className="menu-items">
|
|
666
|
+
<div className="menu-item">
|
|
667
|
+
<User size={16} />
|
|
668
|
+
<span>Profile Settings</span>
|
|
669
|
+
</div>
|
|
670
|
+
<div className="menu-item">
|
|
671
|
+
<Shield size={16} />
|
|
672
|
+
<span>Privacy & Security</span>
|
|
673
|
+
</div>
|
|
674
|
+
<div className="menu-item">
|
|
675
|
+
<CreditCard size={16} />
|
|
676
|
+
<span>Billing</span>
|
|
677
|
+
</div>
|
|
678
|
+
<div className="menu-item">
|
|
679
|
+
<Settings size={16} />
|
|
680
|
+
<span>Preferences</span>
|
|
681
|
+
</div>
|
|
682
|
+
</div>
|
|
683
|
+
|
|
684
|
+
<div className="menu-divider" />
|
|
685
|
+
|
|
686
|
+
<div className="menu-item danger">
|
|
687
|
+
<LogOut size={16} />
|
|
688
|
+
<span>Sign Out</span>
|
|
689
|
+
</div>
|
|
690
|
+
</div>
|
|
691
|
+
}
|
|
692
|
+
side="bottom"
|
|
693
|
+
align="end"
|
|
694
|
+
disableHoverableContent={false}
|
|
695
|
+
>
|
|
696
|
+
<Button variant="ghost" className="user-menu-trigger">
|
|
697
|
+
<div className="user-avatar-small">
|
|
698
|
+
<User size={16} />
|
|
699
|
+
</div>
|
|
700
|
+
<span className="user-name-short">{user.name.split(" ")[0]}</span>
|
|
701
|
+
</Button>
|
|
702
|
+
</Tooltip>
|
|
703
|
+
</nav>
|
|
704
|
+
</header>
|
|
705
|
+
);
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
## References
|
|
709
|
+
|
|
710
|
+
- [Storybook Demo](https://storybook.telegraph.dev/?path=/docs/tooltip)
|
|
711
|
+
- [Radix UI Tooltip](https://www.radix-ui.com/primitives/docs/components/tooltip) - Base primitive
|
|
712
|
+
- [Popover Component](../popover/README.md) - Related overlay component
|
|
713
|
+
|
|
714
|
+
## Contributing
|
|
715
|
+
|
|
716
|
+
See our [Contributing Guide](../../CONTRIBUTING.md) for more details.
|
|
717
|
+
|
|
718
|
+
## License
|
|
719
|
+
|
|
720
|
+
MIT License - see [LICENSE](../../LICENSE) for details.
|