@celestia-island/hikari 0.55.174 → 0.55.175

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@celestia-island/hikari",
3
- "version": "0.55.174",
3
+ "version": "0.55.175",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Hikari Vue 3 component library — production-grade UI components based on shittim-chest design system",
@@ -15,6 +15,10 @@ import { usePopupManager } from "./usePopupManager";
15
15
  * - escape hatches: empty titles, [data-hk-tooltip-native], elements
16
16
  * inside an HkTooltip wrapper — never engage
17
17
  * - pointerdown hides but stays engaged; scroll/resize and Esc disengage
18
+ * - the popup mounts inside #hk-overlay-root (same home as the component
19
+ * tooltip's teleported popup) — at body level its in-root ordinal z
20
+ * would land under the root's document-space elevation and every
21
+ * overlay-hosted surface (the filter panel popover) clipped it
18
22
  * - idempotent install per document; uninstall tears everything down
19
23
  */
20
24
 
@@ -199,6 +203,13 @@ describe("installHkTooltipBridge", () => {
199
203
  expect(el.getAttribute("title")).toBe("Scrolled");
200
204
  });
201
205
 
206
+ it("mounts the popup inside the overlay root", () => {
207
+ install();
208
+ const root = document.querySelector("#hk-overlay-root");
209
+ expect(root).not.toBeNull();
210
+ expect(bridgePopup()?.parentElement).toBe(root);
211
+ });
212
+
202
213
  it("is idempotent per document and uninstallable", () => {
203
214
  vi.useFakeTimers();
204
215
  install();
@@ -25,9 +25,15 @@
25
25
  // - empty / whitespace-only titles never engage
26
26
  //
27
27
  // The bridge holds one popup-manager handle (kind "tooltip"), so its
28
- // popups share the tooltip z band with component tooltips. Installing
29
- // twice on the same document is idempotent: the second install returns
30
- // the first install's uninstall.
28
+ // popups share the tooltip z band with component tooltips — inside the
29
+ // overlay root, which is where the popup MOUNTS (same home as the
30
+ // HkTooltip component's teleported popup: the in-root ordinal z is
31
+ // meaningless at body level once #hk-overlay-root carries its own
32
+ // document-space elevation). Installing twice on the same document is
33
+ // idempotent: the second install returns the first install's uninstall.
34
+ // Side effect: ensures #hk-overlay-root exists before the install appends
35
+ // the popup (the component tooltip's Teleport target is the same node).
36
+ import { ensureOverlayRoot } from "../overlay/overlayRoot";
31
37
  import { applyTooltipPosition, type TooltipPlacement } from "./tooltipPosition";
32
38
  import { usePopupManager, type PopupHandle } from "./usePopupManager";
33
39
  import { reportHkRuntime, type HkRuntimeHandle } from "./registry";
@@ -206,7 +212,19 @@ export function installHkTooltipBridge(options: HkTooltipBridgeOptions = {}): ()
206
212
  const content = document.createElement("div");
207
213
  content.className = "hk-tooltip-content";
208
214
  popup.appendChild(content);
209
- document.body.appendChild(popup);
215
+ // Mount into the overlay root, NOT <body> (2026-10-16 defect report):
216
+ // the manager's z here is the IN-ROOT ordinal band (tooltip 300, above
217
+ // anchored popups 200) — it only competes inside the root's
218
+ // `isolation: isolate` fence. At body level the same number is a
219
+ // near-bottom document z, far under `#hk-overlay-root`'s own elevation
220
+ // (--hk-z-overlay-root, 90000), so every tooltip the bridge showed over
221
+ // an overlay-hosted surface — the filter panel's operator `title=`s
222
+ // over its popover — painted UNDER the panel and was clipped by it.
223
+ // The component tooltips teleport into the root for exactly this
224
+ // reason; the bridge shares their popup classes AND must share their
225
+ // home. `pointer-events` stays none on both the root and the popup, so
226
+ // the hosting subtree changes nothing about hit-testing.
227
+ ensureOverlayRoot().appendChild(popup);
210
228
 
211
229
  const state: BridgeState = {
212
230
  root: document,
@@ -16,12 +16,19 @@ export const TOOLTIP_GAP_PX = 8;
16
16
  * Build the inline style that pins a `position: fixed` popup to one side
17
17
  * of a trigger rect.
18
18
  *
19
- * The popup teleports to <body> — inside any root CSS zoom subtree —
20
- * while `rect` is already in the root visual space (standardized zoom
19
+ * The popup floats OUTSIDE the page's zoomed subtrees — the HkTooltip
20
+ * component teleports it into #hk-overlay-root and the bridge appends
21
+ * it there too, both mounted under unzoomed <body>, outside every
22
+ * zoomed subtree — while `rect`
23
+ * is already in the root visual space (standardized zoom
21
24
  * reports ancestor zoom applied). The browser scales the tooltip's local
22
25
  * px back up at paint, so the visual rect values must be written divided
23
26
  * by the cumulative zoom or the tooltip drifts zoom× off its trigger
24
- * (chest's root-level manual DPI scale).
27
+ * (chest's root-level manual DPI scale). This contract quietly assumes
28
+ * the overlay root itself never carries a CSS zoom: the anchor math here
29
+ * divides by ancestorZoom(document.body) only, while the clamp pass
30
+ * below divides by ancestorZoom(popup) — the two agree exactly because
31
+ * the root sits unzoomed between them.
25
32
  *
26
33
  * `width: max-content` is the position-independence contract (same rule
27
34
  * as .hk-popover-panel): a fixed element otherwise shrink-to-fits against