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

Add menubar role to header when using top toolbar #55910

Closed
wants to merge 11 commits into from
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@
}
}

.block-editor-block-contextual-toolbar.is-fixed {
position: sticky;
top: 0;
z-index: z-index(".block-editor-block-popover");
display: block;
width: 100%;
}

// on desktop browsers the fixed toolbar has tweaked borders
@include break-medium() {
.block-editor-block-contextual-toolbar.is-fixed {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,9 @@ import classnames from 'classnames';
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import {
forwardRef,
useLayoutEffect,
useEffect,
useRef,
useState,
} from '@wordpress/element';
import { forwardRef } from '@wordpress/element';
import { hasBlockSupport, store as blocksStore } from '@wordpress/blocks';
import { useSelect } from '@wordpress/data';
import {
ToolbarItem,
ToolbarButton,
ToolbarGroup,
} from '@wordpress/components';
import { next, previous } from '@wordpress/icons';
import { useViewportMatch } from '@wordpress/compose';

/**
* Internal dependencies
Expand All @@ -36,137 +23,41 @@ function UnforwardedBlockContextualToolbar(
{ focusOnMount, isFixed, ...props },
ref
) {
// When the toolbar is fixed it can be collapsed
const [ isCollapsed, setIsCollapsed ] = useState( false );
const toolbarButtonRef = useRef();

const isLargeViewport = useViewportMatch( 'medium' );
const {
blockType,
blockEditingMode,
hasParents,
showParentSelector,
selectedBlockClientId,
} = useSelect( ( select ) => {
const {
getBlockName,
getBlockParents,
getSelectedBlockClientIds,
getBlockEditingMode,
} = select( blockEditorStore );
const { getBlockType } = select( blocksStore );
const selectedBlockClientIds = getSelectedBlockClientIds();
const _selectedBlockClientId = selectedBlockClientIds[ 0 ];
const parents = getBlockParents( _selectedBlockClientId );
const firstParentClientId = parents[ parents.length - 1 ];
const parentBlockName = getBlockName( firstParentClientId );
const parentBlockType = getBlockType( parentBlockName );

return {
selectedBlockClientId: _selectedBlockClientId,
blockType:
_selectedBlockClientId &&
getBlockType( getBlockName( _selectedBlockClientId ) ),
blockEditingMode: getBlockEditingMode( _selectedBlockClientId ),
hasParents: parents.length,
showParentSelector:
parentBlockType &&
getBlockEditingMode( firstParentClientId ) === 'default' &&
hasBlockSupport(
parentBlockType,
'__experimentalParentSelector',
true
) &&
selectedBlockClientIds.length <= 1 &&
getBlockEditingMode( _selectedBlockClientId ) === 'default',
};
}, [] );

useEffect( () => {
setIsCollapsed( false );
}, [ selectedBlockClientId ] );

const isLargerThanTabletViewport = useViewportMatch( 'large', '>=' );
const isFullscreen =
document.body.classList.contains( 'is-fullscreen-mode' );

/**
* The following code is a workaround to fix the width of the toolbar
* it should be removed when the toolbar will be rendered inline
* FIXME: remove this layout effect when the toolbar is no longer
* absolutely positioned
*/
useLayoutEffect( () => {
// don't do anything if not fixed toolbar
if ( ! isFixed ) {
return;
}

const blockToolbar = document.querySelector(
'.block-editor-block-contextual-toolbar'
);

if ( ! blockToolbar ) {
return;
}

if ( ! blockType ) {
blockToolbar.style.width = 'initial';
return;
}

if ( ! isLargerThanTabletViewport ) {
// set the width of the toolbar to auto
blockToolbar.style = {};
return;
}

if ( isCollapsed ) {
// set the width of the toolbar to auto
blockToolbar.style.width = 'auto';
return;
}

// get the width of the pinned items in the post editor or widget editor
const pinnedItems = document.querySelector(
'.edit-post-header__settings, .edit-widgets-header__actions'
);
// get the width of the left header in the site editor
const leftHeader = document.querySelector(
'.edit-site-header-edit-mode__end'
);

const computedToolbarStyle = window.getComputedStyle( blockToolbar );
const computedPinnedItemsStyle = pinnedItems
? window.getComputedStyle( pinnedItems )
: false;
const computedLeftHeaderStyle = leftHeader
? window.getComputedStyle( leftHeader )
: false;

const marginLeft = parseFloat( computedToolbarStyle.marginLeft );
const pinnedItemsWidth = computedPinnedItemsStyle
? parseFloat( computedPinnedItemsStyle.width )
: 0;
const leftHeaderWidth = computedLeftHeaderStyle
? parseFloat( computedLeftHeaderStyle.width )
: 0;

// set the new witdth of the toolbar
blockToolbar.style.width = `calc(100% - ${
leftHeaderWidth +
pinnedItemsWidth +
marginLeft +
( pinnedItems || leftHeader ? 2 : 0 ) + // Prevents button focus border from being cut off
( isFullscreen ? 0 : 160 ) // the width of the admin sidebar expanded
}px)`;
}, [
isFixed,
isLargerThanTabletViewport,
isCollapsed,
isFullscreen,
blockType,
] );
const { blockType, blockEditingMode, hasParents, showParentSelector } =
useSelect( ( select ) => {
const {
getBlockName,
getBlockParents,
getSelectedBlockClientIds,
getBlockEditingMode,
} = select( blockEditorStore );
const { getBlockType } = select( blocksStore );
const selectedBlockClientIds = getSelectedBlockClientIds();
const _selectedBlockClientId = selectedBlockClientIds[ 0 ];
const parents = getBlockParents( _selectedBlockClientId );
const firstParentClientId = parents[ parents.length - 1 ];
const parentBlockName = getBlockName( firstParentClientId );
const parentBlockType = getBlockType( parentBlockName );

return {
selectedBlockClientId: _selectedBlockClientId,
blockType:
_selectedBlockClientId &&
getBlockType( getBlockName( _selectedBlockClientId ) ),
blockEditingMode: getBlockEditingMode( _selectedBlockClientId ),
hasParents: parents.length,
showParentSelector:
parentBlockType &&
getBlockEditingMode( firstParentClientId ) === 'default' &&
hasBlockSupport(
parentBlockType,
'__experimentalParentSelector',
true
) &&
selectedBlockClientIds.length <= 1 &&
getBlockEditingMode( _selectedBlockClientId ) === 'default',
};
}, [] );

const isToolbarEnabled =
blockType &&
Expand All @@ -183,7 +74,6 @@ function UnforwardedBlockContextualToolbar(
const classes = classnames( 'block-editor-block-contextual-toolbar', {
'has-parent': hasParents && showParentSelector,
'is-fixed': isFixed,
'is-collapsed': isCollapsed,
} );

return (
Expand All @@ -197,31 +87,7 @@ function UnforwardedBlockContextualToolbar(
variant={ isFixed ? 'unstyled' : undefined }
{ ...props }
>
{ ! isCollapsed && <BlockToolbar hideDragHandle={ isFixed } /> }
{ isFixed && isLargeViewport && blockType && (
<ToolbarGroup
className={
isCollapsed
? 'block-editor-block-toolbar__group-expand-fixed-toolbar'
: 'block-editor-block-toolbar__group-collapse-fixed-toolbar'
}
>
<ToolbarItem
as={ ToolbarButton }
ref={ toolbarButtonRef }
icon={ isCollapsed ? next : previous }
onClick={ () => {
setIsCollapsed( ( collapsed ) => ! collapsed );
toolbarButtonRef.current.focus();
} }
label={
isCollapsed
? __( 'Show block tools' )
: __( 'Hide block tools' )
}
/>
</ToolbarGroup>
) }
<BlockToolbar hideDragHandle={ isFixed } />
</NavigableToolbar>
);
}
Expand Down
44 changes: 40 additions & 4 deletions packages/block-editor/src/components/block-tools/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
*/
import { useSelect, useDispatch } from '@wordpress/data';
import { useViewportMatch } from '@wordpress/compose';
import { Popover } from '@wordpress/components';
import {
Fill,
__experimentalUseSlot as useSlot,
Popover,
} from '@wordpress/components';
import { __unstableUseShortcutEventMatch as useShortcutEventMatch } from '@wordpress/keyboard-shortcuts';
import { useRef } from '@wordpress/element';
import { isUnmodifiedDefaultBlock } from '@wordpress/blocks';
Expand Down Expand Up @@ -90,6 +94,8 @@ export default function BlockTools( {

const selectedBlockToolsRef = useRef( null );

const blockToolsSlot = useSlot( '__experimentalSelectedBlockTools' );

function onKeyDown( event ) {
if ( event.defaultPrevented ) return;

Expand Down Expand Up @@ -164,6 +170,13 @@ export default function BlockTools( {
const blockToolbarRef = usePopoverScroll( __unstableContentRef );
const blockToolbarAfterRef = usePopoverScroll( __unstableContentRef );

// Conditions for fixed toolbar
// 1. Not zoom out mode
// 2. It's a large viewport. If it's a smaller viewport, let the floating toolbar handle it as it already has styles attached to make it render that way.
// 3. Fixed toolbar is enabled
const isTopToolbar = ! isZoomOutMode && hasFixedToolbar && isLargeViewport;
const isTopToolbarFill = isTopToolbar && blockToolsSlot?.ref?.current;

return (
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
<div { ...props } onKeyDown={ onKeyDown }>
Expand All @@ -173,8 +186,18 @@ export default function BlockTools( {
__unstableContentRef={ __unstableContentRef }
/>
) }
{ ! isZoomOutMode &&
( hasFixedToolbar || ! isLargeViewport ) && (
{ /* If there is no slot available, such as in the standalone block editor, render within the editor */ }
{ isTopToolbarFill && (
<Fill name="__experimentalSelectedBlockTools">
<BlockContextualToolbar
ref={ selectedBlockToolsRef }
isFixed
/>
</Fill>
) }

{ ! isTopToolbarFill &&
( isTopToolbar || ! isLargeViewport ) && ( // Small viewports always get a fixed toolbar
<BlockContextualToolbar
ref={ selectedBlockToolsRef }
isFixed
Expand All @@ -198,7 +221,20 @@ export default function BlockTools( {
) }

{ /* Used for the inline rich text toolbar. */ }
<Popover.Slot name="block-toolbar" ref={ blockToolbarRef } />
{ /* Only render in the fill if we're also using the top toolbar fill */ }
{ isTopToolbarFill ? (
<Fill name="__experimentalSelectedBlockTools">
<Popover.Slot
name="block-toolbar"
ref={ blockToolbarRef }
/>
</Fill>
) : (
<Popover.Slot
name="block-toolbar"
ref={ blockToolbarRef }
/>
) }
{ children }
{ /* Used for inline rich text popovers. */ }
<Popover.Slot
Expand Down
31 changes: 0 additions & 31 deletions packages/customize-widgets/src/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,3 @@
.customize-widgets-popover {
@include reset;
}

/**
Fixed bloock toolbar overrides. We can't detect each editor instance
in the styles of the block editor component so we need to override
the fixed styles here because the breakpoint css does not fire in the
customizer's left panel.
*/
.block-editor-block-contextual-toolbar {
&.is-fixed {
position: sticky;
top: 0;
left: 0;
z-index: z-index(".block-editor-block-list__insertion-point");
width: calc(100% + 2 * 12px); //12px is the padding of customizer sidebar content

overflow-y: hidden;

border: none;
border-bottom: $border-width solid $gray-200;
border-radius: 0;

.block-editor-block-toolbar .components-toolbar-group,
.block-editor-block-toolbar .components-toolbar {
border-right-color: $gray-200;
}

&.is-collapsed {
margin-left: -12px; //12px is the padding of customizer sidebar content
}
}
}
Loading
Loading