Skip to content

Commit

Permalink
Allow resizing the sidebar and frame of the site editor (#46903)
Browse files Browse the repository at this point in the history
Co-authored-by: James Koster <james@jameskoster.co.uk>
  • Loading branch information
youknowriad and jameskoster authored Jan 10, 2023
1 parent bd17dad commit 429a0c6
Show file tree
Hide file tree
Showing 6 changed files with 294 additions and 142 deletions.
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
50 changes: 43 additions & 7 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;
border-radius: 2px;
background: none;
border-radius: $radius-block-ui;
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: $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

1 comment on commit 429a0c6

@github-actions
Copy link

Choose a reason for hiding this comment

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

Flaky tests detected in 429a0c6.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/3881224411
📝 Reported issues:

Please sign in to comment.