Integrate Resizable Editor with Device Preview and add Responsive editing#75121
Integrate Resizable Editor with Device Preview and add Responsive editing#75121t-hamano wants to merge 33 commits into
Conversation
|
Size Change: +529 B (+0.01%) Total Size: 8.6 MB 📦 View Changed
|
| <PreviewDropdown | ||
| forceIsAutosaveable={ forceIsDirty } | ||
| disabled={ disablePreviewOption } | ||
| disabled={ isStylesCanvasActive } |
There was a problem hiding this comment.
The only exception is StyleBook, where the device preview dropdown is not available, and the canvas is not resizable. I plan to remove this limitation in a follow-up.
|
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. |
Mamaduka
left a comment
There was a problem hiding this comment.
I haven't tested this thoroughly, but I've left some notes based on the initial review.
I think it's an interesting approach. Can you elaborate a bit on why a new global state is needed rather than just using the previous method?
|
@Mamaduka Thanks for the review!
The reason I introduced the new |
|
Yes, but what prevents us from using I'm not saying that either option is better; I'm primarily curious about the technical decisions. |
@tellthemachines Can you try the following steps? I tested it on trunk (f2c4004).
d0d26373639acd414cd859e8ce4e469a.mp4 |
@Mamaduka Can you elaborate a bit more on your concerns? I may not be understanding you properly 😅 |
…lBadges Reorder props so viewport-related props (viewportStates, viewportValue) and pseudo-related props (pseudoStates, pseudoStateValue) are adjacent, improving readability. Co-Authored-By: Claude <noreply@anthropic.com>
Align the deprecation notice with the release the no-op change actually ships in. Co-Authored-By: Claude <noreply@anthropic.com>
Trim the explanatory comments around the global viewport / per-block pseudo split to keep them concise. Co-Authored-By: Claude <noreply@anthropic.com>
The canvasMinHeight action, selector, and reducer were wired into the store but had no consumers reading or setting them. Drop the dead state to keep the canvas store surface limited to canvasWidth. Co-Authored-By: Claude <noreply@anthropic.com>
Group the canvas width reducer with the related rendering-mode state (where the former deviceType reducer lived) for readability. Co-Authored-By: Claude <noreply@anthropic.com>
Move the isResponsiveEditing reducer and its combineReducers entry next to renderingMode/canvasWidth so the related device-preview state stays together. Co-Authored-By: Claude <noreply@anthropic.com>
Document that the currently hardcoded DEVICE_TYPES breakpoints are expected to become customizable via theme.json settings.viewport, so readers know the literals are a temporary baseline. Co-Authored-By: Claude <noreply@anthropic.com>
Explain why vertical and horizontal padding now have separate triggers: vertical frames a width-constrained canvas, horizontal reserves space for the resize handles. Co-Authored-By: Claude <noreply@anthropic.com>
The selector built a fresh object on every call, so useSelect in BlockStyleControls saw a new selectedState reference each render and warned about unstable values / unnecessary re-renders. Wrap it in createSelector keyed on the viewport and per-block style state so the same inputs return a stable reference. Co-Authored-By: Claude <noreply@anthropic.com>
Drop the showDeviceBadge and showStyleStateInfo locals and gate the style-state info area directly on hasPseudoState || isResponsiveEditing. This removes the style-support guard so the device badge shows for any block during Responsive editing, matching BlockStateBadges, and resolves the inconsistency where the outer guard suppressed the badge. Co-Authored-By: Claude <noreply@anthropic.com>
The unit test selected a viewport state through the per-block "State: Default" dropdown, which no longer exists: viewport states are now chosen via the editor's global device preview (Responsive editing), which lives in @wordpress/editor and cannot be rendered from a block-library unit test. Driving the block editor store directly would require leaking the editor's sub-registry through the shared integration test helper, which is too invasive. Remove the broken unit test and its now-unused helper, and cover the behavior with an e2e test that exercises the real user flow: enable Responsive editing, switch the device preview to Tablet, and assert the Cover overlay controls are hidden. Co-Authored-By: Claude <noreply@anthropic.com>
Add an info description to the "Responsive editing" menu item clarifying that edits made in this mode apply only to the current state, so users understand the scope before enabling it. Co-Authored-By: Claude <noreply@anthropic.com>
The viewport badge followed the device preview dropdown but not a manual canvas resize: the dropdown imperatively synced the viewport style state, while the resize handle only updated the canvas width. Since the canvas width is the single source of truth for the device preview, centralize the sync in setCanvasWidth so the viewport style state stays in step however the width changes, and drop the now-redundant sync from the preview dropdown handler. Co-Authored-By: Claude <noreply@anthropic.com>
The viewport is selected globally via the device preview, yet the per-block selected style state still carried a viewport field. The reducer seeded it and the inspector wrote it back, but the selector always overrode it with the global viewport, so the per-block copy was never read. Stop storing it: remove the reducer seed, and pass only the changed value from the inspector so the global viewport is not written back. The selector keeps deriving the viewport from the global state. Co-Authored-By: Claude <noreply@anthropic.com>
jasmussen
left a comment
There was a problem hiding this comment.
This is a strong PR, nice work. I'll defer to others on other details or followups, but for me this looks good.
One detail, to fix or ignore, if I go to the site editor and edit a template, I see View site here:
Similar to other screens I would expect that at the bottom, rather than in the middle. Minor.
That's pretty much what makes me uncomfortable with the preview-only approach: it's pretending to be something it isn't. Global state would imply that anything you do in a certain viewport only applies to that viewport, but that's not the case here. What actually happens is that the state enables some of the inspector controls to output viewport-specific styles. In the context of the inspector that's fairly clear because we're hiding the controls that don't work when the state is enabled, but the UI changes in this PR make it seem that the state is applicable to the whole editor. But the block toolbar controls aren't viewport-specific. If I remove an image caption in the mobile view, it stays removed across all breakpoints. The same goes for reordering blocks and replacing block content. An additional subtlety is the difference between "Desktop" and "Default": Default state means anything you do applies to all breakpoints. That's what happens when "Desktop" is set in the preview, but with "responsive editing" checked, when we say edits apply only to the current state, that's not true for Desktop. We're early enough in the 7.1 cycle that I think we can afford to try this out and see how it feels (and hopefully get feedback on it) but we do need to iterate on a few things, or we risk shipping a very confusing experience. |
I'd agree with this. To take it further, the drop down promises "Edits apply only to the current state." Which edits? I know it's meant for styles, but does the user? And where are the gaps, that is, things that won't apply like certain block controls etc. I like the resizable editor - it solves a UX problem, namely that the user can have finer control over previews in the editor, but my gut instinct is that it's too early for the drop down addition until responsive styles is more mature. That's just my non-blocking opinion. Thanks! |
| const isBlockStyleStateSelected = | ||
| ( !! blockType?.attributes?.style && | ||
| hasViewportBlockStyleState( selectedBlockStyleState ) ) || | ||
| hasPseudoBlockStyleState( selectedBlockStyleState ); |
There was a problem hiding this comment.
isDefaultBlockStyleState just calls these two functions, so we shouldn't need to replace it here.
What does blockType?.attributes?.style tell us about block style state selection?
| deprecated( 'wp.blockEditor.useResizeCanvas', { | ||
| since: '7.1', | ||
| hint: 'This hook is deprecated and no longer does anything.', | ||
| } ); |
There was a problem hiding this comment.
Given this is exported from block editor components and could potentially be in use by third parties should we do this? Is there at least an alternative function that we can suggest to replace it?
|
|
||
| return state.selectedBlockStyleState.value ?? DEFAULT_BLOCK_STYLE_STATE; | ||
| } | ||
| export const getSelectedBlockStyleState = createSelector( |
There was a problem hiding this comment.
Is this change necessary? I don't see the viewport value being used anywhere in this PR. The function name being getSelectedBlockStyleState I'd expect it to be concerned with a specific block, not the wider state value (even if they are the same)
Yes, this is something to keep a close eye on. We discussed some potentially text only changes to mitigate it here, and there's some additional discussion here. Unless I'm misunderstanding! |
Oh I see, I missed your comment of 2 weeks ago, sorry! I'm not sure about Desktop-only edits. Would they be useful? If we went that route it would still be possible to style defaults over all breakpoints by switching off responsive editing. It would also enable, to some extent, a mobile-first approach 😄 in that styles could default to a mobile layout and then add tablet/desktop styles on top. Our whole approach to the editor so far has been Desktop-first though, to the extent that it's not even possible to use these tools (device preview and block inspector) on a phone. There might be additional complications to enabling this that I'm not seeing right now. Would be keen to hear what other folks think! |
|
There were 52 collapsed comments, nothing to be sorry for, I just appreciate Aki's patience and resilience with this PR.
No, I don't think they would. What I think is useful to be clear-eyed about, is the philosophy for responsiveness that we are establishing for the editor, and how we apply that, because there are a few ways this can go: 1: Mobile-first, min-width based Essentially, mobile styles are default, larger breakpoints override upward using min-width. E.g. 2: Desktop-first, max-width based Desktop styles are default, smaller breakpoints override downwards using max-width. E.g. 3: Strictly gated ranges, with an optional separate default layer Each breakpoint adds both min and max-width values, which lock their customizations to that breakpoint only. E.g. There are pros and cons to each, but it seems useful to decide between these three strategies and then apply it in a uniform way. Since the site editor is so desktop-first, I always thought the most logical way was to cast Desktop as the default style base, and tablet and mobile (as well as any additioal breakpoints users might be able to register though theme.json in the future) were additive in the downwards direction. |
|
When changing to Tablet or Mobile to see the handles and resize, I don't see the viewport icon while dragging, just when I drop it. The viewport change is visible when some elements change in the Canvas, but if not, it's not possible to know which viewport I'm about to select until I drop the handle. Here is a recording that I see in both post/template and pattern editor, and with and without the responsive editing mode. handle.drag-and-drop.interaction.mp4Regarding the conceptual approach for responsiveness, I second @jasmussen's take
Since editor was built primarily to be used on desktop, it's fair to assume that desktop-first is the way of editing a site. But there are also solid reasons to think that mobile-first is a common use case of editing. For that, a responsive editing settings that allow to push downwards or upwards the edits made (from desktop to the bottom/table to the bottom, or mobile to the top/tablet to the top) at the block level and for the whole editor could work in the future. |


Note
This PR originally aimed to integrate Device Preview with the Resizable Editor. However, following discussion, its scope shifted to relocating the Responsive editing UI.
What?
This PR does two things:
How?
The core idea is to treat the canvas width (in pixels) as the single source of truth, instead of a discrete device type. The device preview dropdown becomes just a tool to set a specific canvas width, and resizing the canvas is the same operation expressed differently.
New private APIs
getCanvasWidth()/setCanvasWidth( width )— Gets/sets the canvas width in pixels. While Responsive editing is enabled, setting it also drives the viewport style state.isResponsiveEditing()/setResponsiveEditing( enabled )— Gets/toggles whether Responsive editing is enabled (session-only).getStyleStateViewport()/setStyleStateViewport( viewport )— Gets/sets the globally selected viewport style state. Block style edits in the inspector apply to this viewport.Changed / deprecated APIs
getDeviceType()/setDeviceType()(editor) —getDeviceTypenow derives the device type fromcanvasWidthinstead of a storeddeviceType, andsetDeviceTypeconverts the device type to a width and dispatchessetCanvasWidthrather than storing the device type directly.useResizeCanvas()(block-editor) — Deprecated and turned into a no-op. This hook only existed for the old device view, which canvas width now replaces.updateDeviceTypeForViewportState()(editor, private) — Removed. The viewport ↔ device-preview sync now lives insidesetCanvasWidth.Testing Instructions
Post Editor, Template Editor
4dd92e2f8dde1b20e416c7c63516bf3e.mp4
Pattern Editor
The resize handles are always visible in this editor. Make sure the device preview dropdown and canvas width work together nicely.
7f71a97bacedc7e0526cc396311b7b28.mp4
Responsive editing UI
defaultand the badge disappears.