└── README.md
/README.md:
--------------------------------------------------------------------------------
1 | ## Shadcn Lazy Tooltip
2 |
3 | Lazy-mount the shadcn/ui `Tooltip` tree only on first hover/touch. This removes the initial render cost of the entire tooltip/provider/popper stack until a user actually needs it.
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | ---
12 |
13 | ### Why
14 | - **Avoids eager mounting** (provider/popup/portal elements on first paint)
15 | - **Cuts initial render time** when many tooltips exist (lists, grids)
16 | - **Zero behavior change** (after first hover)
17 |
18 | ---
19 |
20 | ### Install
21 |
22 | Prereq: you already use shadcn/ui and have its `Tooltip` component.
23 |
24 | - Add shadcn Tooltip (if missing):
25 |
26 | ```bash
27 | bunx shadcn@latest add tooltip
28 | ```
29 |
30 | - Create `components/lazy-tooltip.tsx` with:
31 |
32 | ```tsx
33 | 'use client';
34 |
35 | import { useState } from 'react';
36 | import {
37 | Tooltip,
38 | TooltipContent,
39 | TooltipTrigger,
40 | } from '@/components/ui/tooltip';
41 |
42 | export function LazyTooltip({
43 | children,
44 | content,
45 | asChild = true,
46 | }: {
47 | children: React.ReactElement;
48 | content: React.ReactNode;
49 | asChild?: boolean;
50 | }) {
51 | const [enabled, setEnabled] = useState(false);
52 |
53 | const triggerProps = {
54 | onPointerEnter: () => setEnabled(true),
55 | onTouchStart: () => setEnabled(true),
56 | } as const;
57 |
58 | if (!enabled) {
59 | // Clone to attach events without mounting Tooltip tree
60 | return { ...children, props: { ...children.props, ...triggerProps } };
61 | }
62 |
63 | return (
64 |
65 |
66 | {
67 | // Attach the same listeners so once active, hover continues to work
68 | { ...children, props: { ...children.props, ...triggerProps } }
69 | }
70 |
71 | {content}
72 |
73 | );
74 | }
75 | ```
76 |
77 | ---
78 |
79 | ### Usage
80 |
81 | ```tsx
82 | import { Button } from '@/components/ui/button';
83 | import { LazyTooltip } from '@/components/lazy-tooltip';
84 |
85 | export function Example() {
86 | return (
87 |
88 |
89 |
90 | );
91 | }
92 | ```
93 |
94 |
95 | ---
96 |
97 | ### API
98 |
99 | - `children: React.ReactElement` — element to trigger the tooltip
100 | - `content: React.ReactNode` — tooltip body
101 | - `asChild?: boolean = true` — forwarded to shadcn `TooltipTrigger`
102 |
103 |
104 | ---
105 |
106 | ### License
107 |
108 | MIT
109 |
--------------------------------------------------------------------------------