Files
1b10c605d7 fix(replay): preserve <style> textContent on var-shorthand CSS (#3542)
* fix(replay): preserve <style> textContent on var-shorthand CSS

When a CSS rule combines a shorthand with var() and a longhand override,
e.g.

    .card { padding: var(--p); padding-bottom: var(--pb); }

browsers store the shorthand's longhands with empty token lists per the
CSS Custom Properties spec, and CSSStyleRule.cssText re-emits them as

    padding-top: ; padding-right: ; padding-left: ; padding-bottom: var(--pb);

The previous serializeTextNode path replaced the original <style> text
with that corrupted output, silently stripping layout rules on replay.
Affected users of any CSS-in-JS framework that combines var() with
shorthands -- Chakra UI v3, Panda CSS, Emotion -- where the form card
padding, flex centering, grid track sizing etc. would vanish in playback
while colors and other single-property declarations stayed intact.

Detect the empty-longhand pattern in stringifyStylesheet's output and
keep the original textContent in that case. Custom properties
(--foo: ;) are intentionally excluded since they may legitimately be
empty.

See rrweb-io/rrweb#1626 / #1567 for the upstream issue tracking.

* chore: correct upstream issue reference (rrweb-io/rrweb#1667)

* fix(replay): also detect vendor-prefixed empty longhands

* test(replay): real-browser playwright coverage for var-shorthand <style> fix

Adds a Chromium + Firefox Playwright spec that exercises the
stringifyStylesheet -> rule.cssText round-trip in a real browser, which
jsdom cannot reproduce. The spec covers:

  1. @layer block + atomic utilities + nested @media round-trip cleanly
     (regression guard for grouping at-rules).
  2. shorthand-with-var() plus a longhand override (the customer's
     reported pattern at app.sonia.so/login) does not surface empty
     placeholder longhands in the captured <style> textContent.
  3. <style> with seeded text plus a runtime sheet.insertRule() addition
     captures both rules when the round-trip is clean (regression check
     for the corruption-detection branch — must not over-fire).

Also adds two playgrounds under packages/browser/playground/:

  - css-layers/  Synthetic fixture for the playwright spec above.
    Drives all three test cases via document.styleSheets API and
    textContent.
  - chakra-emotion/  Vite + React + Chakra UI v3 + @emotion/react +
    posthog-js (linked) playground that mirrors the customer's stack.
    Useful as a debugging artifact for future CSS-in-JS replay issues;
    not currently driven by automated tests.

Generated-By: PostHog Code
Task-Id: 443a699a-1a4a-4ba0-bac0-c34973269261

* chore(release): include posthog-js in changeset

* chore(release): drop @posthog/rrweb-snapshot from changeset

* chore(release): re-add @posthog/rrweb-snapshot to changeset

---------

Co-authored-by: pauldambra <[email protected]>
2026-05-07 21:06:20 +01:00
..