solid-tom-ui 1.0.11 → 1.0.14

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.
Files changed (118) hide show
  1. package/README.md +246 -246
  2. package/dist/README.md +246 -246
  3. package/dist/components/avatar/avatar.js.map +1 -1
  4. package/dist/components/badge/badge.js.map +1 -1
  5. package/dist/components/breadcrumb/breadcrumb.js.map +1 -1
  6. package/dist/components/button/button.js.map +1 -1
  7. package/dist/components/carousel/carousel.js.map +1 -1
  8. package/dist/components/chat-bubble/chatBubble.js.map +1 -1
  9. package/dist/components/checkbox/checkbox.js.map +1 -1
  10. package/dist/components/collapse/collapse.js.map +1 -1
  11. package/dist/components/context-menu/context-menu.js.map +1 -1
  12. package/dist/components/context-menu/context-menu.store.js.map +1 -1
  13. package/dist/components/divider/divider.js.map +1 -1
  14. package/dist/components/dropdown/dropdown.js.map +1 -1
  15. package/dist/components/dropdown/dropdown.store.js.map +1 -1
  16. package/dist/components/float-button/float-button.js.map +1 -1
  17. package/dist/components/hover-3d-image/hover-3d-image.js.map +1 -1
  18. package/dist/components/image-preview/image-preview.js.map +1 -1
  19. package/dist/components/input/input.js.map +1 -1
  20. package/dist/components/input/input.utils.js.map +1 -1
  21. package/dist/components/input/variants/input-color.js.map +1 -1
  22. package/dist/components/input/variants/input-date.js.map +1 -1
  23. package/dist/components/input/variants/input-number.d.ts.map +1 -1
  24. package/dist/components/input/variants/input-number.js +1 -1
  25. package/dist/components/input/variants/input-number.js.map +1 -1
  26. package/dist/components/input/variants/input-otp.js.map +1 -1
  27. package/dist/components/input/variants/input-password.js.map +1 -1
  28. package/dist/components/input/variants/input-radio.js.map +1 -1
  29. package/dist/components/input/variants/input-range.js.map +1 -1
  30. package/dist/components/input/variants/input-text.d.ts.map +1 -1
  31. package/dist/components/input/variants/input-text.js +1 -1
  32. package/dist/components/input/variants/input-text.js.map +1 -1
  33. package/dist/components/input/variants/input-textarea.js.map +1 -1
  34. package/dist/components/loading/loading.js.map +1 -1
  35. package/dist/components/mansory/mansory.js.map +1 -1
  36. package/dist/components/menu/menu.js.map +1 -1
  37. package/dist/components/modal/modal.js.map +1 -1
  38. package/dist/components/modal/modalContext.js.map +1 -1
  39. package/dist/components/pagination/pagination.js.map +1 -1
  40. package/dist/components/progress-bar/progress-bar.js.map +1 -1
  41. package/dist/components/qr-code/qr-code.js.map +1 -1
  42. package/dist/components/select/select.js.map +1 -1
  43. package/dist/components/select-zone/select-zone.js.map +1 -1
  44. package/dist/components/skeleton/skeleton.js.map +1 -1
  45. package/dist/components/slider/slider.js.map +1 -1
  46. package/dist/components/splitter/splitter.js.map +1 -1
  47. package/dist/components/steps/steps.js.map +1 -1
  48. package/dist/components/swap/swap.js.map +1 -1
  49. package/dist/components/switch/switch.js.map +1 -1
  50. package/dist/components/tab/tab.js.map +1 -1
  51. package/dist/components/table/table.js.map +1 -1
  52. package/dist/components/timeline/timeline.js.map +1 -1
  53. package/dist/components/toast/icons/ErrorIcon.js.map +1 -1
  54. package/dist/components/toast/icons/IconCircle.js.map +1 -1
  55. package/dist/components/toast/icons/InfoIcon.js.map +1 -1
  56. package/dist/components/toast/icons/LoaderIcon.js.map +1 -1
  57. package/dist/components/toast/icons/SuccessIcon.js.map +1 -1
  58. package/dist/components/toast/icons/WarningIcon.js.map +1 -1
  59. package/dist/components/toast/toast.js.map +1 -1
  60. package/dist/components/toast/toast.store.js.map +1 -1
  61. package/dist/components/tooltip/tooltip.js.map +1 -1
  62. package/dist/components/tour/tour.js.map +1 -1
  63. package/dist/components/upload/upload.js.map +1 -1
  64. package/dist/components/z-index/z-index.context.js.map +1 -1
  65. package/dist/components/z-index/z-index.js.map +1 -1
  66. package/dist/components/z-index/z-index.store.js.map +1 -1
  67. package/dist/components/z-index/z-index.types.js.map +1 -1
  68. package/dist/package.json +1 -1
  69. package/dist/skill/avatar.skill.md.txt +255 -255
  70. package/dist/skill/badge.skill.md.txt +223 -223
  71. package/dist/skill/breadcrumb.skill.md.txt +177 -177
  72. package/dist/skill/button.skill.md.txt +198 -198
  73. package/dist/skill/carousel.skill.md.txt +406 -406
  74. package/dist/skill/chat-bubble.skill.md.txt +342 -342
  75. package/dist/skill/checkbox.skill.md.txt +326 -326
  76. package/dist/skill/code-preview.skill.md.txt +240 -240
  77. package/dist/skill/collapse.skill.md.txt +329 -329
  78. package/dist/skill/context-menu.skill.md.txt +233 -233
  79. package/dist/skill/diff.skill.md.txt +244 -244
  80. package/dist/skill/divider.skill.md.txt +151 -151
  81. package/dist/skill/doc.skill.md.txt +191 -191
  82. package/dist/skill/drawer.skill.md.txt +157 -157
  83. package/dist/skill/dropdown.skill.md.txt +198 -198
  84. package/dist/skill/float-button.skill.md.txt +315 -315
  85. package/dist/skill/hover-3d-image.skill.md.txt +120 -120
  86. package/dist/skill/iframe.skill.md.txt +114 -114
  87. package/dist/skill/image-preview.skill.md.txt +162 -162
  88. package/dist/skill/indicator.skill.md.txt +60 -60
  89. package/dist/skill/input.skill.md.txt +489 -489
  90. package/dist/skill/loading.skill.md.txt +127 -127
  91. package/dist/skill/menu.skill.md.txt +476 -476
  92. package/dist/skill/modal.skill.md.txt +359 -359
  93. package/dist/skill/pagination.skill.md.txt +405 -405
  94. package/dist/skill/progress-bar.skill.md.txt +207 -207
  95. package/dist/skill/qr-code.skill.md.txt +136 -136
  96. package/dist/skill/rating.skill.md.txt +167 -167
  97. package/dist/skill/select-zone.skill.md.txt +93 -93
  98. package/dist/skill/select.skill.md.txt +663 -663
  99. package/dist/skill/skeleton.skill.md.txt +192 -192
  100. package/dist/skill/slider.skill.md.txt +404 -404
  101. package/dist/skill/splitter.skill.md.txt +411 -411
  102. package/dist/skill/steps.skill.md.txt +264 -264
  103. package/dist/skill/swap.skill.md.txt +139 -139
  104. package/dist/skill/switch.skill.md.txt +191 -191
  105. package/dist/skill/tab.skill.md.txt +484 -484
  106. package/dist/skill/table.example.header.md.txt +666 -666
  107. package/dist/skill/table.skill.md.txt +1407 -1407
  108. package/dist/skill/text-rotate.skill.md.txt +186 -186
  109. package/dist/skill/timeline.skill.md.txt +247 -247
  110. package/dist/skill/toast.skill.md.txt +531 -531
  111. package/dist/skill/tooltip.skill.md.txt +222 -222
  112. package/dist/skill/tour.skill.md.txt +156 -156
  113. package/dist/skill/upload.skill.md.txt +358 -358
  114. package/dist/utils/cn.js.map +1 -1
  115. package/dist/utils/element-tracker.js.map +1 -1
  116. package/dist/utils/helper.js.map +1 -1
  117. package/dist/utils/hoc.js.map +1 -1
  118. package/package.json +132 -133
@@ -1,222 +1,222 @@
1
- ## COMPONENT IDENTITY
2
- - **Import**: `import { Tooltip } from 'solid-tom-ui';`
3
- - **Export**: `Tooltip` (named export)
4
- - **Framework**: SolidJS
5
- - **Purpose**: Tooltip component — DaisyUI + CVA styling engine; two render modes (default / portal) controlled by `type` prop
6
-
7
- ---
8
-
9
- ## TYPE SIGNATURE
10
-
11
- ```ts
12
- // Unified entry point — render mode controlled by `type` prop
13
- type TooltipProps = TooltipDefaultProps | TooltipPortalProps;
14
-
15
- // Default mode (IO-based, no overflow clip)
16
- type TooltipDefaultProps = {
17
- type?: 'default'; // omit or set 'default'
18
- hidden?: boolean;
19
- children: JSX.Element;
20
- position?: 'top' | 'bottom' | 'left' | 'right'; // default: 'top'
21
- color?: BaseColorProps; // default: 'neutral'
22
- zIndex?: number;
23
- class?: {
24
- root?: string;
25
- content?: string;
26
- };
27
- } & (WithContent | WithCustomContent);
28
-
29
- // Portal mode (event-delegation, escapes overflow:hidden)
30
- type TooltipPortalProps = {
31
- type: 'portal'; // REQUIRED to activate portal mode
32
- hidden?: boolean;
33
- children: SolidComponent;
34
- position?: 'top' | 'bottom' | 'left' | 'right'; // default: 'top'
35
- color?: BaseColorProps; // default: 'neutral'
36
- zIndex?: number;
37
- class?: {
38
- root?: string;
39
- content?: string;
40
- };
41
- /**
42
- * `id` of the overflow:hidden parent container.
43
- * Required when type='portal'.
44
- */
45
- containerId: string;
46
- } & (WithContent | WithCustomContent);
47
-
48
- // MUTUALLY EXCLUSIVE — use ONE of the two below:
49
- type WithContent = {
50
- content: string; // plain text tooltip
51
- customContent?: never;
52
- };
53
- type WithCustomContent = {
54
- content?: never;
55
- customContent: JSX.Element; // arbitrary JSX tooltip body
56
- };
57
- ```
58
-
59
- ### CONSTRAINTS
60
-
61
- - `content` and `customContent` are mutually exclusive.
62
- - `containerId` is **required** when `type='portal'`. TypeScript will error if omitted.
63
- - `TooltipPortal` is still exported as a backward-compat alias for `<Tooltip type="portal" ...>`.
64
-
65
- ---
66
-
67
- ## PROP REFERENCE
68
-
69
- | Prop | Type | Default | Description |
70
- | --------------- | ---------------------------------------- | ----------- | ----------------------------------------------------------------------------- |
71
- | `type` | `'default' \| 'portal'` | `'default'` | Render mode: IO-based (default) or event-delegation portal |
72
- | `children` | `JSX.Element` / `SolidComponent` | — | **Required.** The element that triggers the tooltip on hover |
73
- | `content` | `string` | — | Plain text shown in tooltip |
74
- | `customContent` | `JSX.Element` | — | Arbitrary JSX rendered inside tooltip bubble |
75
- | `position` | `'top' \| 'bottom' \| 'left' \| 'right'` | `'top'` | Direction tooltip appears relative to trigger |
76
- | `color` | `BaseColorProps` | `'neutral'` | DaisyUI color variant |
77
- | `hidden` | `boolean` | `undefined` | When `true`, bypasses tooltip wrapper entirely — renders children only |
78
- | `zIndex` | `number` | `undefined` | Override automatic z-index management |
79
- | `containerId` | `string` | — | **Required when `type='portal'`.** The `id` of the element causing clipping |
80
- | `class.root` | `string` | `undefined` | Extra Tailwind classes on the outer wrapper div |
81
- | `class.content` | `string` | `undefined` | Extra Tailwind classes on the tooltip bubble |
82
-
83
- ---
84
-
85
- ## TYPE DECISION RULE
86
-
87
- > **Always default to `type='default'` (or omit the `type` prop entirely).**
88
- > Only switch to `type='portal'` when the tooltip is **clipped by `overflow:hidden`, `overflow:clip`, or `clip-path`** on a parent container.
89
-
90
- | Situation | Choice |
91
- | ---------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
92
- | Tooltip renders normally, not clipped | `type='default'` _(default — no declaration needed)_ |
93
- | Tooltip is inside a container with `overflow:hidden` / `overflow:clip` | `type='portal'` + `containerId` pointing to that specific container |
94
- | Tooltip inside a scrollable table with hundreds of cells | `type='portal'` + same `containerId` for all tooltips (the table's wrapper) |
95
- | Not sure whether it will be clipped | Try default first; switch to portal only if you observe the tooltip being cut |
96
-
97
- ---
98
-
99
- ## CHOOSING THE RIGHT `containerId`
100
-
101
- > **`containerId` must identify the specific element that is causing the tooltip to be hidden — not a global ancestor.**
102
-
103
- 1. Find the element with `overflow:hidden` / `overflow:clip`.
104
- 2. Assign that element an `id`.
105
- 3. Pass that `id` as `containerId`.
106
-
107
- ### What NOT to use as `containerId`
108
-
109
- | ❌ Avoid | Why |
110
- | ---------------------------------------------- | ----------------------------------------------------------- |
111
- | `containerId="html-root"` (pointing to `<html>`) | Near-global listener — defeats all scoping |
112
- | `containerId="root"` (app root div) | Too broad — still covers the entire application |
113
-
114
- ---
115
-
116
- ## USAGE PATTERNS
117
-
118
- ### Pattern 1 — Plain text tooltip (most common)
119
-
120
- ```tsx
121
- <Tooltip content="Save your work" position="top" color="primary">
122
- <Button>Save</Button>
123
- </Tooltip>
124
- ```
125
-
126
- ### Pattern 2 — Custom JSX content
127
-
128
- ```tsx
129
- <Tooltip
130
- position="bottom"
131
- color="info"
132
- customContent={
133
- <div class="bg-info text-info-content rounded-lg p-2">
134
- <p class="font-bold">Title</p>
135
- <p class="text-sm">Description text</p>
136
- </div>
137
- }
138
- >
139
- <Button>Hover me</Button>
140
- </Tooltip>
141
- ```
142
-
143
- ### Pattern 3 — Conditionally hidden tooltip
144
-
145
- ```tsx
146
- <Tooltip content="Only when permitted" hidden={!userHasPermission}>
147
- <Button>Action</Button>
148
- </Tooltip>
149
- ```
150
-
151
- ### Pattern 4 — Portal mode (only when tooltip is clipped by overflow:hidden)
152
-
153
- ```tsx
154
- <div id="my-overflow-box" style={{ overflow: 'hidden' }}>
155
- <Tooltip type="portal" content="Escapes overflow!" containerId="my-overflow-box" position="top">
156
- <Button>Hover me</Button>
157
- </Tooltip>
158
- </div>
159
- ```
160
-
161
- ### Pattern 5 — Portal on many cells in a table (performance-optimized)
162
-
163
- ```tsx
164
- // All tooltips sharing the same containerId use ONE pair of listeners
165
- <div id="my-table-container" class="max-h-64 overflow-auto">
166
- <table>
167
- <tbody>
168
- <For each={rows}>
169
- {row => (
170
- <tr>
171
- <td>
172
- <Tooltip
173
- type="portal"
174
- content={row.label}
175
- position="top"
176
- color="primary"
177
- containerId="my-table-container"
178
- >
179
- <span>{row.value}</span>
180
- </Tooltip>
181
- </td>
182
- </tr>
183
- )}
184
- </For>
185
- </tbody>
186
- </table>
187
- </div>
188
- ```
189
-
190
- ---
191
-
192
- ## BEHAVIOR NOTES FOR AGENTS
193
-
194
- 1. **`hidden` prop short-circuits all tooltip logic** — when `hidden={true}`, renders `<>{children}</>` only.
195
-
196
- 2. **`type='default'` uses IntersectionObserver** — a CSS sentinel (`too08`) inside the wrapper becomes visible on `:hover`, triggering the IO callback which appends the bubble to `document.body`. Zero JS event listeners on the trigger.
197
-
198
- 3. **`type='portal'` uses event delegation** — internally uses a `WeakMap<Element, ContainerState>` keyed by the resolved container. Multiple tooltips with the same `containerId` share a single `mouseover`/`mouseout` listener pair.
199
-
200
- 4. **`containerId` timing** — registration is deferred via `queueMicrotask` so it is safe even when the container is a parent in the same JSX tree.
201
-
202
- 5. **`TooltipPortal` is a backward-compat alias** — `<TooltipPortal containerId="x" ...>` is equivalent to `<Tooltip type="portal" containerId="x" ...>`.
203
-
204
- ---
205
-
206
- ## COMMON MISTAKES TO AVOID
207
-
208
- | Mistake | Correct approach |
209
- | ------------------------------------------------------------ | -------------------------------------------------------------------------- |
210
- | Providing both `content` and `customContent` | Use only one — they are mutually exclusive |
211
- | Using `type='portal'` as the default for every tooltip | Only use it when the tooltip is actually clipped by overflow |
212
- | Using `type='portal'` without `containerId` | TypeScript will error — always provide `containerId` |
213
- | Using `containerId="html-root"` or pointing to `<html>` | Creates a near-global listener. Point to the specific overflow container |
214
- | Using different `containerId` values in a loop | All tooltips in the same container should share the same `containerId` |
215
-
216
- ---
217
-
218
- ## Component Conventions
219
-
220
- > **CSS encoding**: internal CSS classes use short encoded names (e.g. `too01`, `too06`) per project convention.
221
-
222
- > **Unique IDs**: uses `createUniqueId()` from `solid-js` — never `Math.random()` or `Date.now()`.
1
+ ## COMPONENT IDENTITY
2
+ - **Import**: `import { Tooltip } from 'solid-tom-ui';`
3
+ - **Export**: `Tooltip` (named export)
4
+ - **Framework**: SolidJS
5
+ - **Purpose**: Tooltip component — DaisyUI + CVA styling engine; two render modes (default / portal) controlled by `type` prop
6
+
7
+ ---
8
+
9
+ ## TYPE SIGNATURE
10
+
11
+ ```ts
12
+ // Unified entry point — render mode controlled by `type` prop
13
+ type TooltipProps = TooltipDefaultProps | TooltipPortalProps;
14
+
15
+ // Default mode (IO-based, no overflow clip)
16
+ type TooltipDefaultProps = {
17
+ type?: 'default'; // omit or set 'default'
18
+ hidden?: boolean;
19
+ children: JSX.Element;
20
+ position?: 'top' | 'bottom' | 'left' | 'right'; // default: 'top'
21
+ color?: BaseColorProps; // default: 'neutral'
22
+ zIndex?: number;
23
+ class?: {
24
+ root?: string;
25
+ content?: string;
26
+ };
27
+ } & (WithContent | WithCustomContent);
28
+
29
+ // Portal mode (event-delegation, escapes overflow:hidden)
30
+ type TooltipPortalProps = {
31
+ type: 'portal'; // REQUIRED to activate portal mode
32
+ hidden?: boolean;
33
+ children: SolidComponent;
34
+ position?: 'top' | 'bottom' | 'left' | 'right'; // default: 'top'
35
+ color?: BaseColorProps; // default: 'neutral'
36
+ zIndex?: number;
37
+ class?: {
38
+ root?: string;
39
+ content?: string;
40
+ };
41
+ /**
42
+ * `id` of the overflow:hidden parent container.
43
+ * Required when type='portal'.
44
+ */
45
+ containerId: string;
46
+ } & (WithContent | WithCustomContent);
47
+
48
+ // MUTUALLY EXCLUSIVE — use ONE of the two below:
49
+ type WithContent = {
50
+ content: string; // plain text tooltip
51
+ customContent?: never;
52
+ };
53
+ type WithCustomContent = {
54
+ content?: never;
55
+ customContent: JSX.Element; // arbitrary JSX tooltip body
56
+ };
57
+ ```
58
+
59
+ ### CONSTRAINTS
60
+
61
+ - `content` and `customContent` are mutually exclusive.
62
+ - `containerId` is **required** when `type='portal'`. TypeScript will error if omitted.
63
+ - `TooltipPortal` is still exported as a backward-compat alias for `<Tooltip type="portal" ...>`.
64
+
65
+ ---
66
+
67
+ ## PROP REFERENCE
68
+
69
+ | Prop | Type | Default | Description |
70
+ | --------------- | ---------------------------------------- | ----------- | ----------------------------------------------------------------------------- |
71
+ | `type` | `'default' \| 'portal'` | `'default'` | Render mode: IO-based (default) or event-delegation portal |
72
+ | `children` | `JSX.Element` / `SolidComponent` | — | **Required.** The element that triggers the tooltip on hover |
73
+ | `content` | `string` | — | Plain text shown in tooltip |
74
+ | `customContent` | `JSX.Element` | — | Arbitrary JSX rendered inside tooltip bubble |
75
+ | `position` | `'top' \| 'bottom' \| 'left' \| 'right'` | `'top'` | Direction tooltip appears relative to trigger |
76
+ | `color` | `BaseColorProps` | `'neutral'` | DaisyUI color variant |
77
+ | `hidden` | `boolean` | `undefined` | When `true`, bypasses tooltip wrapper entirely — renders children only |
78
+ | `zIndex` | `number` | `undefined` | Override automatic z-index management |
79
+ | `containerId` | `string` | — | **Required when `type='portal'`.** The `id` of the element causing clipping |
80
+ | `class.root` | `string` | `undefined` | Extra Tailwind classes on the outer wrapper div |
81
+ | `class.content` | `string` | `undefined` | Extra Tailwind classes on the tooltip bubble |
82
+
83
+ ---
84
+
85
+ ## TYPE DECISION RULE
86
+
87
+ > **Always default to `type='default'` (or omit the `type` prop entirely).**
88
+ > Only switch to `type='portal'` when the tooltip is **clipped by `overflow:hidden`, `overflow:clip`, or `clip-path`** on a parent container.
89
+
90
+ | Situation | Choice |
91
+ | ---------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
92
+ | Tooltip renders normally, not clipped | `type='default'` _(default — no declaration needed)_ |
93
+ | Tooltip is inside a container with `overflow:hidden` / `overflow:clip` | `type='portal'` + `containerId` pointing to that specific container |
94
+ | Tooltip inside a scrollable table with hundreds of cells | `type='portal'` + same `containerId` for all tooltips (the table's wrapper) |
95
+ | Not sure whether it will be clipped | Try default first; switch to portal only if you observe the tooltip being cut |
96
+
97
+ ---
98
+
99
+ ## CHOOSING THE RIGHT `containerId`
100
+
101
+ > **`containerId` must identify the specific element that is causing the tooltip to be hidden — not a global ancestor.**
102
+
103
+ 1. Find the element with `overflow:hidden` / `overflow:clip`.
104
+ 2. Assign that element an `id`.
105
+ 3. Pass that `id` as `containerId`.
106
+
107
+ ### What NOT to use as `containerId`
108
+
109
+ | ❌ Avoid | Why |
110
+ | ---------------------------------------------- | ----------------------------------------------------------- |
111
+ | `containerId="html-root"` (pointing to `<html>`) | Near-global listener — defeats all scoping |
112
+ | `containerId="root"` (app root div) | Too broad — still covers the entire application |
113
+
114
+ ---
115
+
116
+ ## USAGE PATTERNS
117
+
118
+ ### Pattern 1 — Plain text tooltip (most common)
119
+
120
+ ```tsx
121
+ <Tooltip content="Save your work" position="top" color="primary">
122
+ <Button>Save</Button>
123
+ </Tooltip>
124
+ ```
125
+
126
+ ### Pattern 2 — Custom JSX content
127
+
128
+ ```tsx
129
+ <Tooltip
130
+ position="bottom"
131
+ color="info"
132
+ customContent={
133
+ <div class="bg-info text-info-content rounded-lg p-2">
134
+ <p class="font-bold">Title</p>
135
+ <p class="text-sm">Description text</p>
136
+ </div>
137
+ }
138
+ >
139
+ <Button>Hover me</Button>
140
+ </Tooltip>
141
+ ```
142
+
143
+ ### Pattern 3 — Conditionally hidden tooltip
144
+
145
+ ```tsx
146
+ <Tooltip content="Only when permitted" hidden={!userHasPermission}>
147
+ <Button>Action</Button>
148
+ </Tooltip>
149
+ ```
150
+
151
+ ### Pattern 4 — Portal mode (only when tooltip is clipped by overflow:hidden)
152
+
153
+ ```tsx
154
+ <div id="my-overflow-box" style={{ overflow: 'hidden' }}>
155
+ <Tooltip type="portal" content="Escapes overflow!" containerId="my-overflow-box" position="top">
156
+ <Button>Hover me</Button>
157
+ </Tooltip>
158
+ </div>
159
+ ```
160
+
161
+ ### Pattern 5 — Portal on many cells in a table (performance-optimized)
162
+
163
+ ```tsx
164
+ // All tooltips sharing the same containerId use ONE pair of listeners
165
+ <div id="my-table-container" class="max-h-64 overflow-auto">
166
+ <table>
167
+ <tbody>
168
+ <For each={rows}>
169
+ {row => (
170
+ <tr>
171
+ <td>
172
+ <Tooltip
173
+ type="portal"
174
+ content={row.label}
175
+ position="top"
176
+ color="primary"
177
+ containerId="my-table-container"
178
+ >
179
+ <span>{row.value}</span>
180
+ </Tooltip>
181
+ </td>
182
+ </tr>
183
+ )}
184
+ </For>
185
+ </tbody>
186
+ </table>
187
+ </div>
188
+ ```
189
+
190
+ ---
191
+
192
+ ## BEHAVIOR NOTES FOR AGENTS
193
+
194
+ 1. **`hidden` prop short-circuits all tooltip logic** — when `hidden={true}`, renders `<>{children}</>` only.
195
+
196
+ 2. **`type='default'` uses IntersectionObserver** — a CSS sentinel (`too08`) inside the wrapper becomes visible on `:hover`, triggering the IO callback which appends the bubble to `document.body`. Zero JS event listeners on the trigger.
197
+
198
+ 3. **`type='portal'` uses event delegation** — internally uses a `WeakMap<Element, ContainerState>` keyed by the resolved container. Multiple tooltips with the same `containerId` share a single `mouseover`/`mouseout` listener pair.
199
+
200
+ 4. **`containerId` timing** — registration is deferred via `queueMicrotask` so it is safe even when the container is a parent in the same JSX tree.
201
+
202
+ 5. **`TooltipPortal` is a backward-compat alias** — `<TooltipPortal containerId="x" ...>` is equivalent to `<Tooltip type="portal" containerId="x" ...>`.
203
+
204
+ ---
205
+
206
+ ## COMMON MISTAKES TO AVOID
207
+
208
+ | Mistake | Correct approach |
209
+ | ------------------------------------------------------------ | -------------------------------------------------------------------------- |
210
+ | Providing both `content` and `customContent` | Use only one — they are mutually exclusive |
211
+ | Using `type='portal'` as the default for every tooltip | Only use it when the tooltip is actually clipped by overflow |
212
+ | Using `type='portal'` without `containerId` | TypeScript will error — always provide `containerId` |
213
+ | Using `containerId="html-root"` or pointing to `<html>` | Creates a near-global listener. Point to the specific overflow container |
214
+ | Using different `containerId` values in a loop | All tooltips in the same container should share the same `containerId` |
215
+
216
+ ---
217
+
218
+ ## Component Conventions
219
+
220
+ > **CSS encoding**: internal CSS classes use short encoded names (e.g. `too01`, `too06`) per project convention.
221
+
222
+ > **Unique IDs**: uses `createUniqueId()` from `solid-js` — never `Math.random()` or `Date.now()`.