From cf4ffbf5bce83d618f84c590ce5c1e4c735de8a8 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Tue, 8 Sep 2020 16:36:37 +0800 Subject: [PATCH 01/15] Revert "[Try] Customizable toolbar contents (#23613)" This reverts commit 5078c43a3d72eded68d94488dbe6093454815a0e. --- package-lock.json | 46 +++--- packages/block-editor/package.json | 2 - .../src/components/block-controls/index.js | 17 +-- .../expanded-block-controls-container.js | 131 ------------------ .../src/components/block-toolbar/index.js | 14 +- .../src/components/block-toolbar/style.scss | 28 ---- 6 files changed, 27 insertions(+), 211 deletions(-) delete mode 100644 packages/block-editor/src/components/block-toolbar/expanded-block-controls-container.js diff --git a/package-lock.json b/package-lock.json index 8ca2bd93249c56..cf5f01728484a5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15019,19 +15019,12 @@ } }, "@types/react": { - "version": "16.9.49", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.49.tgz", - "integrity": "sha512-DtLFjSj0OYAdVLBbyjhuV9CdGVHCkHn2R+xr3XkBvK2rS1Y1tkc14XSGjYgm5Fjjr90AxH9tiSzc1pCFMGO06g==", + "version": "16.9.18", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.18.tgz", + "integrity": "sha512-MvjiKX/kUE8o49ipppg49RDZ97p4XfW1WWksp/UlTUSJpisyhzd62pZAMXxAscFLoxfYOflkGANAnGkSeHTFQg==", "requires": { "@types/prop-types": "*", - "csstype": "^3.0.2" - }, - "dependencies": { - "csstype": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.3.tgz", - "integrity": "sha512-jPl+wbWPOWJ7SXsWyqGRk3lGecbar0Cb0OvZF/r/ZU011R4YqiRehgkQ9p4eQfo9DSDLqLL3wHwfxeJiuIsNag==" - } + "csstype": "^2.2.0" } }, "@types/react-color": { @@ -15044,9 +15037,9 @@ } }, "@types/react-dom": { - "version": "16.9.8", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.8.tgz", - "integrity": "sha512-ykkPQ+5nFknnlU6lDd947WbQ6TE3NNzbQAkInC2EKY1qeYdTKp7onFusmYZb+ityzx2YviqT6BXSu+LyWWJwcA==", + "version": "16.9.5", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.5.tgz", + "integrity": "sha512-BX6RQ8s9D+2/gDhxrj8OW+YD4R+8hj7FEM/OJHGNR0KipE1h1mSsf39YeyC81qafkq+N3rU3h3RFbLSwE5VqUg==", "requires": { "@types/react": "*" } @@ -16791,7 +16784,6 @@ "@wordpress/token-list": "file:packages/token-list", "@wordpress/url": "file:packages/url", "@wordpress/viewport": "file:packages/viewport", - "@wordpress/warning": "file:packages/warning", "@wordpress/wordcount": "file:packages/wordcount", "classnames": "^2.2.5", "css-mediaquery": "^0.1.2", @@ -16802,7 +16794,6 @@ "memize": "^1.1.0", "react-autosize-textarea": "^3.0.2", "react-spring": "^8.0.19", - "react-transition-group": "^2.9.0", "reakit": "1.1.0", "redux-multi": "^0.1.12", "refx": "^3.0.0", @@ -31656,6 +31647,7 @@ "version": "3.4.0", "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz", "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==", + "dev": true, "requires": { "@babel/runtime": "^7.1.2" } @@ -53111,7 +53103,8 @@ "react-lifecycles-compat": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", - "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==", + "dev": true }, "react-merge-refs": { "version": "1.0.0", @@ -53874,6 +53867,15 @@ "symbol-observable": "1.0.1" } }, + "scheduler": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.15.0.tgz", + "integrity": "sha512-xAefmSfN6jqAa7Kuq7LIJY0bwAPG3xlCj0HMEBQk1lxYiDKZscY2xJ5U/61ZTrYbmNQbXa+gc7czPkVo11tnCg==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -54390,6 +54392,7 @@ "version": "2.9.0", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz", "integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==", + "dev": true, "requires": { "dom-helpers": "^3.4.0", "loose-envify": "^1.4.0", @@ -55971,15 +55974,6 @@ "xmlchars": "^2.1.1" } }, - "scheduler": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.15.0.tgz", - "integrity": "sha512-xAefmSfN6jqAa7Kuq7LIJY0bwAPG3xlCj0HMEBQk1lxYiDKZscY2xJ5U/61ZTrYbmNQbXa+gc7czPkVo11tnCg==", - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, "schema-utils": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index dee14d5468e36a..fc1612ba904f00 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -50,7 +50,6 @@ "@wordpress/token-list": "file:../token-list", "@wordpress/url": "file:../url", "@wordpress/viewport": "file:../viewport", - "@wordpress/warning": "file:../warning", "@wordpress/wordcount": "file:../wordcount", "classnames": "^2.2.5", "css-mediaquery": "^0.1.2", @@ -61,7 +60,6 @@ "memize": "^1.1.0", "react-autosize-textarea": "^3.0.2", "react-spring": "^8.0.19", - "react-transition-group": "^2.9.0", "reakit": "1.1.0", "redux-multi": "^0.1.12", "refx": "^3.0.0", diff --git a/packages/block-editor/src/components/block-controls/index.js b/packages/block-editor/src/components/block-controls/index.js index f2b35e4b5301f8..297d3839df4aa9 100644 --- a/packages/block-editor/src/components/block-controls/index.js +++ b/packages/block-editor/src/components/block-controls/index.js @@ -20,24 +20,18 @@ import useDisplayBlockControls from '../use-display-block-controls'; const { Fill, Slot } = createSlotFill( 'BlockControls' ); -function BlockControlsSlot( { __experimentalIsExpanded = false, ...props } ) { +function BlockControlsSlot( props ) { const accessibleToolbarState = useContext( ToolbarContext ); - return ( - - ); + return ; } -function BlockControlsFill( { controls, __experimentalIsExpanded, children } ) { +function BlockControlsFill( { controls, children } ) { if ( ! useDisplayBlockControls() ) { return null; } return ( - + { ( fillProps ) => { // Children passed to BlockControlsFill will not have access to any // React Context whose Provider is part of the BlockControlsSlot tree. @@ -54,9 +48,6 @@ function BlockControlsFill( { controls, __experimentalIsExpanded, children } ) { ); } -const buildSlotName = ( isExpanded ) => - `BlockControls${ isExpanded ? '-expanded' : '' }`; - const BlockControls = BlockControlsFill; BlockControls.Slot = BlockControlsSlot; diff --git a/packages/block-editor/src/components/block-toolbar/expanded-block-controls-container.js b/packages/block-editor/src/components/block-toolbar/expanded-block-controls-container.js deleted file mode 100644 index e1a475c286e88f..00000000000000 --- a/packages/block-editor/src/components/block-toolbar/expanded-block-controls-container.js +++ /dev/null @@ -1,131 +0,0 @@ -/** - * External dependencies - */ -import { TransitionGroup, CSSTransition } from 'react-transition-group'; -import { throttle } from 'lodash'; - -/** - * WordPress dependencies - */ -import { useRef, useState, useEffect, useCallback } from '@wordpress/element'; -import warning from '@wordpress/warning'; - -/** - * Internal dependencies - */ -import BlockControls from '../block-controls'; - -function getComputedStyle( node ) { - return node.ownerDocument.defaultView.getComputedStyle( node ); -} - -export default function ExpandedBlockControlsContainer( { - children, - className, -} ) { - return ( - - { ( fills ) => { - return ( - - { children } - - ); - } } - - ); -} - -function ExpandedBlockControlsHandler( { fills, className = '', children } ) { - const containerRef = useRef(); - const fillsRef = useRef(); - const toolbarRef = useRef(); - const [ dimensions, setDimensions ] = useState( {} ); - - const fillsPropRef = useRef(); - fillsPropRef.current = fills; - const resizeToolbar = useCallback( - throttle( () => { - const toolbarContentElement = fillsPropRef.current.length - ? fillsRef.current - : toolbarRef.current; - if ( ! toolbarContentElement ) { - return; - } - toolbarContentElement.style.position = 'absolute'; - toolbarContentElement.style.width = 'auto'; - const contentCSS = getComputedStyle( toolbarContentElement ); - setDimensions( { - width: contentCSS.getPropertyValue( 'width' ), - height: contentCSS.getPropertyValue( 'height' ), - } ); - toolbarContentElement.style.position = ''; - toolbarContentElement.style.width = ''; - }, 100 ), - [] - ); - - useEffect( () => { - const observer = new window.MutationObserver( function ( - mutationsList - ) { - const hasChildList = mutationsList.find( - ( { type } ) => type === 'childList' - ); - if ( hasChildList ) { - resizeToolbar(); - } - } ); - - observer.observe( containerRef.current, { - childList: true, - subtree: true, - } ); - - return () => observer.disconnect(); - }, [] ); - - useEffect( () => { - if ( fills.length > 1 ) { - warning( - `${ fills.length } slots were registered but only one may be displayed.` - ); - } - }, [ fills.length ] ); - - const displayFill = fills[ 0 ]; - return ( -
- - { displayFill ? ( - -
- { displayFill } -
-
- ) : ( - -
- { children } -
-
- ) } -
-
- ); -} diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index bed8b921a2fe91..87cfcad1cf9f1a 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -22,12 +22,8 @@ import BlockControls from '../block-controls'; import BlockFormatControls from '../block-format-controls'; import BlockSettingsMenu from '../block-settings-menu'; import { useShowMoversGestures } from './utils'; -import ExpandedBlockControlsContainer from './expanded-block-controls-container'; -export default function BlockToolbar( { - hideDragHandle, - __experimentalExpandedControl = false, -} ) { +export default function BlockToolbar( { hideDragHandle } ) { const { blockClientIds, blockClientId, @@ -106,12 +102,8 @@ export default function BlockToolbar( { shouldShowMovers && 'is-showing-movers' ); - const Wrapper = __experimentalExpandedControl - ? ExpandedBlockControlsContainer - : 'div'; - return ( - +
{ ! isMultiToolbar && (
@@ -141,6 +133,6 @@ export default function BlockToolbar( { ) } - +
); } diff --git a/packages/block-editor/src/components/block-toolbar/style.scss b/packages/block-editor/src/components/block-toolbar/style.scss index bffe229b714e04..c9499b4731dfd0 100644 --- a/packages/block-editor/src/components/block-toolbar/style.scss +++ b/packages/block-editor/src/components/block-toolbar/style.scss @@ -106,31 +106,3 @@ transform: translateY(-($block-toolbar-height + $grid-unit-15)); } } - -.block-editor-block-toolbar-animated-width-container { - position: relative; - overflow: hidden; - transition: width 300ms; -} - -.block-editor-block-toolbar-content-enter { - position: absolute; - top: 0; - left: 0; - width: auto; - opacity: 0; -} -.block-editor-block-toolbar-content-enter-active { - position: absolute; - opacity: 1; - transition: opacity 300ms; -} -.block-editor-block-toolbar-content-exit { - width: auto; - opacity: 1; - pointer-events: none; -} -.block-editor-block-toolbar-content-exit-active { - opacity: 0; - transition: opacity 300ms; -} From 1ea6f986b89bb8f97d31a9614827c0ee21596c48 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Tue, 6 Oct 2020 18:25:10 +0800 Subject: [PATCH 02/15] Add state for inline editing mode --- .../developers/data/data-core-block-editor.md | 24 +++++++++++++++++++ packages/block-editor/src/store/actions.js | 14 +++++++++++ packages/block-editor/src/store/reducer.js | 16 +++++++++++++ packages/block-editor/src/store/selectors.js | 11 +++++++++ 4 files changed, 65 insertions(+) diff --git a/docs/designers-developers/developers/data/data-core-block-editor.md b/docs/designers-developers/developers/data/data-core-block-editor.md index 2fb6515f86a7fb..51816fcec993e2 100644 --- a/docs/designers-developers/developers/data/data-core-block-editor.md +++ b/docs/designers-developers/developers/data/data-core-block-editor.md @@ -442,6 +442,18 @@ _Properties_ - _isDisabled_ `boolean`: Whether or not the user should be prevented from inserting this item. - _frecency_ `number`: Heuristic that combines frequency and recency. +# **getIsEditingInToolbar** + +Returns whether inline toolbar editing UI is visible. + +_Parameters_ + +- _state_ `Object`: Global application state. + +_Returns_ + +- `boolean`: True if inline toolbar editing UI is visible. + # **getLastMultiSelectedBlockClientId** Returns the client ID of the last block in the multi-selection set, or null @@ -1349,6 +1361,18 @@ _Parameters_ - _clientId_ `string`: The block's clientId. - _hasControlledInnerBlocks_ `boolean`: True if the block's inner blocks are controlled. +# **setIsEditingInToolbar** + +Returns an action that updates the toolbar inline editing state. + +_Parameters_ + +- _isEditingInToolbar_ `boolean`: Whether to show or hide inline editing. + +_Returns_ + +- `Object`: Action object. + # **setNavigationMode** Generators that triggers an action used to enable or disable the navigation mode. diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index e506e3271028e8..bbaf9832b1f9cc 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -551,6 +551,20 @@ export function hideInsertionPoint() { }; } +/** + * Returns an action that updates the toolbar inline editing state. + * + * @param {boolean} isEditingInToolbar Whether to show or hide inline editing. + * + * @return {Object} Action object. + */ +export function setIsEditingInToolbar( isEditingInToolbar ) { + return { + type: 'SET_IS_EDITING_IN_TOOLBAR', + isEditingInToolbar, + }; +} + /** * Returns an action object resetting the template validity. * diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index 85898175da7dac..9a259bcf995d0e 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -1530,6 +1530,22 @@ export function isNavigationMode( state = false, action ) { return state; } +/** + * Reducer returning whether the toolbar is showing an inline editing UI. + * + * @param {boolean} state Whether inline editing UI is displayed. + * @param {Object} action Dispatched action. + * + * @return {boolean} Updated state denoting whether inline editing UI is shown. + */ +export function isEditingInToolbar( state = false, action ) { + if ( action.type === 'SET_IS_EDITING_IN_TOOLBAR' ) { + return action.isEditingInToolbar; + } + + return state; +} + /** * Reducer returning whether the block moving mode is enabled or not. * diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index b84a7ff24aed79..94d68040df91e9 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -1791,3 +1791,14 @@ export function isBlockHighlighted( state, clientId ) { export function areInnerBlocksControlled( state, clientId ) { return !! state.blocks.controlledInnerBlocks[ clientId ]; } + +/** + * Returns whether inline toolbar editing UI is visible. + * + * @param {Object} state Global application state. + * + * @return {boolean} True if inline toolbar editing UI is visible. + */ +export function getIsEditingInToolbar( state ) { + return state.isEditingInToolbar; +} From 0e0c0d17c2a75ed7651d3a1573a72d4b952a9049 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Tue, 6 Oct 2020 19:21:35 +0800 Subject: [PATCH 03/15] Add toolbar inline edit components --- .../block-list/block-contextual-toolbar.js | 23 +++++-- .../components/block-list/block-popover.js | 14 +++-- .../src/components/block-list/style.scss | 5 ++ .../block-toolbar-inline-edit/index.js | 62 +++++++++++++++++++ .../popover-wrapper.js | 57 +++++++++++++++++ packages/block-editor/src/components/index.js | 1 + 6 files changed, 152 insertions(+), 10 deletions(-) create mode 100644 packages/block-editor/src/components/block-toolbar-inline-edit/index.js create mode 100644 packages/block-editor/src/components/block-toolbar-inline-edit/popover-wrapper.js diff --git a/packages/block-editor/src/components/block-list/block-contextual-toolbar.js b/packages/block-editor/src/components/block-list/block-contextual-toolbar.js index 154a8f2e1f303c..9e851c4c21f21c 100644 --- a/packages/block-editor/src/components/block-list/block-contextual-toolbar.js +++ b/packages/block-editor/src/components/block-list/block-contextual-toolbar.js @@ -1,3 +1,8 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + /** * WordPress dependencies */ @@ -12,14 +17,17 @@ import NavigableToolbar from '../navigable-toolbar'; import { BlockToolbar } from '../'; function BlockContextualToolbar( { focusOnMount, ...props } ) { - const { blockType } = useSelect( ( select ) => { - const { getBlockName, getSelectedBlockClientIds } = select( - 'core/block-editor' - ); + const { blockType, isEditingInToolbar } = useSelect( ( select ) => { + const { + getBlockName, + getSelectedBlockClientIds, + getIsEditingInToolbar, + } = select( 'core/block-editor' ); const { getBlockType } = select( 'core/blocks' ); const selectedBlockClientIds = getSelectedBlockClientIds(); const selectedBlockClientId = selectedBlockClientIds[ 0 ]; return { + isEditingInToolbar: getIsEditingInToolbar(), blockType: selectedBlockClientId && getBlockType( getBlockName( selectedBlockClientId ) ), @@ -34,7 +42,12 @@ function BlockContextualToolbar( { focusOnMount, ...props } ) {
) } { ( shouldShowContextualToolbar || isToolbarForced ) && ( - + <> + + + ) } { shouldShowBreadcrumb && ( { + if ( isEmpty( fills ) ) { + setIsEditingInToolbar( false ); + } else { + setIsEditingInToolbar( true ); + } + + return () => setIsEditingInToolbar( false ); + }, [ fills ] ); + + return fills; +} + +function BlockToolbarInlineEdit( { onClose, children } ) { + return ( + + +
+ { children } +
+
+
+ ); +} + +function BlockToolbarInlineEditSlot() { + return ( + + { ( fills ) => ( + + ) } + + ); +} + +BlockToolbarInlineEdit.Slot = BlockToolbarInlineEditSlot; + +export default BlockToolbarInlineEdit; diff --git a/packages/block-editor/src/components/block-toolbar-inline-edit/popover-wrapper.js b/packages/block-editor/src/components/block-toolbar-inline-edit/popover-wrapper.js new file mode 100644 index 00000000000000..375ba0ace1179d --- /dev/null +++ b/packages/block-editor/src/components/block-toolbar-inline-edit/popover-wrapper.js @@ -0,0 +1,57 @@ +/** + * WordPress dependencies + */ +import { + withConstrainedTabbing, + withFocusReturn, + withFocusOutside, +} from '@wordpress/components'; +import { Component } from '@wordpress/element'; +import { ESCAPE } from '@wordpress/keycodes'; + +function stopPropagation( event ) { + event.stopPropagation(); +} + +const DetectOutside = withFocusOutside( + class extends Component { + handleFocusOutside( event ) { + this.props.onFocusOutside( event ); + } + + render() { + return this.props.children; + } + } +); + +const FocusManaged = withConstrainedTabbing( + withFocusReturn( ( { children } ) => children ) +); + +export default function PopoverWrapper( { onClose, children, className } ) { + // Event handlers + const maybeClose = ( event ) => { + // Close on escape + if ( event.keyCode === ESCAPE && onClose ) { + event.stopPropagation(); + onClose(); + } + }; + + // Disable reason: this stops certain events from propagating outside of the component. + // - onMouseDown is disabled as this can cause interactions with other DOM elements + /* eslint-disable jsx-a11y/no-static-element-interactions */ + return ( +
+ + { children } + +
+ ); + /* eslint-enable jsx-a11y/no-static-element-interactions */ +} diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js index 7719bfff230e89..72306584cd3bef 100644 --- a/packages/block-editor/src/components/index.js +++ b/packages/block-editor/src/components/index.js @@ -17,6 +17,7 @@ export { default as BlockEdit, useBlockEditContext } from './block-edit'; export { default as BlockFormatControls } from './block-format-controls'; export { default as BlockIcon } from './block-icon'; export { default as BlockNavigationDropdown } from './block-navigation/dropdown'; +export { default as __experimentalBlockToolbarInlineEdit } from './block-toolbar-inline-edit'; export { BlockNavigationBlockFill as __experimentalBlockNavigationBlockFill } from './block-navigation/block-slot'; export { default as __experimentalBlockNavigationEditor } from './block-navigation/editor'; export { default as __experimentalBlockNavigationTree } from './block-navigation/tree'; From 5b465cb8cd5f2755b0d97871bdeec99bc69dd817 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Tue, 6 Oct 2020 19:22:09 +0800 Subject: [PATCH 04/15] Ensure reducer is exported --- packages/block-editor/src/store/reducer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index 9a259bcf995d0e..b4934c277622a7 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -1679,6 +1679,7 @@ export default combineReducers( { preferences, lastBlockAttributesChange, isNavigationMode, + isEditingInToolbar, hasBlockMovingClientId, automaticChangeStatus, highlightedBlock, From 3aa23bcf06319941fce3f15ff8782de4820cc0db Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Tue, 6 Oct 2020 19:23:01 +0800 Subject: [PATCH 05/15] Use inline editing in image block --- packages/block-library/src/image/image-editor.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/block-library/src/image/image-editor.js b/packages/block-library/src/image/image-editor.js index a3401132390fb3..9c02d1fcdb6db7 100644 --- a/packages/block-library/src/image/image-editor.js +++ b/packages/block-library/src/image/image-editor.js @@ -9,7 +9,7 @@ import classnames from 'classnames'; * WordPress dependencies */ -import { BlockControls } from '@wordpress/block-editor'; +import { __experimentalBlockToolbarInlineEdit } from '@wordpress/block-editor'; import { useState } from '@wordpress/element'; import { search, @@ -319,7 +319,7 @@ export default function ImageEditor( { /> { inProgress && }
- + <__experimentalBlockToolbarInlineEdit> - + ); } From 336046e00e778eaf4f3be075abd81d07d191409d Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Wed, 7 Oct 2020 12:23:47 +0800 Subject: [PATCH 06/15] Remove conditional rendering of buttons to ensure focus can be returned to the crop button --- packages/block-library/src/image/image.js | 48 +++++++++++------------ 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index 3e32afd372524d..9a7e927b7d7295 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -248,21 +248,19 @@ export default function Image( { const controls = ( <> - { ! isEditingImage && ( - - - - ) } - { canEditImage && ! isEditingImage && ( + + + + { canEditImage && ( setIsEditingImage( true ) } @@ -280,17 +278,15 @@ export default function Image( { /> ) } - { ! isEditingImage && ( - - ) } + From aabd11ed284c2e9be8381fba5b1de9eaf25fdfd0 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Wed, 7 Oct 2020 12:47:00 +0800 Subject: [PATCH 07/15] Remove some toolbar semantics --- .../block-library/src/image/image-editor.js | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/packages/block-library/src/image/image-editor.js b/packages/block-library/src/image/image-editor.js index 9c02d1fcdb6db7..053e3ccd517bd6 100644 --- a/packages/block-library/src/image/image-editor.js +++ b/packages/block-library/src/image/image-editor.js @@ -20,7 +20,6 @@ import { import { ToolbarGroup, ToolbarButton, - ToolbarItem, Spinner, RangeControl, DropdownMenu, @@ -342,17 +341,12 @@ export default function ImageEditor( { /> ) } /> - - { ( toggleProps ) => ( - - ) } - + Date: Wed, 7 Oct 2020 12:50:25 +0800 Subject: [PATCH 08/15] Prevent WritingFlow from triggering --- .../block-toolbar-inline-edit/popover-wrapper.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/block-toolbar-inline-edit/popover-wrapper.js b/packages/block-editor/src/components/block-toolbar-inline-edit/popover-wrapper.js index 375ba0ace1179d..9de5c8ff6a3fc7 100644 --- a/packages/block-editor/src/components/block-toolbar-inline-edit/popover-wrapper.js +++ b/packages/block-editor/src/components/block-toolbar-inline-edit/popover-wrapper.js @@ -7,7 +7,9 @@ import { withFocusOutside, } from '@wordpress/components'; import { Component } from '@wordpress/element'; -import { ESCAPE } from '@wordpress/keycodes'; +import { ESCAPE, UP, RIGHT, DOWN, LEFT } from '@wordpress/keycodes'; + +const ARROW_KEYCODES = [ UP, RIGHT, DOWN, LEFT ]; function stopPropagation( event ) { event.stopPropagation(); @@ -32,8 +34,13 @@ const FocusManaged = withConstrainedTabbing( export default function PopoverWrapper( { onClose, children, className } ) { // Event handlers const maybeClose = ( event ) => { - // Close on escape + if ( ARROW_KEYCODES.includes( event.keyCode ) ) { + // Prevent WritingFlow from triggering a block focus change. + event.stopPropagation(); + } + if ( event.keyCode === ESCAPE && onClose ) { + // Close on escape event.stopPropagation(); onClose(); } From f439f237b2f2575efc41d77c863ae210a11373dc Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Wed, 7 Oct 2020 12:54:28 +0800 Subject: [PATCH 09/15] Pass onClose prop to ensure esc closes popover --- packages/block-library/src/image/image-editor.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/image/image-editor.js b/packages/block-library/src/image/image-editor.js index 053e3ccd517bd6..1abea058264850 100644 --- a/packages/block-library/src/image/image-editor.js +++ b/packages/block-library/src/image/image-editor.js @@ -318,7 +318,9 @@ export default function ImageEditor( { /> { inProgress && }
- <__experimentalBlockToolbarInlineEdit> + <__experimentalBlockToolbarInlineEdit + onClose={ () => setIsEditingImage( false ) } + > Date: Wed, 7 Oct 2020 12:55:06 +0800 Subject: [PATCH 10/15] Rename function --- .../components/block-toolbar-inline-edit/popover-wrapper.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/block-toolbar-inline-edit/popover-wrapper.js b/packages/block-editor/src/components/block-toolbar-inline-edit/popover-wrapper.js index 9de5c8ff6a3fc7..9c862912c2e9a2 100644 --- a/packages/block-editor/src/components/block-toolbar-inline-edit/popover-wrapper.js +++ b/packages/block-editor/src/components/block-toolbar-inline-edit/popover-wrapper.js @@ -33,7 +33,7 @@ const FocusManaged = withConstrainedTabbing( export default function PopoverWrapper( { onClose, children, className } ) { // Event handlers - const maybeClose = ( event ) => { + const onKeyDown = ( event ) => { if ( ARROW_KEYCODES.includes( event.keyCode ) ) { // Prevent WritingFlow from triggering a block focus change. event.stopPropagation(); @@ -52,7 +52,7 @@ export default function PopoverWrapper( { onClose, children, className } ) { return (
From 8484b553499186bc1f631a2a5ab970c22ab80fab Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Wed, 7 Oct 2020 13:03:17 +0800 Subject: [PATCH 11/15] Add haspopup and expanded aria attributes to crop button --- packages/block-library/src/image/image.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index 9a7e927b7d7295..a484a4167229d4 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -266,6 +266,8 @@ export default function Image( { onClick={ () => setIsEditingImage( true ) } icon={ crop } label={ __( 'Crop' ) } + aria-haspopup="dialog" + aria-expanded={ isEditingImage } /> ) } From b61533762d6d9e53c2654db4b727eca538680084 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Wed, 7 Oct 2020 13:30:06 +0800 Subject: [PATCH 12/15] Hide toolbar more thoroughly --- .../src/components/block-list/style.scss | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/src/components/block-list/style.scss b/packages/block-editor/src/components/block-list/style.scss index 5c8df3f9f17774..10c83c7793780a 100644 --- a/packages/block-editor/src/components/block-list/style.scss +++ b/packages/block-editor/src/components/block-list/style.scss @@ -514,11 +514,17 @@ } } - /** * Block Toolbar when contextual. */ +.block-editor-block-contextual-toolbar-wrapper.is-editing-in-toolbar { + width: 0; + height: 0; + opacity: 0; + overflow: hidden; +} + .block-editor-block-contextual-toolbar { // Block UI appearance. border: $border-width solid $gray-900; @@ -562,11 +568,6 @@ } } } - - &.is-editing-in-toolbar { - width: 0; - opacity: 0; - } } From 5a1e62a12c21490d33e657244723ede80341cd20 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Wed, 7 Oct 2020 13:31:22 +0800 Subject: [PATCH 13/15] Focus first tabbable on mount of the popover wrapper --- .../block-list/block-contextual-toolbar.js | 16 ++--- .../popover-wrapper.js | 62 ++++++++++++++++++- 2 files changed, 69 insertions(+), 9 deletions(-) diff --git a/packages/block-editor/src/components/block-list/block-contextual-toolbar.js b/packages/block-editor/src/components/block-list/block-contextual-toolbar.js index 9e851c4c21f21c..f2c35796246bba 100644 --- a/packages/block-editor/src/components/block-list/block-contextual-toolbar.js +++ b/packages/block-editor/src/components/block-list/block-contextual-toolbar.js @@ -39,15 +39,17 @@ function BlockContextualToolbar( { focusOnMount, ...props } ) { } } return ( -
+
children ) ); -export default function PopoverWrapper( { onClose, children, className } ) { +/** + * Hook used to focus the first tabbable element on mount. + * + * @param {boolean|string} focusOnMount Focus on mount mode. + * @param {Object} contentRef Reference to the popover content element. + */ +function useFocusContentOnMount( focusOnMount, contentRef ) { + // Focus handling + useEffect( () => { + /* + * Without the setTimeout, the dom node is not being focused. Related: + * https://stackoverflow.com/questions/35522220/react-ref-with-focus-doesnt-work-without-settimeout-my-example + * + * TODO: Treat the cause, not the symptom. + */ + const focusTimeout = setTimeout( () => { + if ( ! focusOnMount || ! contentRef.current ) { + return; + } + + if ( focusOnMount === 'firstElement' ) { + // Find first tabbable node within content and shift focus, falling + // back to the popover panel itself. + const firstTabbable = focus.tabbable.find( + contentRef.current + )[ 0 ]; + + if ( firstTabbable ) { + firstTabbable.focus(); + } else { + contentRef.current.focus(); + } + + return; + } + + if ( focusOnMount === 'container' ) { + // Focus the popover panel itself so items in the popover are easily + // accessed via keyboard navigation. + contentRef.current.focus(); + } + }, 0 ); + + return () => clearTimeout( focusTimeout ); + }, [] ); +} + +export default function PopoverWrapper( { + onClose, + focusOnMount = 'firstElement', + children, + className, +} ) { // Event handlers const onKeyDown = ( event ) => { if ( ARROW_KEYCODES.includes( event.keyCode ) ) { @@ -46,11 +99,16 @@ export default function PopoverWrapper( { onClose, children, className } ) { } }; + const contentRef = useRef(); + + useFocusContentOnMount( focusOnMount, contentRef ); + // Disable reason: this stops certain events from propagating outside of the component. // - onMouseDown is disabled as this can cause interactions with other DOM elements /* eslint-disable jsx-a11y/no-static-element-interactions */ return (
Date: Mon, 12 Oct 2020 16:17:07 +0800 Subject: [PATCH 14/15] Use flex for toolbar inline edit contents --- .../src/components/block-toolbar-inline-edit/style.scss | 3 +++ packages/block-editor/src/style.scss | 1 + 2 files changed, 4 insertions(+) create mode 100644 packages/block-editor/src/components/block-toolbar-inline-edit/style.scss diff --git a/packages/block-editor/src/components/block-toolbar-inline-edit/style.scss b/packages/block-editor/src/components/block-toolbar-inline-edit/style.scss new file mode 100644 index 00000000000000..b9bced138c3782 --- /dev/null +++ b/packages/block-editor/src/components/block-toolbar-inline-edit/style.scss @@ -0,0 +1,3 @@ +.block-editor-block-toolbar-inline-edit-popover__toolbar-wrapper { + display: flex; +} diff --git a/packages/block-editor/src/style.scss b/packages/block-editor/src/style.scss index 096eb3bacb7969..84bfa247103e08 100644 --- a/packages/block-editor/src/style.scss +++ b/packages/block-editor/src/style.scss @@ -24,6 +24,7 @@ @import "./components/block-settings-menu/style.scss"; @import "./components/block-styles/style.scss"; @import "./components/block-switcher/style.scss"; +@import "./components/block-toolbar-inline-edit/style.scss"; @import "./components/block-types-list/style.scss"; @import "./components/block-variation-picker/style.scss"; @import "./components/button-block-appender/style.scss"; From a5357faf485e3e6971f0e6f6a1e0a4e0686c5a3f Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Mon, 12 Oct 2020 16:19:42 +0800 Subject: [PATCH 15/15] Add basic styles to match toolbar --- .../src/components/block-toolbar-inline-edit/style.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/block-editor/src/components/block-toolbar-inline-edit/style.scss b/packages/block-editor/src/components/block-toolbar-inline-edit/style.scss index b9bced138c3782..0ba61112c6876f 100644 --- a/packages/block-editor/src/components/block-toolbar-inline-edit/style.scss +++ b/packages/block-editor/src/components/block-toolbar-inline-edit/style.scss @@ -1,3 +1,7 @@ +.block-editor-block-toolbar-inline-edit-popover { + margin-bottom: $grid-unit-15; +} + .block-editor-block-toolbar-inline-edit-popover__toolbar-wrapper { display: flex; }