└── 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 | lazy_tooltip 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 | --------------------------------------------------------------------------------