Interactivity API: Preserve client-injected styles via data-wp-router-managed - #81452
Draft
DAreRodz wants to merge 2 commits into
Draft
Interactivity API: Preserve client-injected styles via data-wp-router-managed#81452DAreRodz wants to merge 2 commits into
DAreRodz wants to merge 2 commits into
Conversation
|
Size Change: +128 B (0%) Total Size: 7.71 MB 📦 View Changed
|
|
Flaky tests detected in 28f82b5. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/31522779853 should render an autosave that is absent from the revisions collection in
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What?
See #76031.
Make the Interactivity API router honor the
data-wp-router-managedattribute during client-side navigation. Style assets that lack the attribute — on pages that otherwise use it — were injected by client scripts and are left untouched when navigating: never disabled, never re-enabled.This is the client-side counterpart of the server experiment in WordPress/wordpress-develop#12963, which adds an empty
data-wp-router-managedattribute to every<style>and<link rel="stylesheet">element in the generated HTML when the page supports client-side navigation.Why?
The router currently disables every style element not present in the incoming page, including elements it didn't render: styles injected at runtime by consent managers, theme/dark-mode switchers, a11y toolbars, or lazily loaded CSS disappear on the first client-side navigation.
The router can't infer ownership reliably on its own (see the discussion in #76031). With the server marking its own style assets, ownership becomes a synchronous per-element attribute check — no heuristics, no re-fetching, no races.
How?
All changes live in
@wordpress/interactivity-router:initRouterManagedMode()runs once at module evaluation: the router enters "managed mode" if the initial document contains at least one marked style asset, and eagerly claims all marked elements as server-managed. Eager claiming matters because the initial page is prepared only after every region has hydrated (initialVdomPromise), while a navigation only needs the region that triggers it: on a page with many islands, a click on an early-hydrated region with the target page already prefetched can render before the initial page preparation runs.prepareStylePromise()classifies elements stickily: elements from fetched documents are server-managed by definition; elements already live and unmarked (in managed mode) are client-owned and never claimed.applyStyles()in managed mode only disables server-managed elements, and only re-enables elements it disabled itself, so a stylesheet disabled by a client script keeps its state. Without markers, the previous behavior is unchanged — full backward compatibility with WordPress versions that don't emit the attribute.normalizeMedia()ignores the attribute when comparing elements, so navigating between marked and unmarked pages reuses equivalent stylesheets instead of duplicating them.The WordPress version bundled with
wp-envdoesn't emit the attribute yet, so the new e2e test plugin (test/router-styles-managed) simulates it with an output buffer that marks all style assets viaWP_HTML_Tag_Processor, keeping the tests self-contained.Testing Instructions
npm run test:unit -- packages/interactivity-router.npm run wp-env-test start) and build(
npm run build).npm run test:e2e -- test/e2e/specs/interactivity/router-styles-managed.spec.tsfor the new behavior, andnpm run test:e2e -- test/e2e/specs/interactivity/router-styles.spec.tsto confirm unmarked pages keep the current behavior.To test manually:
test/router-styles-managedblock (linking to a second post, see the e2e spec setup).Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Fable 5, Claude Opus 5
Used for: Implementation, tests, adversarial review, and drafting this description.