|
12 | 12 | align?: Align;
|
13 | 13 | distance?: string;
|
14 | 14 | hidden?: boolean;
|
| 15 | + arrow?: boolean; |
| 16 | + manual?: boolean; // Always render tooltip, even when not hovered |
15 | 17 | anchor?: HTMLElement;
|
16 | 18 | };
|
17 | 19 |
|
|
23 | 25 | align = "center",
|
24 | 26 | distance = "0.5rem",
|
25 | 27 | hidden = false,
|
| 28 | + manual = false, |
| 29 | + arrow = true, |
26 | 30 | anchor,
|
27 | 31 | children,
|
28 | 32 | class: className,
|
|
31 | 35 |
|
32 | 36 | let wrapperRef = $state<HTMLElement>();
|
33 | 37 | let tooltipRef = $state<HTMLElement>();
|
34 |
| - let isTooltipVisible = $state(false); |
| 38 | + let isTooltipVisible = $state(manual ? !hidden : false); |
35 | 39 |
|
36 | 40 | const anchorRef = $derived(
|
37 | 41 | anchor ??
|
|
94 | 98 | tooltipRef?.hidePopover();
|
95 | 99 | }
|
96 | 100 | });
|
| 101 | +
|
| 102 | + $effect(() => { |
| 103 | + if (manual) { |
| 104 | + isTooltipVisible = !hidden; |
| 105 | + } |
| 106 | + }); |
97 | 107 | </script>
|
98 | 108 |
|
99 |
| -{#if hidden} |
| 109 | +{#if !manual && hidden} |
100 | 110 | {@render children?.()}
|
101 | 111 | {:else}
|
102 | 112 | <!-- Wrapper used for event handlers and (optionally) anchoring -->
|
103 | 113 | <!-- svelte-ignore a11y_no_static_element_interactions -->
|
104 | 114 | <div
|
105 | 115 | bind:this={wrapperRef}
|
106 |
| - onmouseenter={() => (isTooltipVisible = true)} |
107 |
| - onmouseleave={() => (isTooltipVisible = false)} |
108 |
| - onfocusin={() => (isTooltipVisible = true)} |
109 |
| - onfocusout={() => (isTooltipVisible = false)} |
110 |
| - ontouchend={() => (isTooltipVisible = !isTooltipVisible)} |
| 116 | + onmouseenter={() => !manual && (isTooltipVisible = true)} |
| 117 | + onmouseleave={() => !manual && (isTooltipVisible = false)} |
| 118 | + onfocusin={() => !manual && (isTooltipVisible = true)} |
| 119 | + onfocusout={() => !manual && (isTooltipVisible = false)} |
| 120 | + ontouchend={() => !manual && (isTooltipVisible = !isTooltipVisible)} |
111 | 121 | class="contents"
|
112 | 122 | aria-describedby={id}
|
113 | 123 | >
|
|
161 | 171 | </span>
|
162 | 172 | {/if}
|
163 | 173 | <!-- Tooltip arrow -->
|
164 |
| - <div |
165 |
| - class={[ |
166 |
| - "absolute size-0", |
167 |
| - { |
168 |
| - up: { |
169 |
| - start: "bottom-0 left-7", |
170 |
| - center: "bottom-0 left-[50%]", |
171 |
| - end: "right-7 bottom-0", |
172 |
| - }[align], |
173 |
| - right: { |
174 |
| - start: "top-7 left-0", |
175 |
| - center: "top-[50%] left-0", |
176 |
| - end: "bottom-7 left-0", |
177 |
| - }[align], |
178 |
| - down: { |
179 |
| - start: "top-0 left-7", |
180 |
| - center: "top-0 left-[50%]", |
181 |
| - end: "top-0 right-7", |
182 |
| - }[align], |
183 |
| - left: { |
184 |
| - start: "top-7 right-0", |
185 |
| - center: "top-[50%] right-0", |
186 |
| - end: "right-0 bottom-7", |
187 |
| - }[align], |
188 |
| - }[direction], |
189 |
| - ]} |
190 |
| - > |
| 174 | + {#if arrow} |
191 | 175 | <div
|
192 | 176 | class={[
|
193 |
| - "bg-fg-primary size-2 origin-center -translate-1 rotate-45", |
| 177 | + "absolute size-0", |
194 | 178 | {
|
195 |
| - up: "rounded-br-xs", |
196 |
| - right: "rounded-bl-xs", |
197 |
| - down: "rounded-tl-xs", |
198 |
| - left: "rounded-tr-xs", |
| 179 | + up: { |
| 180 | + start: "bottom-0 left-7", |
| 181 | + center: "bottom-0 left-[50%]", |
| 182 | + end: "right-7 bottom-0", |
| 183 | + }[align], |
| 184 | + right: { |
| 185 | + start: "top-7 left-0", |
| 186 | + center: "top-[50%] left-0", |
| 187 | + end: "bottom-7 left-0", |
| 188 | + }[align], |
| 189 | + down: { |
| 190 | + start: "top-0 left-7", |
| 191 | + center: "top-0 left-[50%]", |
| 192 | + end: "top-0 right-7", |
| 193 | + }[align], |
| 194 | + left: { |
| 195 | + start: "top-7 right-0", |
| 196 | + center: "top-[50%] right-0", |
| 197 | + end: "right-0 bottom-7", |
| 198 | + }[align], |
199 | 199 | }[direction],
|
200 | 200 | ]}
|
201 |
| - ></div> |
202 |
| - </div> |
| 201 | + > |
| 202 | + <div |
| 203 | + class={[ |
| 204 | + "bg-fg-primary size-2 origin-center -translate-1 rotate-45", |
| 205 | + { |
| 206 | + up: "rounded-br-xs", |
| 207 | + right: "rounded-bl-xs", |
| 208 | + down: "rounded-tl-xs", |
| 209 | + left: "rounded-tr-xs", |
| 210 | + }[direction], |
| 211 | + ]} |
| 212 | + ></div> |
| 213 | + </div> |
| 214 | + {/if} |
203 | 215 | </div>
|
204 | 216 | </div>
|
205 | 217 | {/if}
|
|
0 commit comments