From 17086c9eff0d4c51c069c7e222c549ab9888fcec Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Tue, 14 Oct 2025 13:31:22 -0400 Subject: [PATCH] Refactor floating panel and metrics styling --- css/tailwind.source.css | 12 ++ docs/design-system.md | 20 ++ js/designSystem/dynamicStyles.js | 276 +++++++++++++++++++++++++ js/designSystem/metrics.js | 83 ++++++-- js/ui/utils/floatingPanelStyles.js | 52 ++++- scripts/check-inline-styles.mjs | 5 +- tests/design-system-metrics.test.mjs | 61 ++++++ tests/position-floating-panel.test.mjs | 34 +++ 8 files changed, 507 insertions(+), 36 deletions(-) create mode 100644 js/designSystem/dynamicStyles.js create mode 100644 tests/design-system-metrics.test.mjs diff --git a/css/tailwind.source.css b/css/tailwind.source.css index ea6236cb..88849605 100644 --- a/css/tailwind.source.css +++ b/css/tailwind.source.css @@ -121,6 +121,18 @@ @apply flex items-center justify-start py-md; } + .ds-metric-probe { + position: absolute; + top: 0; + left: 0; + visibility: hidden; + pointer-events: none; + contain: layout size style; + inline-size: 0; + block-size: var(--ds-metric-probe-length, 0); + overflow: hidden; + } + .ds-header__logo { @apply h-24 w-auto max-w-none; } diff --git a/docs/design-system.md b/docs/design-system.md index 2c45d344..a4806976 100644 --- a/docs/design-system.md +++ b/docs/design-system.md @@ -12,6 +12,26 @@ The new design system ships behind the `FEATURE_DESIGN_SYSTEM` runtime flag defi - **Runtime toggle:** Set `window.__BITVID_RUNTIME_FLAGS__.FEATURE_DESIGN_SYSTEM = false` (or call `setFeatureDesignSystemEnabled(false)`) to temporarily fall back to the legacy primitives. The entrypoint automatically updates every `[data-ds]` container to `data-ds="new"` and notifies controllers. - **DOM contract:** Templates and partials must include `data-ds` on their root elements. Controllers should rely on the `designSystem` context (see `js/designSystem.js`) before attaching classes or behaviors that only exist in the new system. +## Dynamic runtime styling + +Inline styles are blocked in production builds, so runtime components that need bespoke coordinates or measurements must route their overrides through `js/designSystem/dynamicStyles.js`. + +- `registerScope(id, selectors)` creates (or reuses) a constructable stylesheet when supported, allocates a unique identifier, and injects empty rules scoped to `[data-ds-style-id=""]`. Callers attach the attribute to any element that should inherit those rules. +- `setVariables(id, tokens)` updates CSS custom properties on the registered scope. Pass CSS variable names (`"--floating-fallback-top"`) and string or number values—`setVariables` handles serialization and removes entries when they resolve to empty strings. +- `releaseScope(id)` removes the generated rules and frees the identifier. Always invoke it from component teardown paths to avoid leaking rules between renders. + +The floating panel utility and design-system metrics both lean on this helper: + +- `createFloatingPanelStyles` assigns each popover a unique scope and publishes fallback coordinates through CSS variables instead of mutating `.style`. Positioning logic reads and writes the same API, and teardown releases the scope before removing dataset attributes. +- `readDesignTokenAsPixels` measures non-`px`/`rem` tokens with an offscreen probe that ships in core CSS (`.ds-metric-probe`). The probe is registered through the helper so dynamic lengths are fed into `--ds-metric-probe-length` without touching inline styles. + +When introducing a new runtime feature that requires dynamic styling: + +1. Register a dedicated scope during setup and attach the returned attribute to the relevant DOM node. +2. Update custom properties with `setVariables` instead of touching `.style` or appending `