Skip to content

Commit

Permalink
Stacked/unified block toolbar
Browse files Browse the repository at this point in the history
  • Loading branch information
ellatrix committed May 4, 2021
1 parent 90f67f9 commit bfee573
Show file tree
Hide file tree
Showing 30 changed files with 270 additions and 429 deletions.
25 changes: 19 additions & 6 deletions packages/block-editor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ _This package assumes that your code will run in an **ES2015+** environment. If
import {
BlockEditorProvider,
BlockList,
BlockTools,
WritingFlow,
ObserveTyping,
} from '@wordpress/block-editor';
Expand All @@ -34,12 +35,13 @@ function MyEditorComponent() {
onChange={ ( blocks ) => updateBlocks( blocks ) }
>
<SlotFillProvider>
<Popover.Slot name="block-toolbar" />
<WritingFlow>
<ObserveTyping>
<BlockList />
</ObserveTyping>
</WritingFlow>
<BlockTools>
<WritingFlow>
<ObserveTyping>
<BlockList />
</ObserveTyping>
</WritingFlow>
</BlockTools>
<Popover.Slot />
</SlotFillProvider>
</BlockEditorProvider>
Expand Down Expand Up @@ -226,6 +228,17 @@ _Returns_

Undocumented declaration.

<a name="BlockTools" href="#BlockTools">#</a> **BlockTools**

Renders block tools (the block toolbar, select/navigation mode toolbar, the
insertion point and a slot for the inline rich text toolbar). Must be wrapped
around the block content and editor styles wrapper or iframe.

_Parameters_

- _$0_ `Object`: Props.
- _$0.children_ `Object`: The block content and style container.

<a name="BlockVerticalAlignmentControl" href="#BlockVerticalAlignmentControl">#</a> **BlockVerticalAlignmentControl**

Undocumented declaration.
Expand Down
6 changes: 3 additions & 3 deletions packages/block-editor/src/components/block-list/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ import BlockListBlock from './block';
import BlockListAppender from '../block-list-appender';
import useBlockDropZone from '../use-block-drop-zone';
import { useInBetweenInserter } from './use-in-between-inserter';
import BlockTools from '../block-tools';
import { store as blockEditorStore } from '../../store';
import { usePreParsePatterns } from '../../utils/pre-parse-patterns';
import { LayoutProvider, defaultLayout } from './layout';
import BlockToolsBackCompat from '../block-tools/back-compat';

function Root( { className, children } ) {
const isLargeViewport = useViewportMatch( 'medium' );
Expand Down Expand Up @@ -67,11 +67,11 @@ function Root( { className, children } ) {
export default function BlockList( { className, __experimentalLayout } ) {
usePreParsePatterns();
return (
<BlockTools>
<BlockToolsBackCompat>
<Root className={ className }>
<BlockListItems __experimentalLayout={ __experimentalLayout } />
</Root>
</BlockTools>
</BlockToolsBackCompat>
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
}
}

.block-editor-block-contextual-toolbar.has-parent {
.block-editor-block-contextual-toolbar.has-parent:not(.is-fixed) {
margin-left: calc(#{$grid-unit-60} + #{$grid-unit-10});

.show-icon-labels & {
Expand Down
31 changes: 31 additions & 0 deletions packages/block-editor/src/components/block-tools/back-compat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* WordPress dependencies
*/
import { useContext } from '@wordpress/element';
import deprecated from '@wordpress/deprecated';

/**
* Internal dependencies
*/
import InsertionPoint, { InsertionPointOpenRef } from './insertion-point';
import BlockPopover from './block-popover';

export default function BlockToolsBackCompat( { children } ) {
const openRef = useContext( InsertionPointOpenRef );

// If context is set, `BlockTools` is a parent component.
if ( openRef ) {
return children;
}

deprecated( 'wp.components.Popover.Slot name="block-toolbar"', {
alternative: 'wp.blockEditor.BlockTools',
} );

return (
<InsertionPoint __unstablePopoverSlot="block-toolbar">
<BlockPopover __unstablePopoverSlot="block-toolbar" />
{ children }
</InsertionPoint>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ import { useSelect } from '@wordpress/data';
* Internal dependencies
*/
import NavigableToolbar from '../navigable-toolbar';
import { BlockToolbar } from '../';
import BlockToolbar from '../block-toolbar';
import { store as blockEditorStore } from '../../store';

function BlockContextualToolbar( { focusOnMount, ...props } ) {
function BlockContextualToolbar( { focusOnMount, isFixed, ...props } ) {
const { blockType, hasParents } = useSelect( ( select ) => {
const {
getBlockName,
Expand All @@ -43,20 +43,19 @@ function BlockContextualToolbar( { focusOnMount, ...props } ) {
// Shifts the toolbar to make room for the parent block selector.
const classes = classnames( 'block-editor-block-contextual-toolbar', {
'has-parent': hasParents,
'is-fixed': isFixed,
} );

return (
<div className="block-editor-block-contextual-toolbar-wrapper">
<NavigableToolbar
focusOnMount={ focusOnMount }
className={ classes }
/* translators: accessibility text for the block toolbar */
aria-label={ __( 'Block tools' ) }
{ ...props }
>
<BlockToolbar />
</NavigableToolbar>
</div>
<NavigableToolbar
focusOnMount={ focusOnMount }
className={ classes }
/* translators: accessibility text for the block toolbar */
aria-label={ __( 'Block tools' ) }
{ ...props }
>
<BlockToolbar hideDragHandle={ isFixed } />
</NavigableToolbar>
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ function BlockPopover( {
isValid,
isEmptyDefaultBlock,
capturingClientId,
__unstablePopoverSlot,
} ) {
const {
isNavigationMode,
Expand Down Expand Up @@ -180,7 +181,9 @@ function BlockPopover( {
anchorRef={ anchorRef }
className="block-editor-block-list__block-popover"
__unstableStickyBoundaryElement={ stickyBoundaryElement }
__unstableSlotName="block-toolbar"
// Render in the old slot if needed for backward compatibility,
// otherwise render in place (not in the the default popover slot).
__unstableSlotName={ __unstablePopoverSlot || null }
__unstableBoundaryParent
// Observe movement for block animations (especially horizontal).
__unstableObserveElement={ node }
Expand Down Expand Up @@ -293,7 +296,7 @@ function wrapperSelector( select ) {
};
}

export default function WrappedBlockPopover() {
export default function WrappedBlockPopover( { __unstablePopoverSlot } ) {
const selected = useSelect( wrapperSelector, [] );

if ( ! selected ) {
Expand All @@ -320,6 +323,7 @@ export default function WrappedBlockPopover() {
isValid={ isValid }
isEmptyDefaultBlock={ isEmptyDefaultBlock }
capturingClientId={ capturingClientId }
__unstablePopoverSlot={ __unstablePopoverSlot }
/>
);
}
32 changes: 32 additions & 0 deletions packages/block-editor/src/components/block-tools/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,46 @@
/**
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';
import { useViewportMatch } from '@wordpress/compose';
import { Popover } from '@wordpress/components';

/**
* Internal dependencies
*/
import InsertionPoint from './insertion-point';
import BlockPopover from './block-popover';
import { store as blockEditorStore } from '../../store';
import BlockContextualToolbar from './block-contextual-toolbar';

/**
* Renders block tools (the block toolbar, select/navigation mode toolbar, the
* insertion point and a slot for the inline rich text toolbar). Must be wrapped
* around the block content and editor styles wrapper or iframe.
*
* @param {Object} $0 Props.
* @param {Object} $0.children The block content and style container.
*/
export default function BlockTools( { children } ) {
const isLargeViewport = useViewportMatch( 'medium' );
const hasFixedToolbar = useSelect(
( select ) => select( blockEditorStore ).getSettings().hasFixedToolbar,
[]
);

return (
<InsertionPoint>
{ ( hasFixedToolbar || ! isLargeViewport ) && (
<BlockContextualToolbar isFixed />
) }
{ /* Even if the toolbar is fixed, the block popover is still
needed for navigation mode. */ }
<BlockPopover />
{ /* Used for the inline rich text toolbar. */ }
<Popover.Slot name="block-toolbar" />
{ children }
{ /* Forward compatibility: a place to render block tools behind the
content so it can be tabbed to properly. */ }
</InsertionPoint>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { __unstableUseBlockElement as useBlockElement } from '../block-list/use-

export const InsertionPointOpenRef = createContext();

function InsertionPointPopover() {
function InsertionPointPopover( { __unstablePopoverSlot } ) {
const { selectBlock } = useDispatch( blockEditorStore );
const openRef = useContext( InsertionPointOpenRef );
const ref = useRef();
Expand Down Expand Up @@ -117,6 +117,7 @@ function InsertionPointPopover() {
}, [ previousElement, nextElement ] );

const getAnchorRect = useCallback( () => {
const { ownerDocument } = previousElement;
const previousRect = previousElement.getBoundingClientRect();
const nextRect = nextElement
? nextElement.getBoundingClientRect()
Expand All @@ -128,6 +129,7 @@ function InsertionPointPopover() {
left: previousRect.right,
right: previousRect.left,
bottom: nextRect ? nextRect.top : previousRect.bottom,
ownerDocument,
};
}

Expand All @@ -136,6 +138,7 @@ function InsertionPointPopover() {
left: previousRect.left,
right: previousRect.right,
bottom: nextRect ? nextRect.top : previousRect.bottom,
ownerDocument,
};
}

Expand All @@ -145,6 +148,7 @@ function InsertionPointPopover() {
left: nextRect ? nextRect.right : previousRect.left,
right: previousRect.left,
bottom: previousRect.bottom,
ownerDocument,
};
}

Expand All @@ -153,6 +157,7 @@ function InsertionPointPopover() {
left: previousRect.right,
right: nextRect ? nextRect.left : previousRect.right,
bottom: previousRect.bottom,
ownerDocument,
};
}, [ previousElement, nextElement ] );

Expand Down Expand Up @@ -205,7 +210,9 @@ function InsertionPointPopover() {
getAnchorRect={ getAnchorRect }
focusOnMount={ false }
className="block-editor-block-list__insertion-point-popover"
__unstableSlotName="block-toolbar"
// Render in the old slot if needed for backward compatibility,
// otherwise render in place (not in the the default popover slot).
__unstableSlotName={ __unstablePopoverSlot || null }
>
<div
ref={ ref }
Expand Down
54 changes: 33 additions & 21 deletions packages/block-editor/src/components/block-tools/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,25 @@
border-right-color: $gray-900;
}

&.is-fixed {
position: sticky;
top: 0;
width: 100%;
z-index: z-index(".block-editor-block-list__block-popover");
// Fill up when empty
min-height: $block-toolbar-height;
display: block;

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;
}
}

.block-editor-block-mover-button {
overflow: hidden;
}
Expand All @@ -140,29 +159,23 @@
}

// Position mover arrows for both toolbars.
.block-editor-block-contextual-toolbar,
.edit-post-header-toolbar__block-toolbar,
.edit-site-header-toolbar__block-toolbar,
.edit-navigation-layout__block-toolbar,
.edit-widgets-header__block-toolbar {
.block-editor-block-mover:not(.is-horizontal) {
// Position SVGs.
.block-editor-block-mover-button {
&:focus::before {
left: 0 !important;
min-width: 0;
width: 100%;
}
.block-editor-block-contextual-toolbar .block-editor-block-mover:not(.is-horizontal) {
// Position SVGs.
.block-editor-block-mover-button {
&:focus::before {
left: 0 !important;
min-width: 0;
width: 100%;
}
}

@include break-small() {
.block-editor-block-mover-button.is-up-button svg {
top: 5px;
}
@include break-small() {
.block-editor-block-mover-button.is-up-button svg {
top: 5px;
}

.block-editor-block-mover-button.is-down-button svg {
bottom: 5px;
}
.block-editor-block-mover-button.is-down-button svg {
bottom: 5px;
}
}
}
Expand Down Expand Up @@ -234,7 +247,6 @@
}
}


/**
* Popovers.
*/
Expand Down
1 change: 1 addition & 0 deletions packages/block-editor/src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export { default as BlockSettingsMenu } from './block-settings-menu';
export { default as BlockSettingsMenuControls } from './block-settings-menu-controls';
export { default as BlockTitle } from './block-title';
export { default as BlockToolbar } from './block-toolbar';
export { default as BlockTools } from './block-tools';
export {
default as CopyHandler,
useClipboardHandler as __unstableUseClipboardHandler,
Expand Down
5 changes: 3 additions & 2 deletions packages/components/src/popover/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,10 @@ function computeAnchorRect(
return;
}

const rect = getAnchorRect( anchorRefFallback.current );
return offsetIframe(
getAnchorRect( anchorRefFallback.current ),
anchorRefFallback.current.ownerDocument
rect,
rect.ownerDocument || anchorRefFallback.current.ownerDocument
);
}

Expand Down
Loading

0 comments on commit bfee573

Please sign in to comment.