From d1abffbd2c12aba53c45a0eb8b0255b86163c3ef Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 27 Aug 2026 17:56:12 +0200 Subject: [PATCH] Extensible site editor: Add a revisions entry point to the Styles route The Styles route rendered the shared global styles UI, which already ships the revisions screen, but offered no way to reach it, and its canvas never previewed a selected revision. - Add a Revisions button (with the usual gating on existing revisions) to the route header, mirroring the edit-mode Styles panel. - Sync the open revisions screen into the editor store's styles path so the preview-mode editor canvas swaps to the revisions preview, exactly as it does in edit mode. - When the style book preview is on, resolve the selected revision and pass it to StyleBookPreview so the style book previews that revision's styles. - StylesCanvas: in preview mode, render edge to edge and drop the close button and Escape handler; there the canvas is the whole surface and whatever opened it owns closing it. Co-Authored-By: Claude Fable 5 --- package-lock.json | 1 + packages/editor/CHANGELOG.md | 1 + .../src/components/styles-canvas/index.jsx | 41 +++++++----- .../src/components/styles-canvas/style.scss | 6 ++ routes/styles/canvas.tsx | 48 ++++++++++++++ routes/styles/package.json | 1 + routes/styles/stage.tsx | 62 ++++++++++++++++--- routes/styles/tsconfig.json | 1 + 8 files changed, 137 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index e62d7d72d62c61..af34547baca422 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54571,6 +54571,7 @@ "@wordpress/data": "file:../../packages/data", "@wordpress/editor": "file:../../packages/editor", "@wordpress/element": "file:../../packages/element", + "@wordpress/global-styles-ui": "file:../../packages/global-styles-ui", "@wordpress/html-entities": "file:../../packages/html-entities", "@wordpress/i18n": "file:../../packages/i18n", "@wordpress/icons": "file:../../packages/icons", diff --git a/packages/editor/CHANGELOG.md b/packages/editor/CHANGELOG.md index 4b278af7511ac5..46db2bbef77f06 100644 --- a/packages/editor/CHANGELOG.md +++ b/packages/editor/CHANGELOG.md @@ -9,6 +9,7 @@ ### Bug Fixes - `EditorInterface`: Apply the `showListViewByDefault` preference when the editor enters edit mode, so every editor built on the package honors it — including the extensible site editor, which previously ignored it. The logic moves here from `edit-post` and `edit-site`. +- `StylesCanvas`: In preview mode, render edge to edge without the close button and Escape handler. There the canvas is the whole surface rather than a frame opened over an editing session, and whatever opened it owns closing it. ### Bug Fixes diff --git a/packages/editor/src/components/styles-canvas/index.jsx b/packages/editor/src/components/styles-canvas/index.jsx index 7dd6cee8fdc653..7df03c446cae29 100644 --- a/packages/editor/src/components/styles-canvas/index.jsx +++ b/packages/editor/src/components/styles-canvas/index.jsx @@ -1,3 +1,4 @@ +import clsx from 'clsx'; import { Button } from '@wordpress/components'; import { ESCAPE } from '@wordpress/keycodes'; import { __ } from '@wordpress/i18n'; @@ -35,8 +36,8 @@ export function getStylesCanvasTitle( path, showStylebook ) { * @return {React.JSX.Element} The styles canvas or null if nothing to render. */ export default function StylesCanvas() { - const { stylesPath, showStylebook, showListViewByDefault } = useSelect( - ( select ) => { + const { stylesPath, showStylebook, showListViewByDefault, isPreviewMode } = + useSelect( ( select ) => { const { getStylesPath, getShowStylebook } = unlock( select( editorStore ) ); @@ -50,10 +51,10 @@ export default function StylesCanvas() { stylesPath: getStylesPath(), showStylebook: getShowStylebook(), showListViewByDefault: _showListViewByDefault, + isPreviewMode: + select( editorStore ).getEditorSettings().isPreviewMode, }; - }, - [] - ); + }, [] ); const { resetStylesNavigation, setStylesPath } = unlock( useDispatch( editorStore ) ); @@ -95,23 +96,31 @@ export default function StylesCanvas() { } }; + // In preview mode (e.g. the styles route of the extensible site editor), + // the canvas is not opened over an editing session: whatever opened it + // owns closing it, so the close affordances would only desync that owner. return ( -
+
- { /* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions */ }
-
diff --git a/packages/editor/src/components/styles-canvas/style.scss b/packages/editor/src/components/styles-canvas/style.scss index 16a30cd218f241..092259c5f92853 100644 --- a/packages/editor/src/components/styles-canvas/style.scss +++ b/packages/editor/src/components/styles-canvas/style.scss @@ -15,6 +15,12 @@ width: 100%; height: 100%; } + + // In preview mode the canvas is the whole surface, not a frame opened + // over an editing session, so it renders edge to edge. + &.is-preview-mode { + padding: 0; + } } .editor-styles-canvas__section { diff --git a/routes/styles/canvas.tsx b/routes/styles/canvas.tsx index 4473a9a19c9344..a0765a22338770 100644 --- a/routes/styles/canvas.tsx +++ b/routes/styles/canvas.tsx @@ -4,10 +4,46 @@ import { useEditorAssets, useEditorSettings } from '@wordpress/lazy-editor'; import { Spinner } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; +import { useGlobalStylesRevisions } from '@wordpress/global-styles-ui'; import { unlock } from '@wordpress/routes-lock-unlock'; const { StyleBookPreview } = unlock( editorPrivateApis ); +// Rendered instead of the plain style book while a revision is selected in +// the revisions screen, so the style book previews that revision's styles +// rather than the current ones. A separate component so the revisions (and +// authors) are only fetched once a revision is actually selected. +function RevisionStyleBookPreview( { + revisionId, + section, + onChangeSection, + settings, +}: { + revisionId: string; + section: string; + onChangeSection: ( updatedSection: string ) => void; + settings: any; +} ) { + const { revisions, isLoading } = useGlobalStylesRevisions(); + + if ( isLoading ) { + return null; + } + + const selectedRevision = revisions.find( + ( revision: any ) => String( revision.id ) === revisionId + ); + + return ( + + ); +} + function Canvas() { const { isReady: assetsReady } = useEditorAssets(); const navigate = useNavigate(); @@ -63,6 +99,18 @@ function Canvas() { return ; } + const revisionId = section.match( /^\/revisions\/(.+)$/ )?.[ 1 ]; + if ( revisionId ) { + return ( + + ); + } + return ( { - const { getCurrentTheme, __experimentalGetCurrentGlobalStylesId } = - select( coreStore ) as any; + const { + getCurrentTheme, + getEntityRecord, + __experimentalGetCurrentGlobalStylesId, + } = select( coreStore ) as any; const themeNameRendered = isPreviewingTheme ? getCurrentTheme()?.name?.rendered : undefined; + const _globalStylesId = __experimentalGetCurrentGlobalStylesId(); + const globalStyles = _globalStylesId + ? getEntityRecord( 'root', 'globalStyles', _globalStylesId ) + : undefined; return { - globalStylesId: __experimentalGetCurrentGlobalStylesId(), + globalStylesId: _globalStylesId, + hasRevisions: + !! globalStyles?._links?.[ 'version-history' ]?.[ 0 ] + ?.count, themeName: themeNameRendered ? decodeEntities( themeNameRendered ) : undefined, @@ -49,6 +62,21 @@ function Stage() { } ); const section = ( search.section ?? '/' ) as string; + const areRevisionsOpened = section.startsWith( '/revisions' ); + + // The canvas on this route is the editor in preview mode, and its + // revisions preview is driven by the editor store's styles path rather + // than this route's `section` search param. Keep the store in sync while + // the revisions screen is open so selecting a revision previews it in + // the canvas. + const { setStylesPath } = unlock( useDispatch( editorStore ) ); + useEffect( () => { + if ( ! areRevisionsOpened ) { + return; + } + setStylesPath( section ); + return () => setStylesPath( '/' ); + }, [ areRevisionsOpened, section, setStylesPath ] ); const [ isStyleBookOpened, setIsStyleBookOpened ] = useState( search.preview === 'stylebook' ); @@ -97,6 +125,24 @@ function Stage() { } ); } } /> +