Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zoom Out: Add a control to enter and leave zoom out mode #63870

Merged
merged 18 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions packages/block-editor/src/components/block-tools/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,12 +251,11 @@ export default function BlockTools( {
name="__unstable-block-tools-after"
ref={ blockToolbarAfterRef }
/>
{ window.__experimentalEnableZoomedOutPatternsTab &&
isZoomOutMode && (
<ZoomOutModeInserters
__unstableContentRef={ __unstableContentRef }
/>
) }
Comment on lines -254 to -259
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the <ZoomOutModeInserters /> from behind the experimental window.__experimentalEnableZoomedOutPatternsTab flag, as you can manually enter zoom out mode via this preview dropdown. I think this is the right call here. Otherwise you don't see the zoom out mode inserters unless you have the experiment on.

{ isZoomOutMode && (
<ZoomOutModeInserters
__unstableContentRef={ __unstableContentRef }
/>
) }
</InsertionPointOpenRef.Provider>
</div>
);
Expand Down
6 changes: 2 additions & 4 deletions packages/block-editor/src/components/iframe/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -242,10 +242,8 @@ function Iframe( {
const isZoomedOut = scale !== 1;

useEffect( () => {
if ( ! isZoomedOut ) {
prevContainerWidth.current = containerWidth;
Comment on lines -245 to -246
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder what led to this change? As I understand it the value of prevContainerWidth should be that of containerWidth before Zoom Out is engaged because the scale calculation needs to arrive at a scale which preserves the document width. That calculation wasn’t perfect before but this seems to have thrown it off a good deal when Zoom Out is engaged by way of the Inserter (not through the control added by this PR).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, I made a PR for that here: #64478

}
}, [ containerWidth, isZoomedOut ] );
prevContainerWidth.current = containerWidth;
}, [ containerWidth ] );

const disabledRef = useDisabled( { isDisabled: ! readonly } );
const bodyRef = useMergeRefs( [
Expand Down
2 changes: 1 addition & 1 deletion packages/block-editor/src/hooks/use-zoom-out.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,5 @@ export function useZoomOut( zoomOut = true ) {
) {
__unstableSetEditorMode( originalEditingMode.current );
}
}, [ __unstableSetEditorMode, zoomOut, mode ] );
}, [ __unstableGetEditorMode, __unstableSetEditorMode, zoomOut ] ); // Mode is deliberately excluded from the dependencies so that the effect does not run when mode changes.
}
3 changes: 1 addition & 2 deletions packages/editor/src/components/header/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ function Header( {
showIconLabels,
hasFixedToolbar,
isNestedEntity,
isZoomedOutView,
} = useSelect( ( select ) => {
const { get: getPreference } = select( preferencesStore );
const {
Expand Down Expand Up @@ -136,7 +135,7 @@ function Header( {
) }
<PreviewDropdown
forceIsAutosaveable={ forceIsDirty }
disabled={ isNestedEntity || isZoomedOutView }
disabled={ isNestedEntity }
/>
<PostPreviewButton
className="editor-header__post-preview-button"
Expand Down
108 changes: 79 additions & 29 deletions packages/editor/src/components/preview-dropdown/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* External dependencies
*/
import clsx from 'clsx';

/**
* WordPress dependencies
*/
Expand All @@ -14,7 +19,9 @@ import { __ } from '@wordpress/i18n';
import { desktop, mobile, tablet, external } from '@wordpress/icons';
import { useSelect, useDispatch } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';
import { useEffect, useRef } from '@wordpress/element';
import { store as preferencesStore } from '@wordpress/preferences';
import { store as blockEditorStore } from '@wordpress/block-editor';

/**
* Internal dependencies
Expand All @@ -23,21 +30,50 @@ import { store as editorStore } from '../../store';
import PostPreviewButton from '../post-preview-button';

export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) {
const { deviceType, homeUrl, isTemplate, isViewable, showIconLabels } =
useSelect( ( select ) => {
const { getDeviceType, getCurrentPostType } = select( editorStore );
const { getUnstableBase, getPostType } = select( coreStore );
const { get } = select( preferencesStore );
const _currentPostType = getCurrentPostType();
return {
deviceType: getDeviceType(),
homeUrl: getUnstableBase()?.home,
isTemplate: _currentPostType === 'wp_template',
isViewable: getPostType( _currentPostType )?.viewable ?? false,
showIconLabels: get( 'core', 'showIconLabels' ),
};
}, [] );
const {
deviceType,
editorMode,
homeUrl,
isTemplate,
isViewable,
showIconLabels,
} = useSelect( ( select ) => {
const { getDeviceType, getCurrentPostType } = select( editorStore );
const { getUnstableBase, getPostType } = select( coreStore );
const { get } = select( preferencesStore );
const { __unstableGetEditorMode } = select( blockEditorStore );
const _currentPostType = getCurrentPostType();
return {
deviceType: getDeviceType(),
editorMode: __unstableGetEditorMode(),
homeUrl: getUnstableBase()?.home,
isTemplate: _currentPostType === 'wp_template',
isViewable: getPostType( _currentPostType )?.viewable ?? false,
showIconLabels: get( 'core', 'showIconLabels' ),
};
}, [] );
const { setDeviceType } = useDispatch( editorStore );
const { __unstableSetEditorMode } = useDispatch( blockEditorStore );

/**
* Save the original editing mode in a ref to restore it when we exit zoom out.
*/
const originalEditingMode = useRef( editorMode );
useEffect( () => {
if ( editorMode !== 'zoom-out' ) {
originalEditingMode.current = editorMode;
}

return () => {
if (
editorMode === 'zoom-out' &&
editorMode !== originalEditingMode.current
) {
__unstableSetEditorMode( originalEditingMode.current );
}
};
}, [ editorMode, __unstableSetEditorMode ] );

const isMobile = useViewportMatch( 'medium', '<' );
if ( isMobile ) {
return null;
Expand All @@ -48,6 +84,7 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) {
};
const toggleProps = {
className: 'editor-preview-dropdown__toggle',
iconPosition: 'right',
size: 'compact',
showTooltip: ! showIconLabels,
disabled,
Expand All @@ -58,9 +95,9 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) {
};

const deviceIcons = {
desktop,
mobile,
tablet,
desktop,
};

/**
Expand All @@ -74,6 +111,11 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) {
label: __( 'Desktop' ),
icon: desktop,
},
{
value: 'ZoomOut',
label: __( 'Desktop (50%)' ),
icon: desktop,
},
{
value: 'Tablet',
label: __( 'Tablet' ),
Expand All @@ -86,29 +128,37 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) {
},
];

const previewValue = editorMode === 'zoom-out' ? 'ZoomOut' : deviceType;

/**
* The selected choice.
* Handles the selection of a device type.
*
* @type {Object}
* @param {string} value The device type.
*/
let selectedChoice = choices.find(
( choice ) => choice.value === deviceType
);
const onSelect = ( value ) => {
let newEditorMode = originalEditingMode.current;

/**
* If no selected choice is found, default to the first
*/
if ( ! selectedChoice ) {
selectedChoice = choices[ 0 ];
}
if ( value === 'ZoomOut' ) {
newEditorMode = 'zoom-out';
setDeviceType( 'Desktop' );
} else {
setDeviceType( value );
}

__unstableSetEditorMode( newEditorMode );
};

return (
<DropdownMenu
className="editor-preview-dropdown"
className={ clsx(
'editor-preview-dropdown',
`editor-preview-dropdown--${ deviceType.toLowerCase() }`
) }
popoverProps={ popoverProps }
toggleProps={ toggleProps }
menuProps={ menuProps }
icon={ deviceIcons[ deviceType.toLowerCase() ] }
text={ editorMode === 'zoom-out' ? __( '50%' ) : undefined }
label={ __( 'View' ) }
disableOpenOnArrowDown={ disabled }
>
Expand All @@ -117,8 +167,8 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) {
<MenuGroup>
<MenuItemsChoice
choices={ choices }
value={ selectedChoice.value }
onSelect={ setDeviceType }
value={ previewValue }
onSelect={ onSelect }
/>
</MenuGroup>
{ isTemplate && (
Expand Down
5 changes: 5 additions & 0 deletions packages/editor/src/components/preview-dropdown/style.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
.editor-preview-dropdown .editor-preview-dropdown__toggle.has-icon.has-text {
padding-right: 4px;
padding-left: 6px;
}

.editor-preview-dropdown__button-external {
width: 100%;
display: flex;
Expand Down
14 changes: 8 additions & 6 deletions packages/editor/src/components/visual-editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ function VisualEditor( {
} ) {
const [ resizeObserver, sizes ] = useResizeObserver();
const isMobileViewport = useViewportMatch( 'small', '<' );
const isTabletViewport = useViewportMatch( 'medium', '<' );
const {
renderingMode,
postContentAttributes,
Expand Down Expand Up @@ -341,12 +342,13 @@ function VisualEditor( {
} ),
] );

const zoomOutProps = isZoomOutMode
? {
scale: 'default',
frameSize: '48px',
}
: {};
const zoomOutProps =
isZoomOutMode && ! isTabletViewport
? {
scale: 'default',
frameSize: '48px',
}
: {};

const forceFullHeight = postType === NAVIGATION_POST_TYPE;
const enableResizing =
Expand Down
Loading