Skip to content

Commit 2e0adfe

Browse files
t-hamanofaisalahammadtalldan
committed
Editor: Restore fixed device preview height for mobile and tablet (#80466)
* Editor: Restore fixed device preview height for mobile and tablet Mobile and tablet device previews collapsed to the editor/content height after #75121 dropped the fixed-height frame that useResizeCanvas used to set. This restores the pre-7.1 device-shaped frame (768px mobile, 1024px tablet) by reading deviceType in ResizableEditor and applying a fixed height when one is defined for the active device type. - Add getCanvasHeightByDeviceType() helper alongside the existing width helpers in packages/editor/src/utils/device-type.js. - Wire ResizableEditor to read deviceType from the store and set the ResizableBox size.height to the fixed value when present, falling back to the height prop / 100% otherwise. - Add unit test covering mobile, tablet, and desktop. Desktop preview, the site editor, and the styles canvas (which uses enableResizing=false) are unaffected. * Editor: use aspect ratio for device preview height - Replace fixed pixel heights with aspect ratios (mobile 8/5, tablet 3/4) so the frame scales with canvas width and supports custom viewports. - Add getCanvasHeight selector applying the height only at the preset width, so dragging away frees the canvas to fill the editor. - Simplify the height lookup to a direct map access. - Animate the height transition with the existing width transition. - Update unit tests and API docs for the new selector. Addresses PR feedback. Refs #80271 * Editor: make getCanvasHeight private and inline aspect-ratio logic - Move getCanvasHeight from public selectors.js to private-selectors.js, matching the private getCanvasWidth selector. - Inline the device aspect-ratio logic into getCanvasHeight and delete the single-caller getCanvasHeightByDeviceType helper. Add direct unit tests for getCanvasHeight covering preset heights, desktop, zoom-out, dragging off the preset, missing canvas width, and custom viewport breakpoints. - Switch tablet to portrait (4/3), matching the WordPress 7.0 preview behavior. Mobile stays portrait (8/5). - Remove the now-stale getCanvasHeight section from data-core-editor.md, since private selectors are not documented. Addresses PR feedback. ---- Co-authored-by: faisalahammad <faisalahammad@git.wordpress.org> Co-authored-by: talldan <talldanwp@git.wordpress.org>
1 parent 5dde599 commit 2e0adfe

4 files changed

Lines changed: 138 additions & 6 deletions

File tree

‎packages/editor/src/components/resizable-editor/index.js‎

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,18 @@ function isAtMaxWidth( currentWidth, containerWidth, tolerance = 0 ) {
4545
function ResizableEditor( { className, enableResizing, height, children } ) {
4646
const [ isResizing, setIsResizing ] = useState( false );
4747
const { setCanvasWidth } = unlock( useDispatch( editorStore ) );
48-
const canvasWidth = useSelect(
48+
const { canvasWidth, canvasHeight } = useSelect(
4949
( select ) => {
5050
if ( ! enableResizing ) {
51-
return undefined;
51+
return { canvasWidth: undefined, canvasHeight: undefined };
5252
}
53-
const { getCanvasWidth } = unlock( select( editorStore ) );
54-
return getCanvasWidth();
53+
const { getCanvasWidth, getCanvasHeight } = unlock(
54+
select( editorStore )
55+
);
56+
return {
57+
canvasWidth: getCanvasWidth(),
58+
canvasHeight: getCanvasHeight(),
59+
};
5560
},
5661
[ enableResizing ]
5762
);
@@ -100,7 +105,10 @@ function ResizableEditor( { className, enableResizing, height, children } ) {
100105
size={ {
101106
width:
102107
enableResizing && canvasWidth ? canvasWidth + 'px' : '100%',
103-
height: enableResizing && height ? height : '100%',
108+
height:
109+
enableResizing && canvasHeight
110+
? canvasHeight + 'px'
111+
: height || '100%',
104112
} }
105113
onResizeStart={ () => {
106114
setIsResizing( true );

‎packages/editor/src/components/resizable-editor/style.scss‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// Don't apply transition when resized using the resizer handle.
66
.editor-resizable-editor:not(.is-resizing) {
77
@media (prefers-reduced-motion: no-preference) {
8-
transition: width 0.2s ease-out;
8+
transition: width 0.2s ease-out, height 0.2s ease-out;
99
}
1010
}
1111

‎packages/editor/src/store/private-selectors.js‎

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,22 @@ import {
3535
isEntityReady as _isEntityReady,
3636
} from '../dataviews/store/private-selectors';
3737
import { getTemplatePartIcon } from '../utils';
38+
import {
39+
getDeviceTypeByCanvasWidth,
40+
getCanvasWidthByDeviceType,
41+
} from '../utils/device-type';
3842
import { unlock } from '../lock-unlock';
3943

44+
// Device preview aspect ratios (height / width). Used to give the editor
45+
// canvas a device-shaped frame in mobile and tablet previews. These are
46+
// display ratios for the preview frame, not responsive breakpoints. Mobile
47+
// and tablet are both portrait (taller than wide) to match the WordPress 7.0
48+
// preview behavior.
49+
const DEVICE_ASPECT_RATIO_BY_DEVICE_TYPE = {
50+
Mobile: 8 / 5,
51+
Tablet: 4 / 3,
52+
};
53+
4054
const EMPTY_INSERTION_POINT = {
4155
rootClientId: undefined,
4256
insertionIndex: undefined,
@@ -369,6 +383,45 @@ export const getCanvasWidth = createRegistrySelector(
369383
}
370384
);
371385

386+
/**
387+
* Returns the device preview canvas height in pixels, derived from the canvas
388+
* width using the device aspect ratio. Only applies when the canvas width
389+
* matches the device preset (set via the Preview dropdown), so dragging away
390+
* from the preset frees the frame to fill the editor. Returns `undefined` for
391+
* desktop, zoom-out, or when no device height applies.
392+
*
393+
* @param {Object} state Global application state.
394+
* @return {number|undefined} The canvas height in pixels, or undefined.
395+
*/
396+
export const getCanvasHeight = createRegistrySelector(
397+
( select ) => ( state ) => {
398+
const blockEditorSelect = unlock( select( blockEditorStore ) );
399+
if ( blockEditorSelect.isZoomOut() ) {
400+
return undefined;
401+
}
402+
const canvasWidth = state.canvasWidth;
403+
const viewportSettings =
404+
blockEditorSelect.getSettings().__experimentalFeatures?.viewport;
405+
const deviceType = getDeviceTypeByCanvasWidth(
406+
canvasWidth,
407+
viewportSettings
408+
);
409+
// Only apply the device height at the preset width; a dragged width
410+
// within a band frees the canvas to fill the editor.
411+
if (
412+
canvasWidth !==
413+
getCanvasWidthByDeviceType( deviceType, viewportSettings )
414+
) {
415+
return undefined;
416+
}
417+
const ratio = DEVICE_ASPECT_RATIO_BY_DEVICE_TYPE[ deviceType ];
418+
if ( ratio && canvasWidth > 0 ) {
419+
return Math.round( canvasWidth * ratio );
420+
}
421+
return undefined;
422+
}
423+
);
424+
372425
/**
373426
* Returns the current revisions page number.
374427
*

‎packages/editor/src/store/test/private-selectors.js‎

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
/**
22
* WordPress dependencies
33
*/
4+
import { store as blockEditorStore } from '@wordpress/block-editor';
45
import { store as coreStore } from '@wordpress/core-data';
56
import { store as preferencesStore } from '@wordpress/preferences';
67

78
/**
89
* Internal dependencies
910
*/
1011
import {
12+
getCanvasHeight,
1113
getDefaultRenderingMode,
1214
getPostBlocksByName,
1315
isCollaborationEnabledForCurrentPost,
@@ -251,3 +253,72 @@ describe( 'getDefaultRenderingMode', () => {
251253
} );
252254
} );
253255
} );
256+
257+
describe( 'getCanvasHeight', () => {
258+
// Default viewport breakpoints: Mobile 480, Tablet 782.
259+
function setupRegistry( { isZoomOut = false, viewport } = {} ) {
260+
getCanvasHeight.registry = {
261+
select: ( store ) => {
262+
if ( store === blockEditorStore ) {
263+
// In a real registry, `unlock( select( blockEditorStore ) )`
264+
// returns the combined public + private selectors, so both
265+
// getSettings and isZoomOut live in the unlocked map.
266+
const selectors = {};
267+
lock( selectors, {
268+
getSettings: () => ( {
269+
__experimentalFeatures: viewport
270+
? { viewport }
271+
: {},
272+
} ),
273+
isZoomOut: () => isZoomOut,
274+
} );
275+
return selectors;
276+
}
277+
},
278+
};
279+
}
280+
281+
it( 'returns the portrait height at the mobile preset width', () => {
282+
// Mobile aspect ratio is 8/5 (portrait): 480 * 8/5 = 768.
283+
setupRegistry();
284+
expect( getCanvasHeight( { canvasWidth: 480 } ) ).toBe( 768 );
285+
} );
286+
287+
it( 'returns the portrait height at the tablet preset width', () => {
288+
// Tablet aspect ratio is 4/3 (portrait): 782 * 4/3 = 1043.
289+
setupRegistry();
290+
expect( getCanvasHeight( { canvasWidth: 782 } ) ).toBe( 1043 );
291+
} );
292+
293+
it( 'returns undefined for desktop (no aspect ratio applies)', () => {
294+
setupRegistry();
295+
expect( getCanvasHeight( { canvasWidth: 1200 } ) ).toBeUndefined();
296+
} );
297+
298+
it( 'returns undefined when zoom-out is active', () => {
299+
setupRegistry( { isZoomOut: true } );
300+
expect( getCanvasHeight( { canvasWidth: 480 } ) ).toBeUndefined();
301+
} );
302+
303+
it( 'returns undefined when the width is dragged within a device band but is not the preset', () => {
304+
// 400 resolves to Mobile (at or below the 480 breakpoint) but is not the
305+
// 480 preset, so the device height does not apply and the canvas fills.
306+
setupRegistry();
307+
expect( getCanvasHeight( { canvasWidth: 400 } ) ).toBeUndefined();
308+
} );
309+
310+
it( 'returns undefined when canvasWidth is not set', () => {
311+
setupRegistry();
312+
expect( getCanvasHeight( {} ) ).toBeUndefined();
313+
} );
314+
315+
it( 'uses custom viewport breakpoints when provided', () => {
316+
// Custom mobile preset 640: 640 * 8/5 = 1024.
317+
setupRegistry( {
318+
viewport: { mobile: '640px', tablet: '1024px' },
319+
} );
320+
expect( getCanvasHeight( { canvasWidth: 640 } ) ).toBe( 1024 );
321+
// Custom tablet preset 1024: 1024 * 4/3 = 1365 (rounded).
322+
expect( getCanvasHeight( { canvasWidth: 1024 } ) ).toBe( 1365 );
323+
} );
324+
} );

0 commit comments

Comments
 (0)