Site Editor: Fix unsupported theme flash on direct URL navigation#76465
Site Editor: Fix unsupported theme flash on direct URL navigation#76465
Conversation
|
Size Change: +47 B (0%) Total Size: 7.66 MB
ℹ️ View Unchanged
|
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
When navigating directly to a Site Editor URL (e.g. a template edit screen), the sidebar briefly flashes "The theme you are currently using does not support this screen" before the correct content appears. This happens because route area resolvers check `siteData.currentTheme?.is_block_theme` to decide what to render, but `currentTheme` is fetched asynchronously and is initially null. The optional chaining evaluates to undefined (falsy), so the resolvers fall through to `<SidebarNavigationScreenUnsupported />`. Add an `isThemeDataLoaded` helper that distinguishes "theme data not yet loaded" from "classic theme." Area resolvers that render the unsupported screen now return null while theme data is pending, rendering nothing until the theme type is actually known. Co-authored-by: Claude <[email protected]>
dce231f to
85c7bab
Compare
There was a problem hiding this comment.
Pull request overview
Fixes a transient “unsupported theme” warning that appears when navigating directly to Site Editor URLs on block themes, caused by currentTheme being null while the theme is still resolving via REST.
Changes:
- Added
isThemeDataLoaded( siteData )helper to detect whensiteData.currentThemehas been populated. - Updated multiple route area resolvers to return early while theme data is pending, avoiding rendering
<SidebarNavigationScreenUnsupported />during the loading window. - Applied the early-return pattern across templates/pages/navigation/home/stylebook routes.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/edit-site/src/components/site-editor-routes/utils.js | Adds isThemeDataLoaded() helper used by route resolvers. |
| packages/edit-site/src/components/site-editor-routes/templates.js | Prevents unsupported-screen flash in templates sidebar/mobile while theme data is pending. |
| packages/edit-site/src/components/site-editor-routes/template-item.js | Prevents unsupported-screen flash for individual template route areas while theme data is pending. |
| packages/edit-site/src/components/site-editor-routes/stylebook.js | Avoids rendering unsupported sidebar until theme data is known. |
| packages/edit-site/src/components/site-editor-routes/pages.js | Prevents unsupported-screen flash in pages sidebar/mobile while theme data is pending. |
| packages/edit-site/src/components/site-editor-routes/page-item.js | Prevents unsupported-screen flash for individual page route areas while theme data is pending. |
| packages/edit-site/src/components/site-editor-routes/navigation.js | Prevents unsupported-screen flash in navigation sidebar/mobile while theme data is pending. |
| packages/edit-site/src/components/site-editor-routes/navigation-item.js | Prevents unsupported-screen flash for individual navigation item route areas while theme data is pending. |
| packages/edit-site/src/components/site-editor-routes/home.js | Avoids rendering unsupported screen on home route until theme data is known. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const isBlockTheme = siteData.currentTheme?.is_block_theme; | ||
| return isBlockTheme || | ||
| if ( ! isThemeDataLoaded( siteData ) ) { | ||
| return null; |
There was a problem hiding this comment.
In mobile viewports, returning null here makes areas.mobile falsy, so the layout treats the route as having no mobile area and falls back to rendering the sidebar/content/preview layout instead (see edit-site/src/components/layout/index.js checks like isMobileViewport && areas.mobile). If the intent is “render nothing while theme is loading” but still keep the mobile area active, return an empty React node (e.g. an empty fragment) instead of null (or adjust the layout checks to differentiate undefined vs null).
| return null; | |
| return <></>; |
| const isBlockTheme = siteData.currentTheme?.is_block_theme; | ||
| return isBlockTheme ? ( | ||
| if ( ! isThemeDataLoaded( siteData ) ) { | ||
| return null; |
There was a problem hiding this comment.
Returning null here makes areas.mobile falsy, which the Site Editor layout interprets as “no mobile area provided” and it will render the non-mobile sidebar layout on mobile viewports until theme data arrives. To keep the route in its mobile/fullscreen mode while still rendering nothing during loading, return an empty React node (e.g. an empty fragment) rather than null.
| return null; | |
| return <></>; |
| const isBlockTheme = siteData.currentTheme?.is_block_theme; | ||
| return isBlockTheme ? ( | ||
| if ( ! isThemeDataLoaded( siteData ) ) { | ||
| return null; |
There was a problem hiding this comment.
Returning null from the mobile area makes areas.mobile falsy, so the layout may fall back to rendering the sidebar layout on mobile viewports until theme data is available. If you want the mobile area to be considered “present” while rendering nothing, return an empty React node (e.g. an empty fragment) instead of null.
| return null; | |
| return <></>; |
| const isBlockTheme = siteData.currentTheme?.is_block_theme; | ||
| return isBlockTheme ? ( | ||
| if ( ! isThemeDataLoaded( siteData ) ) { | ||
| return null; |
There was a problem hiding this comment.
Returning null here makes areas.preview falsy, so the layout skips rendering the preview canvas container entirely until theme data loads, then mounts it later. If you want to keep the preview area reserved (avoiding layout shifts) while still rendering nothing during loading, return an empty React node (e.g. an empty fragment) instead of null.
| return null; | |
| return <></>; |
| const isBlockTheme = siteData.currentTheme?.is_block_theme; | ||
| return isBlockTheme ? ( | ||
| if ( ! isThemeDataLoaded( siteData ) ) { | ||
| return null; |
There was a problem hiding this comment.
Because the layout renders the preview canvas only when areas.preview is truthy (areas.preview && ...), returning null here suppresses the entire preview container while theme data is loading, then mounts it later. If you want to avoid layout shifts while still rendering nothing during loading, return an empty React node (e.g. an empty fragment) instead of null so the preview area is still considered present.
| return null; | |
| return <></>; |
| const isBlockTheme = siteData.currentTheme?.is_block_theme; | ||
| return isBlockTheme ? ( | ||
| if ( ! isThemeDataLoaded( siteData ) ) { | ||
| return null; |
There was a problem hiding this comment.
Returning null from the mobile area makes areas.mobile falsy, which can cause the layout to temporarily treat this route as not having a mobile area and render the sidebar layout on mobile viewports instead. If the goal is to render nothing while loading but keep the mobile area active, return an empty React node (e.g. an empty fragment) rather than null.
| return null; | |
| return <></>; |
| const isBlockTheme = siteData.currentTheme?.is_block_theme; | ||
| return isBlockTheme ? ( | ||
| if ( ! isThemeDataLoaded( siteData ) ) { | ||
| return null; |
There was a problem hiding this comment.
The preview canvas is only rendered when areas.preview is truthy in the Site Editor layout. Returning null here removes the preview container while theme data is loading, then adds it later, which can cause a noticeable layout shift. Consider returning an empty React node (e.g. empty fragment) during loading instead of null so the preview area remains “present” while still rendering nothing.
| return null; | |
| return <></>; |
| const isBlockTheme = siteData.currentTheme?.is_block_theme; | ||
| return isBlockTheme ? ( | ||
| if ( ! isThemeDataLoaded( siteData ) ) { | ||
| return null; |
There was a problem hiding this comment.
Returning null from the mobile area makes areas.mobile falsy, which the layout interprets as “no mobile area”, potentially rendering the non-mobile sidebar layout on mobile viewports during the loading window. To keep the route in mobile mode while rendering nothing, return an empty React node (e.g. an empty fragment) instead of null.
| return null; | |
| return <></>; |
| const isBlockTheme = siteData.currentTheme?.is_block_theme; | ||
| if ( ! isBlockTheme ) { | ||
| if ( ! isThemeDataLoaded( siteData ) ) { | ||
| return null; |
There was a problem hiding this comment.
Returning null here makes areas.mobile falsy; on mobile viewports this can cause the layout to fall back to rendering the sidebar/content/preview layout (because it checks areas.mobile truthiness) until theme data is available. If you want a blank mobile screen without switching layouts, return an empty React node (e.g. an empty fragment) instead of null.
| return null; | |
| return <></>; |
| const isBlockTheme = siteData.currentTheme?.is_block_theme; | ||
| return isBlockTheme ? ( | ||
| if ( ! isThemeDataLoaded( siteData ) ) { | ||
| return null; |
There was a problem hiding this comment.
Returning null from the mobile area makes areas.mobile falsy, so on mobile viewports the layout may temporarily render the non-mobile sidebar layout (it uses areas.mobile truthiness to decide) until theme data arrives. If you want to render nothing while still keeping the mobile area active, return an empty React node (e.g. an empty fragment) rather than null.
| return null; | |
| return <></>; |
|
Flaky tests detected in 85c7bab. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/23353913395
|
|
The copilot reviews all boil down to the same thing: returning null makes areas.mobile / areas.preview falsy, which causes the layout to treat the route as not having that area at all — potentially causing layout shifts or briefly showing the wrong layout mode on mobile. It sounds technically true, but when I test with a mobile viewport I don't see layout shifts or incorrect modes. |
mikachan
left a comment
There was a problem hiding this comment.
This is looking good, thanks @dsas!
There are still a few cases of optional chaining with currentTheme?.is_block_theme. Do you think we should apply your fix to all cases? These are the ones I can see:
- line 25 in home.js
- line 43 in navigation.js
- lines 69 and 73 of pages.js
- lines 47 and 60 of templates.js
The copilot reviews all boil down to the same thing: returning null makes areas.mobile / areas.preview falsy, which causes the layout to treat the route as not having that area at all — potentially causing layout shifts or briefly showing the wrong layout mode on mobile.
It sounds technically true, but when I test with a mobile viewport I don't see layout shifts or incorrect modes.
I can't see a layout shift in a mobile viewport either, although it sounds like it would be possible on a very slow connection. I'd favour applying this only to the mobile areas, and leave the preview and sidebar areas as they are.
|
Thanks for taking a look @mikachan
I don't think so because it doesn't makes any difference. We currently return undefined for those cases, and with the fix, we would continue to return a falsy-value. If you'd prefer I make the changes for consistency, then I'm happy to do so though.
Ok, that makes sense, I'll do that. |
… loads When areas.mobile is falsy, the layout briefly renders the desktop sidebar instead of the mobile layout. Return an empty fragment rather than null so the mobile layout container stays mounted during loading. Co-authored-by: Claude <[email protected]>
What?
Fix a brief flash of "The theme you are currently using does not support this screen" when navigating directly to a Site Editor URL with a block theme.
This closes issue #76462
Why?
When loading a Site Editor URL directly (e.g.
?p=%2Fwp_template%2F...&canvas=edit), the route area resolvers checksiteData.currentTheme?.is_block_themeto decide whether to render the actual content or<SidebarNavigationScreenUnsupported />. However,currentThemeis fetched asynchronously via the REST API and is initiallynull. The optional chaining evaluates toundefined(falsy), so the resolvers briefly render the unsupported theme warning before the theme data arrives and the correct UI takes over.How?
Add an
isThemeDataLoaded()helper toutils.jsthat checks whethercurrentThemehas been populated yet. Area resolvers that render<SidebarNavigationScreenUnsupported />now returnnullearly when theme data is still pending, rendering nothing in those slots until the theme type is actually known. Areas that already returnedundefinedfor non-block themes (likepreviewandcontent) are unaffected since they were already safe.This is an AI-assisted contribution (Claude). All code has been reviewed and tested by the author.
Testing Instructions
wp-envwith a block theme active (e.g. Twenty Twenty-Five)./wp-admin/site-editor.php?p=%2Fwp_template%2Fpub%2Ftwentytwentyfive%2F%2Findex&canvas=edit/wp-admin/site-editor.php. Verify the unsupported theme warning still appears and persists as expected.Testing Instructions for Keyboard
No UI interaction changes — this only affects the timing of what renders in existing layout areas.