aidenybai / aidenybai/react-scan
0.5.7 overlay toggle switch (and other translate/rotate utilities) render broken: Tailwind v4 @property rules unregistered inside shadow DOM
- Langage dominant
- TypeScript
- Étoiles
- 21.8k
- Forks
- 390
- Merge moyen
- 23 min
- PR mergées (30 j)
- 1
Description
## Symptom
In `react-scan@0.5.7`, overlay UI utilities that rely on Tailwind v4's `translate` / `rotate` / `scale` shorthand render incorrectly. The most visible symptom is the outline-render toggle switch: in the OFF state the white thumb pops out of the track and hangs below it. The same class of bug affects the resize handles, slider thumb, and expand arrow — anywhere the overlay CSS uses `@apply -translate-*` / `translate-*`.
Reproduction on Chrome 149 with a Tailwind v4 host (also reproduces with a non-Tailwind host, verified against a Panda CSS project — the host stylesheet is irrelevant since the overlay is inside a shadow DOM).
Downgrading to `react-scan@0.5.6` restores correct rendering (v0.5.6 is on Tailwind v3, which uses preflight-seeded `--tw-translate-*` rather than `@property`).
## Screenshots
## Root cause
React Scan mounts its overlay UI in a shadow DOM and injects the bundled Tailwind stylesheet as a `` element inside that shadow root ([`packages/scan/src/core/index.ts`](https://github.com/aidenybai/react-scan/blob/main/packages/scan/src/core/index.ts#L33-L51)). Tailwind v3 → v4 in 0.5.7 changed how `-translate-y-1/2` etc. compile: instead of the preflight-seeded `--tw-translate-*` variables, v4 emits 62 `@property` rules to declare the `initial-value` (0).
Chromium does not register `@property` rules declared inside a shadow-DOM stylesheet. The CSSOM parses them into `CSSPropertyRule`s (visible via `stylesheet.cssRules`), but the custom-property registry is empty for that shadow tree. Consequently `--tw-translate-x` has no computed value, and
```css
translate: var(--tw-translate-x) var(--tw-translate-y);
```
collapses to `translate: none`.
Measurement on `.react-scan-toggle > div::before` in the OFF state (react-scan 0.5.7, Chrome 149):
| property | value |
| --- | --- |
| `translate` | `none` |
| `--tw-translate-x` | `""` (empty) |
| `--tw-translate-y` | `calc(calc(1 / 2 * 100%) * -1)` |
For the ON state, the `input:checked + div::before` selector applies `translate-x-full` which explicitly sets `--tw-translate-x: 100%`, so translate resolves — that's why the ON state visually looks OK while OFF is broken.
Document-level `@property` registrations *do* cascade into a shadow tree, verified in a minimal repro on Chrome 149.
Spec: [CSS Properties and Values API L1](https://drafts.css-houdini.org/css-properties-values-api/).
## Proposed fix (branch available)
I have a one-file fix on my fork:
[`hidenari-pixel/react-scan@fix/shadow-dom-property-registration`](https://github.com/hidenari-pixel/react-scan/tree/fix/shadow-dom-property-registration) ([diff](https://github.com/aidenybai/react-scan/compare/main...hidenari-pixel:react-scan:fix/shadow-dom-property-registration))
Approach: in `initRootContainer()`, extract every `@property --…{…}` block from the bundled overlay CSS with a regex before injecting the stylesheet into the shadow root, and mount just those rules under a `<style data-react-scan="property-registrations">` in `document.head`. The remainder still goes into the shadow root as before.
After the fix, the same `::before` in the OFF state resolves to:
| property | value |
| --- | --- |
| `translate` | `0px -50%` |
| `--tw-translate-x` | `0` |
| `--tw-translate-y` | `calc(calc(1 / 2 * 100%) * -1)` |
and 62/62 `@property` rules move from the shadow tree to `document.head`.
- Change is ~14 lines in `packages/scan/src/core/index.ts` plus a changeset entry
- `pnpm --filter react-scan build` succeeds
- `pnpm test:e2e` — 47/47 pass, including the outline toggle instrumentation specs from #459
- Manual verification in `kitchen-sink` on Chrome 149: toggle thumb renders centered in both OFF and ON states
## Note
I tried to open this as a PR but hit "An owner of this repository has limited the ability to open a pull request to users that are collaborators on this repository." Happy to open the PR the moment the interaction limit is lifted, or invited as a collaborator, or feel free to cherry-pick the commit directly:
```
git remote add hidenari-pixel https://github.com/hidenari-pixel/react-scan.git
git fetch hidenari-pixel fix/shadow-dom-property-registration
git cherry-pick 2407c8b
```
Related open work: PR #458 (React port of the toolbar UI) may incidentally sidestep this if it moves off Tailwind v4 utility classes, but it is still open and orthogonal.
Guide de contribution
Ouvrir le guide de contribution
Évaluation
Cette issue n'a pas encore été évaluée.