fix(design-system): glass-panel rules now actually apply backdrop-filter (#98)

Production check after #97 promoted: the .glass-panel and .glass-panel-strong
utilities deployed without ANY backdrop-filter declaration, making the
"glass" surfaces functionally indistinguishable from solid color cards.

Root cause (two compounding Lightning CSS quirks in Next.js 16):

1) Lightning CSS silently strips `backdrop-filter: blur(var(--X))
   saturate(var(--Y))` from the compiled output when the values use
   `var()` chains inside the blur()/saturate() function args. Tailwind's
   own .backdrop-blur-* utilities survive because they wrap the *entire*
   `blur(...)` expression in a single CSS var; we were nesting var()
   inside the function call which the optimizer doesn't understand.
   Same root cause emptied .mobile-nav-backdrop in production earlier.

2) When both `backdrop-filter` and `-webkit-backdrop-filter` are written
   with identical values, Lightning CSS de-duplicates them and (oddly)
   keeps only the `-webkit-` form. Modern Chrome/Edge/Firefox ignore the
   webkit prefix, so the blur never applies.

Fix:
- Use LITERAL values: `blur(12px) saturate(180%)` instead of `blur(var(...))
  saturate(var(...))`. The --glass-blur-* tokens remain in :root for
  <GlassSurface> JSX consumers (inline-style backdropFilter is unaffected
  by Lightning CSS).
- Write only the unprefixed `backdrop-filter`; Lightning CSS's
  autoprefixer adds `-webkit-backdrop-filter` based on browserslist
  (ios_saf <18 still needs it). Verified by `npm run build`:

    .glass-panel {
      ...
      -webkit-backdrop-filter: blur(12px) saturate(180%);
      backdrop-filter: blur(12px) saturate(180%);
      ...
    }

Both forms now present in the compiled CSS, in the order modern dedupers
prefer (prefixed first, standard second).

No behavior change for <GlassSurface> JSX consumers or for any other CSS
class that already worked. Just gets the two utility classes from #97
actually doing their job.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
varutasu 2026-06-03 21:38:38 -05:00 committed by GitHub
parent 19050cf1bc
commit 40e00e57c6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -439,18 +439,29 @@ body {
from Tailwind (the class itself doesn't set border-radius
because consumers vary between rounded-xl and rounded-2xl).
============================================================ */
/* IMPORTANT backdrop-filter quirks with Next.js 16's Lightning CSS:
1) `backdrop-filter: blur(var(--X)) saturate(var(--Y))` is silently
stripped from the compiled CSS (same root cause that emptied
`.mobile-nav-backdrop` in production). Use LITERAL values.
2) Writing both `backdrop-filter` and `-webkit-backdrop-filter` with
identical values triggers Lightning CSS's de-dup; it keeps only the
`-webkit-` form which Chrome/Edge/Firefox ignore. Write only the
unprefixed `backdrop-filter` and let Lightning CSS's autoprefixer
add the vendor prefix per browserslist (it does for ios_saf <18).
If the blur radii ever need to change, change them here AND in the
matching --glass-blur-* tokens (kept for `<GlassSurface>` JSX consumers
which set `backdropFilter` via inline style those are unaffected by
the Lightning CSS optimizer). */
.glass-panel {
background-color: var(--glass-surface-mid);
backdrop-filter: blur(var(--glass-blur-mid)) saturate(var(--glass-saturate));
-webkit-backdrop-filter: blur(var(--glass-blur-mid)) saturate(var(--glass-saturate));
backdrop-filter: blur(12px) saturate(180%);
border: 1px solid var(--rim-light-outer);
box-shadow: var(--elevation-ambient), inset 0 1px 0 var(--rim-light-inner);
}
.glass-panel-strong {
background-color: var(--glass-surface-high);
backdrop-filter: blur(var(--glass-blur-high)) saturate(var(--glass-saturate));
-webkit-backdrop-filter: blur(var(--glass-blur-high)) saturate(var(--glass-saturate));
backdrop-filter: blur(20px) saturate(180%);
border: 1px solid var(--rim-light-outer);
box-shadow: var(--elevation-pronounced), inset 0 1px 0 var(--rim-light-inner);
}