Skip to content

Commit

Permalink
Editor: Improve Header layout (WordPress#62636)
Browse files Browse the repository at this point in the history
* Revise header for resilient centering

* Better match existing responsiveness

* Fix naming typo

* Remove padding from header center to make just a bit more room

* Revise style to add space before collapsible block toolbar

* Account for potential lack of a back button

* Post editor: Leave out the back button instead of hiding it

* Hide post preview button at less than small breakpoint

* Try keeping the Document Bar visible at less than mobile breakpoints

* Revert change to display of post preview button

* Revise mobile display of Document Bar

* Revert conditional rendering changes

* Remove has-back-button class name

* Remove has-center class name

Co-authored-by: stokesman <[email protected]>
Co-authored-by: jeryj <[email protected]>
Co-authored-by: Mamaduka <[email protected]>
Co-authored-by: youknowriad <[email protected]>
Co-authored-by: jasmussen <[email protected]>
Co-authored-by: jameskoster <[email protected]>
Co-authored-by: richtabor <[email protected]>
  • Loading branch information
8 people authored Jul 22, 2024
1 parent 39edce5 commit bced5e0
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,16 @@ import { store as editorStore } from '@wordpress/editor';
import { store as coreStore } from '@wordpress/core-data';
import { useReducedMotion } from '@wordpress/compose';

/**
* Internal dependencies
*/
import { store as editPostStore } from '../../store';

function FullscreenModeClose( { showTooltip, icon, href, initialPost } ) {
const { isActive, isRequestingSiteIcon, postType, siteIconUrl } = useSelect(
const { isRequestingSiteIcon, postType, siteIconUrl } = useSelect(
( select ) => {
const { getCurrentPostType } = select( editorStore );
const { isFeatureActive } = select( editPostStore );
const { getEntityRecord, getPostType, isResolving } =
select( coreStore );
const siteData =
getEntityRecord( 'root', '__unstableBase', undefined ) || {};
const _postType = initialPost?.type || getCurrentPostType();
return {
isActive: isFeatureActive( 'fullscreenMode' ),
isRequestingSiteIcon: isResolving( 'getEntityRecord', [
'root',
'__unstableBase',
Expand All @@ -50,7 +43,7 @@ function FullscreenModeClose( { showTooltip, icon, href, initialPost } ) {

const disableMotion = useReducedMotion();

if ( ! isActive || ! postType ) {
if ( ! postType ) {
return null;
}

Expand Down Expand Up @@ -83,8 +76,7 @@ function FullscreenModeClose( { showTooltip, icon, href, initialPost } ) {
buttonIcon = <Icon size="36px" icon={ icon } />;
}

const classes = clsx( {
'edit-post-fullscreen-mode-close': true,
const classes = clsx( 'edit-post-fullscreen-mode-close', {
'has-icon': siteIconUrl,
} );

Expand Down
4 changes: 0 additions & 4 deletions packages/edit-post/src/components/back-button/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@
// They need to be updated in both places.

.edit-post-fullscreen-mode-close.components-button {
// Do not show the toolbar icon on small screens,
// when Fullscreen Mode is not an option in the "More" menu.
display: none;

@include break-medium() {
display: flex;
align-items: center;
Expand Down
9 changes: 8 additions & 1 deletion packages/edit-post/src/components/layout/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { addQueryArgs } from '@wordpress/url';
import { decodeEntities } from '@wordpress/html-entities';
import { store as coreStore } from '@wordpress/core-data';
import { SlotFillProvider } from '@wordpress/components';
import { useViewportMatch } from '@wordpress/compose';

/**
* Internal dependencies
Expand Down Expand Up @@ -327,6 +328,12 @@ function Layout( {
id: initialPostId,
};
}, [ initialPostType, initialPostId ] );

const backButton =
useViewportMatch( 'medium' ) && isFullscreenActive ? (
<BackButton initialPost={ initialPost } />
) : null;

return (
<SlotFillProvider>
<ErrorBoundary>
Expand Down Expand Up @@ -373,7 +380,7 @@ function Layout( {
<InitPatternModal />
<PluginArea onError={ onPluginAreaError } />
<PostEditorMoreMenu />
<BackButton initialPost={ initialPost } />
{ backButton }
<EditorSnackbars />
</Editor>
</ErrorBoundary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { unlock } from '../../lock-unlock';

const { useHasBlockToolbar } = unlock( blockEditorPrivateApis );

function CollapsableBlockToolbar( { isCollapsed, onToggle } ) {
export default function CollapsibleBlockToolbar( { isCollapsed, onToggle } ) {
const { blockSelectionStart } = useSelect( ( select ) => {
return {
blockSelectionStart:
Expand Down Expand Up @@ -73,5 +73,3 @@ function CollapsableBlockToolbar( { isCollapsed, onToggle } ) {
</>
);
}

export default CollapsableBlockToolbar;
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,3 @@
}
}

.editor-collapsible-block-toolbar__toggle {
margin-left: 2px; // Allow focus ring to be fully visible
}
6 changes: 1 addition & 5 deletions packages/editor/src/components/document-bar/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
min-width: 0;
background: $gray-100;
border-radius: $grid-unit-05;
width: min(100%, 416px);
width: min(100%, 450px);

&:hover {
background-color: $gray-200;
Expand All @@ -25,10 +25,6 @@
background: $gray-200;
}
}

@include break-large() {
width: min(100%, 450px);
}
}

.editor-document-bar__command {
Expand Down
8 changes: 4 additions & 4 deletions packages/editor/src/components/document-tools/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@
.editor-document-tools__left {
display: inline-flex;
align-items: center;
padding-left: $grid-unit-20;
gap: $grid-unit-10;

// Some plugins add buttons here despite best practices.
// Push them a bit rightwards to fit the top toolbar.
margin-right: $grid-unit-10;
// Some plugins add buttons here despite best practices — accommodate them with a gap.
&:not(:last-child) {
margin-inline-end: $grid-unit-10;
}
}

.editor-document-tools .editor-document-tools__left > .editor-document-tools__inserter-toggle.has-icon {
Expand Down
12 changes: 6 additions & 6 deletions packages/editor/src/components/header/back-button.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ import {
// Keeping an old name for backward compatibility.
const slotName = '__experimentalMainDashboardButton';

export const useHasBackButton = () => {
const fills = useSlotFills( slotName );
return Boolean( fills && fills.length );
};

const { Fill, Slot } = createSlotFill( slotName );

const BackButton = Fill;
const BackButtonSlot = ( { children } ) => {
const BackButtonSlot = () => {
const fills = useSlotFills( slotName );
const hasFills = Boolean( fills && fills.length );

if ( ! hasFills ) {
return children;
}

return (
<Slot
Expand Down
51 changes: 26 additions & 25 deletions packages/editor/src/components/header/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
/**
* External dependencies
*/
import clsx from 'clsx';

/**
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';
import { useViewportMatch } from '@wordpress/compose';
import { useMediaQuery, useViewportMatch } from '@wordpress/compose';
import { __unstableMotion as motion } from '@wordpress/components';
import { store as preferencesStore } from '@wordpress/preferences';
import { useState } from '@wordpress/element';
Expand All @@ -17,8 +12,8 @@ import { store as blockEditorStore } from '@wordpress/block-editor';
/**
* Internal dependencies
*/
import BackButton from './back-button';
import CollapsableBlockToolbar from '../collapsible-block-toolbar';
import BackButton, { useHasBackButton } from './back-button';
import CollapsibleBlockToolbar from '../collapsible-block-toolbar';
import DocumentBar from '../document-bar';
import DocumentTools from '../document-tools';
import MoreMenu from '../more-menu';
Expand Down Expand Up @@ -55,6 +50,7 @@ function Header( {
} ) {
const isWideViewport = useViewportMatch( 'large' );
const isLargeViewport = useViewportMatch( 'medium' );
const isTooNarrowForDocumentBar = useMediaQuery( '(max-width: 403px)' );
const {
isTextEditor,
isPublishSidebarOpened,
Expand Down Expand Up @@ -82,21 +78,25 @@ function Header( {
};
}, [] );

const hasTopToolbar = isLargeViewport && hasFixedToolbar;

const [ isBlockToolsCollapsed, setIsBlockToolsCollapsed ] =
useState( true );

const hasCenter = isBlockToolsCollapsed && ! isTooNarrowForDocumentBar;
const hasBackButton = useHasBackButton();

// The edit-post-header classname is only kept for backward compatibilty
// as some plugins might be relying on its presence.
return (
<div className="editor-header edit-post-header">
<motion.div
variants={ backButtonVariations }
transition={ { type: 'tween' } }
>
<BackButton.Slot />
</motion.div>
{ hasBackButton && (
<motion.div
className="editor-header__back-button"
variants={ backButtonVariations }
transition={ { type: 'tween' } }
>
<BackButton.Slot />
</motion.div>
) }
<motion.div
variants={ toolbarVariations }
className="editor-header__toolbar"
Expand All @@ -105,21 +105,22 @@ function Header( {
<DocumentTools
disableBlockTools={ forceDisableBlockTools || isTextEditor }
/>
{ hasTopToolbar && (
<CollapsableBlockToolbar
{ hasFixedToolbar && isLargeViewport && (
<CollapsibleBlockToolbar
isCollapsed={ isBlockToolsCollapsed }
onToggle={ setIsBlockToolsCollapsed }
/>
) }
<div
className={ clsx( 'editor-header__center', {
'is-collapsed':
! isBlockToolsCollapsed && hasTopToolbar,
} ) }
</motion.div>
{ hasCenter && (
<motion.div
className="editor-header__center"
variants={ toolbarVariations }
transition={ { type: 'tween' } }
>
<DocumentBar title={ title } icon={ icon } />
</div>
</motion.div>
</motion.div>
) }
<motion.div
variants={ toolbarVariations }
transition={ { type: 'tween' } }
Expand Down
85 changes: 64 additions & 21 deletions packages/editor/src/components/header/style.scss
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
.editor-header {
height: $header-height;
background: $white;
display: flex;
flex-wrap: wrap;
display: grid;
grid-auto-flow: row;
grid-template: auto / $header-height minmax(0, max-content) minmax(min-content, 1fr) $header-height;
&:has(> .editor-header__center) {
grid-template: auto / $header-height min-content 1fr min-content $header-height;
@include break-medium {
grid-template: auto / $header-height minmax(min-content, 1fr) 2fr minmax(min-content, 1fr) $header-height;
}
}
@include break-mobile {
gap: $grid-unit-20;
}
align-items: center;
// The header should never be wider than the viewport, or buttons might be hidden. Especially relevant at high zoom levels. Related to https://core.trac.wordpress.org/ticket/47603#ticket.
max-width: 100vw;
Expand All @@ -15,19 +25,32 @@
}

.editor-header__toolbar {
grid-column: 1 / 3;
// When there is no back button or the viewport is <= mobile the margin keeps the content off
// the starting edge.
> :first-child {
margin-inline: $grid-unit-20 0;
}

// This is the typical case, the back button takes up the first column.
.editor-header__back-button + & {
grid-column: 2 / 3;

@include break-mobile {
// Clears the margin; at this breakpoint the parent’s `gap` takes its place.
> :first-child {
margin-inline: 0;
}
}
}
display: flex;
// Allow this area to shrink to fit the toolbar buttons.
flex-shrink: 8;
// Take up the space of the toolbar so it can be justified to the left side of the toolbar.
flex-grow: 3;
// Hide the overflow so flex will limit its width. Block toolbar will allow scrolling on fixed toolbar.
overflow: hidden;
// Leave enough room for the focus ring to show.
padding: 2px 0;
// Make narrowing to less than content width possible. Block toolbar will hide overflow and allow scrolling on fixed toolbar.
min-width: 0;
align-items: center;
// Allow focus ring to be fully visible on furthest right button.
@include break-medium() {
padding-right: var(--wp-admin-border-width-focus);
// Clip the box while leaving room for focus rings.
clip-path: inset(-2px);
@include break-mobile {
clip-path: none;
}

.table-of-contents {
Expand All @@ -37,20 +60,35 @@
display: block;
}
}

// Add a gap before the block toolbar or its toggle button when collapsed.
.editor-collapsible-block-toolbar {
margin-inline: $grid-unit 0;

&.is-collapsed ~ .editor-collapsible-block-toolbar__toggle {
margin-inline: $grid-unit 0;
}
}
}

.editor-header__center {
flex-grow: 1;
grid-column: 3 / 4;
display: flex;
justify-content: center;
// Flex items will, by default, refuse to shrink below a minimum
// intrinsic width. In order to shrink this flexbox item, and
// subsequently truncate child text, we set an explicit min-width.
// See https://dev.w3.org/csswg/css-flexbox/#min-size-auto
align-items: center;
// To enable shrinking and truncating of child text, apply an explicit min-width.
min-width: 0;

&.is-collapsed {
display: none;
// Clip the box while leaving room for focus rings.
clip-path: inset(-2px);
// At less than mobile the header’s `gap` is zero so margins are added to create a smaller
// gap around the center’s contents.
@media (max-width: #{$break-mobile - 1}) {
> :first-child {
margin-inline-start: $grid-unit;
}
> :last-child {
margin-inline-end: $grid-unit;
}
}
}

Expand All @@ -59,6 +97,11 @@
*/

.editor-header__settings {
grid-column: 3 / -1;
.editor-header:has(> .editor-header__center) & {
grid-column: 4 / -1;
}
justify-self: end;
display: inline-flex;
align-items: center;
flex-wrap: nowrap;
Expand Down

0 comments on commit bced5e0

Please sign in to comment.