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

Allow resizing the sidebar and frame of the site editor #46903

Merged
merged 10 commits into from
Jan 10, 2023
1 change: 1 addition & 0 deletions packages/base-styles/_z-index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ $z-layers: (
".edit-site-layout__header": 2,
".edit-site-layout__canvas-container": 2,
".edit-site-layout__sidebar": 1,
".edit-site-layout__canvas-container.is-resizing::after": 100,
);

@function z-index( $key ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import { VisuallyHidden } from '@wordpress/components';

const DELTA_DISTANCE = 20; // The distance to resize per keydown in pixels.

export default function ResizeHandle( { direction, resizeWidthBy } ) {
export default function ResizeHandle( {
variation = 'default',
direction,
resizeWidthBy,
} ) {
function handleKeyDown( event ) {
const { keyCode } = event;

Expand All @@ -27,7 +31,7 @@ export default function ResizeHandle( { direction, resizeWidthBy } ) {
return (
<>
<button
className={ `resizable-editor__drag-handle is-${ direction }` }
className={ `resizable-editor__drag-handle is-${ direction } is-variation-${ variation }` }
aria-label={ __( 'Drag to resize' ) }
aria-describedby={ `resizable-editor__resize-help-${ direction }` }
onKeyDown={ handleKeyDown }
Expand Down
48 changes: 42 additions & 6 deletions packages/edit-site/src/components/block-editor/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -78,21 +78,50 @@
}

.resizable-editor__drag-handle {
$height: 100px;
position: absolute;
top: 0;
bottom: 0;
padding: 0;
margin: auto 0;
width: $grid-unit-05;
height: $height;
width: $grid-unit-15;
appearance: none;
cursor: ew-resize;
outline: none;
background: $gray-600;
background: none;
border-radius: 2px;
border: 0;

&.is-variation-default {
height: 100px;
}

&.is-variation-separator {
height: 100%;

&::after {
width: 1px;
border-radius: 0;
background: $gray-800;
left: auto;
right: 50%;
transition: all ease 0.2s;
transition-delay: 0.1s;
@include reduce-motion;
}
}

&::after {
position: absolute;
top: 0;
left: $grid-unit-05;
right: 0;
bottom: 0;
content: "";
width: $grid-unit-05;
background: $gray-600;
border-radius: 2px;
Copy link
Member

Choose a reason for hiding this comment

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

Could it be $radius-block-ui?

}

&.is-left {
left: -$grid-unit-20;
}
Expand All @@ -103,10 +132,17 @@

&:hover,
&:active {
background: $gray-400;
opacity: 1;
&.is-variation-default::after {
background: $gray-400;
}
&.is-variation-separator::after {
width: 2px;
background: var(--wp-admin-theme-color);
}
}

&:focus {
&:focus::after {
box-shadow: 0 0 0 1px $gray-800, 0 0 0 calc(var(--wp-admin-border-width-focus) + 1px) var(--wp-admin-theme-color);
}
}
118 changes: 98 additions & 20 deletions packages/edit-site/src/components/layout/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ import {
__unstableMotion as motion,
__unstableAnimatePresence as AnimatePresence,
__unstableUseNavigateRegions as useNavigateRegions,
ResizableBox,
} from '@wordpress/components';
import {
useReducedMotion,
useViewportMatch,
useResizeObserver,
} from '@wordpress/compose';
import { __ } from '@wordpress/i18n';
import { useState, useEffect } from '@wordpress/element';
import { useState, useEffect, useRef } from '@wordpress/element';
import { NavigableRegion } from '@wordpress/interface';
import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts';

Expand All @@ -35,13 +36,25 @@ import getIsListPage from '../../utils/get-is-list-page';
import Header from '../header-edit-mode';
import useInitEditedEntityFromURL from '../sync-state-with-url/use-init-edited-entity-from-url';
import SiteHub from '../site-hub';
import ResizeHandle from '../block-editor/resize-handle';

const ANIMATION_DURATION = 0.5;
const emptyResizeHandleStyles = {
position: undefined,
userSelect: undefined,
cursor: undefined,
width: undefined,
height: undefined,
top: undefined,
right: undefined,
bottom: undefined,
left: undefined,
};

export default function Layout( { onError } ) {
// This ensures the edited entity id and type are initialized properly.
useInitEditedEntityFromURL();

const hubRef = useRef();
const { params } = useLocation();
const isListPage = getIsListPage( params );
const isEditorPage = ! isListPage;
Expand Down Expand Up @@ -86,6 +99,14 @@ export default function Layout( { onError } ) {
// Ideally this effect could be removed if we move the "isMobileCanvasVisible" into the store.
const [ canvasResizer, canvasSize ] = useResizeObserver();
const [ fullResizer, fullSize ] = useResizeObserver();
const [ forcedWidth, setForcedWidth ] = useState( null );
const [ isResizing, setIsResizing ] = useState( false );
const isResizingEnabled = ! isMobileViewport && canvasMode === 'view';
const defaultSidebarWidth = isMobileViewport ? '100vw' : 360;
let canvasWidth = isResizing ? '100%' : fullSize.width;
if ( showFrame && ! isResizing ) {
canvasWidth = canvasSize.width - canvasPadding;
}
useEffect( () => {
if ( canvasMode === 'view' && isMobileViewport ) {
setIsMobileCanvasVisible( false );
Expand All @@ -112,7 +133,14 @@ export default function Layout( { onError } ) {
) }
>
<SiteHub
ref={ hubRef }
className="edit-site-layout__hub"
style={ {
width:
isResizingEnabled && forcedWidth
? forcedWidth - 48
: undefined,
} }
isMobileCanvasVisible={ isMobileCanvasVisible }
setIsMobileCanvasVisible={ setIsMobileCanvasVisible }
/>
Expand Down Expand Up @@ -149,7 +177,7 @@ export default function Layout( { onError } ) {
<div className="edit-site-layout__content">
<AnimatePresence initial={ false }>
{ showSidebar && (
<NavigableRegion
<ResizableBox
as={ motion.div }
initial={ {
opacity: 0,
Expand All @@ -162,22 +190,73 @@ export default function Layout( { onError } ) {
} }
transition={ {
type: 'tween',
duration: disableMotion
? 0
: ANIMATION_DURATION,
duration:
disableMotion || isResizing
? 0
: ANIMATION_DURATION,
ease: 'easeOut',
} }
size={ {
height: '100%',
width:
isResizingEnabled && forcedWidth
? forcedWidth
: defaultSidebarWidth,
} }
className="edit-site-layout__sidebar"
ariaLabel={ __( 'Navigation sidebar' ) }
enable={ {
right: isResizingEnabled,
} }
onResizeStop={ ( event, direction, elt ) => {
setForcedWidth( elt.clientWidth );
setIsResizing( false );
} }
onResizeStart={ () => {
setIsResizing( true );
} }
onResize={ ( event, direction, elt ) => {
// This is a performance optimization
// We set the width imperatively to avoid re-rendering
// the whole component while resizing.
hubRef.current.style.width =
elt.clientWidth - 48 + 'px';
} }
handleComponent={ {
right: (
<ResizeHandle
direction="right"
variation="separator"
/>
),
} }
handleClasses={ undefined }
handleStyles={ {
right: emptyResizeHandleStyles,
} }
minWidth={ isResizingEnabled ? 320 : undefined }
maxWidth={
isResizingEnabled && fullSize
? fullSize.width - 360
: undefined
}
>
<Sidebar />
</NavigableRegion>
<NavigableRegion
ariaLabel={ __( 'Navigation sidebar' ) }
>
<Sidebar />
</NavigableRegion>
</ResizableBox>
) }
</AnimatePresence>

{ showCanvas && (
<div
className="edit-site-layout__canvas-container"
className={ classnames(
'edit-site-layout__canvas-container',
{
'is-resizing': isResizing,
}
) }
style={ {
paddingTop: showFrame ? canvasPadding : 0,
paddingBottom: showFrame ? canvasPadding : 0,
Expand All @@ -191,9 +270,10 @@ export default function Layout( { onError } ) {
className="edit-site-layout__canvas"
transition={ {
type: 'tween',
duration: disableMotion
? 0
: ANIMATION_DURATION,
duration:
disableMotion || isResizing
? 0
: ANIMATION_DURATION,
ease: 'easeOut',
} }
>
Expand All @@ -206,16 +286,14 @@ export default function Layout( { onError } ) {
} }
initial={ false }
animate={ {
width: showFrame
? canvasSize.width -
canvasPadding
: fullSize.width,
width: canvasWidth,
} }
transition={ {
type: 'tween',
duration: disableMotion
? 0
: ANIMATION_DURATION,
duration:
disableMotion || isResizing
? 0
: ANIMATION_DURATION,
ease: 'easeOut',
} }
>
Expand Down
30 changes: 26 additions & 4 deletions packages/edit-site/src/components/layout/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -63,34 +63,55 @@ $hub-height: $grid-unit-20 * 2 + $button-size;
.edit-site-layout__content {
flex-grow: 1;
display: flex;
gap: $canvas-padding;

// Hide scrollbars during the edit/view animation.
overflow: hidden;
}

.edit-site-layout__sidebar {
z-index: z-index(".edit-site-layout__sidebar");
overflow-y: auto;
width: 100vw;
@include custom-scrollbars-on-hover;

@include break-medium {
width: $nav-sidebar-width;
}

// This is only necessary for the exit animation
.edit-site-layout.is-full-canvas & {
position: fixed;
position: fixed !important;
height: 100vh;
left: 0;
top: 0;
}

.resizable-editor__drag-handle.is-right {
right: math.div(-$grid-unit-15, 2);
}

> div {
overflow-y: auto;
min-height: 100%;
@include custom-scrollbars-on-hover;
}
}

.edit-site-layout__canvas-container {
position: relative;
flex-grow: 1;
z-index: z-index(".edit-site-layout__canvas-container");

&.is-resizing::after {
// This covers the whole content which ensures mouse up triggers
// even if the content is "inert".
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
content: "";
z-index: z-index(".edit-site-layout__canvas-container.is-resizing::after");
}
}

.edit-site-layout__canvas {
Expand All @@ -99,12 +120,13 @@ $hub-height: $grid-unit-20 * 2 + $button-size;
left: 0;
bottom: 0;
width: 100%;
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.8), 0 8px 10px -6px rgba(0, 0, 0, 0.8);

& > div {
color: $gray-900;
background: $white;
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.8), 0 8px 10px -6px rgba(0, 0, 0, 0.8);
}

@include break-medium {
top: $canvas-padding;
bottom: $canvas-padding;
Expand Down
Loading