Skip to content

[grid-lanes M5] Frontend toolchain & Lynx for Web (lynx-family/lynx-stack) #8621

Description

@Huxpro

Part of the display: grid-lanes roadmap (umbrella: #8615). Depends on M1 (#8617) (property IDs + @lynx-js/tasm / @lynx-js/css-defines / @lynx-js/types releases). Independent of M2–M4 — can proceed in parallel. Blocks M6 and the harness's oracle Mode B.

The work items below land in lynx-family/lynx-stack (plus docs in lynx-family/lynx-website); this issue tracks them from the engine side.

Context

Lynx for Web renders styles roughly 1:1 onto real DOM CSS, so display: grid-lanes should ultimately be browser-native on Web. But the pass-through has three traps, confirmed by inspection of lynx-stack (@lynx-js/web-core is now hybrid Rust/TS; the old web-constants / web-style-transformer packages were merged into it):

  1. Numeric property table is positional. CSSPropertyEnum in packages/web-platform/web-core/src/template/template_sections/style_info/css_property.rs mirrors the engine's numeric IDs (Display = 24, … OffsetDistance = 215); from_id silently drops anything beyond the last known ID. New engine properties (flow-tolerance = 237 per M1) must be appended at the exact engine indices in both STYLE_PROPERTY_MAP and the enum, or numeric-keyed inline styles vanish with no diagnostic.
  2. --lynx-display is a closed registered grammar. @property --lynx-display { syntax: "linear | flex" } — an unknown keyword is silently discarded and falls back to initial-value: linear, so a grid-lanes container would behave as a linear box. Declared in three places (web-core/css/index.css, web-elements/src/elements/common-css/linear.css, seeded in in_shadow.css / playwright-fixtures common.css).
  3. The linear cascade leaks. display: grid today has no REPLACE_RULE entry in style_transformer/rules.rs, so linear.css's justify-content/flex-* variables still apply to grid containers. Grid-lanes must get an explicit rule (and this is a good moment to fix display: grid the same way).

Deliverables (in lynx-stack unless noted)

Toolchain

  • Bump @lynx-js/tasm in packages/webpack/template-webpack-plugin (the encoder is the only gate — @lynx-js/css-serializer is property-agnostic and passes unknown declarations through).
  • Bump @lynx-js/types across all pinned packages (~15 package.jsons, all pinned to one exact version) once M1 publishes CSSProperties with 'grid-lanes' + flowTolerance.
  • Mirror in the REPL's forked parser (packages/repl/src/bundler/css-processor.ts) if it validates properties.

@lynx-js/web-core (Rust)

  • Append flow-tolerance (and any M1 additions) to STYLE_PROPERTY_MAP + CSSPropertyEnum at engine indices; update the from_id bound; unit tests mirroring test_css_property_from_id.
  • REPLACE_RULE entry for display: grid-lanes in style_transformer/rules.rs (mirror the linear/flex shape): set --lynx-display-toggle/--lynx-display, emit native display: grid-lanes. Decide whether to add the missing display: grid entry in the same PR (there's an existing test asserting its absence — flip deliberately).
  • Transformer round-trip tests (inline_style.rs); rebuild wasm binaries (pnpm build:wasm), commit regenerated .d.ts.

@lynx-js/web-elements (CSS)

  • Widen @property --lynx-display { syntax: "linear | flex | grid-lanes" } in all three declaration sites; add --lynx-display-grid-lanes toggle var; audit the @container style(--lynx-display: …) blocks so grid-lanes children don't inherit linear's flex shorthand behavior.
  • Browser fallback strategy: native display: grid-lanes behind @supports (display: grid-lanes); else the legacy Chromium display: masonry syntax where present; else a documented fallback (the x-list[list-type="waterfall"] absolute-positioning approach and LinearContainer/ compat are in-repo precedents). Define the support matrix explicitly (Safari 26.4+ native; Chromium flag; everything else → fallback) and what "fallback" renders (recommendation: plain display: grid degradation per spec §9, not a JS polyfill, for v1).
  • Playwright E2E fixtures (web-core-e2e/tests/reactlynx/basic-grid-lanes-*/) + snapshots; encode/decode test for the new numeric ID (element-apis.spec.ts precedent).

Ecosystem

  • Tailwind preset: .grid-lanes display utility + flow-tolerance plugin (packages/tailwind-preset — display.ts, plugin registry, theme scales, tests).
  • Changesets for all touched packages.
  • Docs (in lynx-family/lynx-website): display: grid-lanes + flow-tolerance property pages, guide with fallback guidance, compat table fed from css_defines compat_data (web_lynx flags set honestly).
  • Oracle Mode B for M0's harness: with the above landed, the same .lynx.bundle runs through Lynx for Web in headless Chromium/WebKit — wire it into the differential harness as the product-parity oracle mode.

Acceptance criteria

  1. A ReactLynx page using display: grid-lanes + flow-tolerance builds with zero "Unsupported property" diagnostics and renders via browser-native grid-lanes in Safari 26.4 / flagged Chromium.
  2. In non-supporting browsers, the documented fallback renders (no linear-cascade leakage, no silently-linear containers).
  3. Ring 1 Mode B green on the M2-level corpus (same bundle, native vs web).
  4. Tailwind utilities compile; types autocomplete 'grid-lanes' / flowTolerance; E2E snapshots green.

References

  • lynx-stack: packages/web-platform/web-core/src/style_transformer/rules.rs, .../style_info/css_property.rs, packages/web-platform/web-elements/src/elements/common-css/linear.css, packages/tools/css-serializer/src/parse.ts, packages/webpack/template-webpack-plugin/src/cssDiagnostics.ts
  • Waterfall precedent on web: packages/web-platform/web-elements/src/elements/XList/x-list.css (list-type="waterfall")
  • Spec degradation guidance: §9

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions