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 99cc264cc7e2e..0506c426c07f4 100644 --- a/docs/designers-developers/developers/data/data-core-block-editor.md +++ b/docs/designers-developers/developers/data/data-core-block-editor.md @@ -1141,16 +1141,12 @@ _Parameters_ # **setNavigationMode** -Returns an action object used to enable or disable the navigation mode. +Generators that triggers an action used to enable or disable the navigation mode. _Parameters_ - _isNavigationMode_ `string`: Enable/Disable navigation mode. -_Returns_ - -- `Object`: Action object - # **setTemplateValidity** Returns an action object resetting the template validity. diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index c90ced2fe3c7c..cf04f3f559a43 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -427,6 +427,10 @@ _Type_ - `Object` +# **ToolSelector** + +Undocumented declaration. + # **transformStyles** Applies a series of CSS rule transforms to wrap selectors inside a given class and/or rewrite URLs depending on the parameters passed. diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js index 48b5506e452f2..d2695ac0e0b21 100644 --- a/packages/block-editor/src/components/block-list/block.js +++ b/packages/block-editor/src/components/block-list/block.js @@ -101,7 +101,7 @@ function BlockListBlock( { animateOnChange, enableAnimation, isNavigationMode, - enableNavigationMode, + setNavigationMode, } ) { // Random state used to rerender the component if needed, ideally we don't need this const [ , updateRerenderState ] = useState( {} ); @@ -326,7 +326,7 @@ function BlockListBlock( { isSelected && isEditMode ) { - enableNavigationMode(); + setNavigationMode( true ); wrapper.current.focus(); } break; @@ -345,6 +345,14 @@ function BlockListBlock( { return; } + if ( + isNavigationMode && + isSelected && + isInsideRootBlock( blockNodeRef.current, event.target ) + ) { + setNavigationMode( false ); + } + if ( event.shiftKey ) { if ( ! isSelected ) { onShiftSelection(); @@ -778,9 +786,7 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, { select } ) => { toggleSelection( selectionEnabled ) { toggleSelection( selectionEnabled ); }, - enableNavigationMode() { - setNavigationMode( true ); - }, + setNavigationMode, }; } ); diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js index c7792608518ac..2ff44fed17fb4 100644 --- a/packages/block-editor/src/components/index.js +++ b/packages/block-editor/src/components/index.js @@ -39,6 +39,7 @@ export { RichTextToolbarButton, __unstableRichTextInputEvent, } from './rich-text'; +export { default as ToolSelector } from './tool-selector'; export { default as URLInput } from './url-input'; export { default as URLInputButton } from './url-input/button'; export { default as URLPopover } from './url-popover'; diff --git a/packages/block-editor/src/components/inner-blocks/index.js b/packages/block-editor/src/components/inner-blocks/index.js index ed147bfe736ad..dc281d0f42f4f 100644 --- a/packages/block-editor/src/components/inner-blocks/index.js +++ b/packages/block-editor/src/components/inner-blocks/index.js @@ -7,7 +7,7 @@ import classnames from 'classnames'; /** * WordPress dependencies */ -import { withViewportMatch } from '@wordpress/viewport'; // Temporary click-through disable on desktop. +import { withViewportMatch } from '@wordpress/viewport'; import { Component } from '@wordpress/element'; import { withSelect, withDispatch } from '@wordpress/data'; import { synchronizeBlocksWithTemplate, withBlockContentContext } from '@wordpress/blocks'; @@ -102,7 +102,7 @@ class InnerBlocks extends Component { render() { const { - isSmallScreen, // Temporary click-through disable on desktop. + enableClickThrough, clientId, hasOverlay, renderAppender, @@ -117,7 +117,7 @@ class InnerBlocks extends Component { const isPlaceholder = template === null && !! templateOptions; const classes = classnames( 'editor-inner-blocks block-editor-inner-blocks', { - 'has-overlay': isSmallScreen && ( hasOverlay && ! isPlaceholder ), // Temporary click-through disable on desktop. + 'has-overlay': enableClickThrough && ( hasOverlay && ! isPlaceholder ), } ); return ( @@ -141,7 +141,7 @@ class InnerBlocks extends Component { } InnerBlocks = compose( [ - withViewportMatch( { isSmallScreen: '< medium' } ), // Temporary click-through disable on desktop. + withViewportMatch( { isSmallScreen: '< medium' } ), withBlockEditContext( ( context ) => pick( context, [ 'clientId' ] ) ), withSelect( ( select, ownProps ) => { const { @@ -151,8 +151,9 @@ InnerBlocks = compose( [ getBlockListSettings, getBlockRootClientId, getTemplateLock, + isNavigationMode, } = select( 'core/block-editor' ); - const { clientId } = ownProps; + const { clientId, isSmallScreen } = ownProps; const block = getBlock( clientId ); const rootClientId = getBlockRootClientId( clientId ); @@ -161,6 +162,7 @@ InnerBlocks = compose( [ blockListSettings: getBlockListSettings( clientId ), hasOverlay: block.name !== 'core/template' && ! isBlockSelected( clientId ) && ! hasSelectedInnerBlock( clientId, true ), parentLock: getTemplateLock( rootClientId ), + enableClickThrough: isNavigationMode() || isSmallScreen, }; } ), withDispatch( ( dispatch, ownProps ) => { diff --git a/packages/block-editor/src/components/tool-selector/index.js b/packages/block-editor/src/components/tool-selector/index.js new file mode 100644 index 0000000000000..9fc634f6e6104 --- /dev/null +++ b/packages/block-editor/src/components/tool-selector/index.js @@ -0,0 +1,76 @@ +/** + * WordPress dependencies + */ +import { + Dropdown, + IconButton, + MenuItemsChoice, + SVG, + Path, + NavigableMenu, +} from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { useSelect, useDispatch } from '@wordpress/data'; +import { ifViewportMatches } from '@wordpress/viewport'; + +const editIcon = ; +const selectIcon = ; + +function ToolSelector() { + const isNavigationTool = useSelect( ( select ) => select( 'core/block-editor' ).isNavigationMode() ); + const { setNavigationMode } = useDispatch( 'core/block-editor' ); + const onSwitchMode = ( mode ) => { + setNavigationMode( mode === 'edit' ? false : true ); + }; + + return ( + ( + + ) } + renderContent={ () => ( + <> + + + { editIcon } + { __( 'Edit' ) } + + ), + }, + { + value: 'select', + label: ( + <> + { selectIcon } + { __( 'Select' ) } + + ), + }, + ] } + /> + +
+ { __( 'Tools offer different interactions for block selection & editing. To select, press Escape, to go back to editing, press Enter.' ) } +
+ + ) } + /> + ); +} + +export default ifViewportMatches( 'medium' )( ToolSelector ); diff --git a/packages/block-editor/src/components/tool-selector/style.scss b/packages/block-editor/src/components/tool-selector/style.scss new file mode 100644 index 0000000000000..1f61a871dce89 --- /dev/null +++ b/packages/block-editor/src/components/tool-selector/style.scss @@ -0,0 +1,5 @@ +.block-editor-tool-selector__help { + padding: $grid-size-large; + border-top: 1px solid $light-gray-500; + color: $dark-gray-300; +} diff --git a/packages/block-editor/src/components/writing-flow/index.js b/packages/block-editor/src/components/writing-flow/index.js index 37e45dd2680d0..cd9355bcf2a36 100644 --- a/packages/block-editor/src/components/writing-flow/index.js +++ b/packages/block-editor/src/components/writing-flow/index.js @@ -104,13 +104,6 @@ class WritingFlow extends Component { onMouseDown() { this.verticalRect = null; - this.disableNavigationMode(); - } - - disableNavigationMode() { - if ( this.props.isNavigationMode ) { - this.props.disableNavigationMode(); - } } /** @@ -377,7 +370,6 @@ class WritingFlow extends Component { * Sets focus to the end of the last tabbable text field, if one exists. */ focusLastTextField() { - this.disableNavigationMode(); const focusableNodes = focus.focusable.find( this.container ); const target = findLast( focusableNodes, isTabbableTextField ); if ( target ) { @@ -445,11 +437,10 @@ export default compose( [ }; } ), withDispatch( ( dispatch ) => { - const { multiSelect, selectBlock, setNavigationMode, clearSelectedBlock } = dispatch( 'core/block-editor' ); + const { multiSelect, selectBlock, clearSelectedBlock } = dispatch( 'core/block-editor' ); return { onMultiSelect: multiSelect, onSelectBlock: selectBlock, - disableNavigationMode: () => setNavigationMode( false ), clearSelectedBlock, }; } ), diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index 6e71703578346..06ef92914ab81 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -7,6 +7,8 @@ import { castArray, first, get, includes } from 'lodash'; * WordPress dependencies */ import { getDefaultBlockName, createBlock } from '@wordpress/blocks'; +import { speak } from '@wordpress/a11y'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -793,15 +795,19 @@ export function __unstableMarkAutomaticChange() { } /** - * Returns an action object used to enable or disable the navigation mode. + * Generators that triggers an action used to enable or disable the navigation mode. * * @param {string} isNavigationMode Enable/Disable navigation mode. - * - * @return {Object} Action object */ -export function setNavigationMode( isNavigationMode = true ) { - return { +export function * setNavigationMode( isNavigationMode = true ) { + yield { type: 'SET_NAVIGATION_MODE', isNavigationMode, }; + + if ( isNavigationMode ) { + speak( __( 'You are currently in navigation mode. Navigate blocks using arrow keys. To exit navigation mode and edit the selected block, press Enter.' ) ); + } else { + speak( __( 'You are currently in edit mode. To return to the navigation mode, press Escape.' ) ); + } } diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index ac663d977e42b..d0e5d9e64dd02 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -1256,7 +1256,7 @@ export const blockListSettings = ( state = {}, action ) => { * * @return {string} Updated state. */ -export function isNavigationMode( state = true, action ) { +export function isNavigationMode( state = false, action ) { if ( action.type === 'SET_NAVIGATION_MODE' ) { return action.isNavigationMode; } diff --git a/packages/block-editor/src/style.scss b/packages/block-editor/src/style.scss index 3169be962d3b3..de5698f91de48 100644 --- a/packages/block-editor/src/style.scss +++ b/packages/block-editor/src/style.scss @@ -32,6 +32,7 @@ @import "./components/rich-text/format-toolbar/style.scss"; @import "./components/rich-text/style.scss"; @import "./components/skip-to-selected-block/style.scss"; +@import "./components/tool-selector/style.scss"; @import "./components/url-input/style.scss"; @import "./components/url-popover/style.scss"; @import "./components/warning/style.scss"; diff --git a/packages/components/src/menu-items-choice/index.js b/packages/components/src/menu-items-choice/index.js index 2311fd3a0435d..8412c64e4141f 100644 --- a/packages/components/src/menu-items-choice/index.js +++ b/packages/components/src/menu-items-choice/index.js @@ -17,6 +17,7 @@ export default function MenuItemsChoice( { icon={ isSelected && 'yes' } isSelected={ isSelected } shortcut={ item.shortcut } + className="components-menu-items-choice" onClick={ () => { if ( ! isSelected ) { onSelect( item.value ); diff --git a/packages/components/src/menu-items-choice/style.scss b/packages/components/src/menu-items-choice/style.scss new file mode 100644 index 0000000000000..2d933a77a13a9 --- /dev/null +++ b/packages/components/src/menu-items-choice/style.scss @@ -0,0 +1,12 @@ +.components-menu-items-choice, +.components-menu-items-choice.components-icon-button { + padding-left: 2rem; + + &.has-icon { + padding-left: 0.5rem; + } + + .dashicon { + margin-right: 4px; + } +} diff --git a/packages/components/src/style.scss b/packages/components/src/style.scss index dbc80b743351f..a21839bd27b3f 100644 --- a/packages/components/src/style.scss +++ b/packages/components/src/style.scss @@ -26,6 +26,7 @@ @import "./icon-button/style.scss"; @import "./menu-group/style.scss"; @import "./menu-item/style.scss"; +@import "./menu-items-choice/style.scss"; @import "./modal/style.scss"; @import "./notice/style.scss"; @import "./panel/style.scss"; diff --git a/packages/e2e-test-utils/CHANGELOG.md b/packages/e2e-test-utils/CHANGELOG.md index 8cbae26a2abc5..ccbbd0e96d218 100644 --- a/packages/e2e-test-utils/CHANGELOG.md +++ b/packages/e2e-test-utils/CHANGELOG.md @@ -1,3 +1,9 @@ +## master + +### Breaking Changes + +- The disableNavigationMode utility was removed. By default, the editor is in edit mode now. + ## 3.0.0 (2019-11-14) ### Breaking Changes diff --git a/packages/e2e-test-utils/README.md b/packages/e2e-test-utils/README.md index e01082057a82a..37d5f86d06cb9 100644 --- a/packages/e2e-test-utils/README.md +++ b/packages/e2e-test-utils/README.md @@ -137,14 +137,6 @@ _Parameters_ - _slug_ `string`: Plugin slug. -# **disableNavigationMode** - -Triggers edit mode if not already active. - -_Returns_ - -- `Promise`: Promise resolving after enabling the keyboard edit mode. - # **disablePrePublishChecks** Disables Pre-publish checks. diff --git a/packages/e2e-test-utils/src/create-new-post.js b/packages/e2e-test-utils/src/create-new-post.js index ddc2ad64ea6c1..91a95bf5216a4 100644 --- a/packages/e2e-test-utils/src/create-new-post.js +++ b/packages/e2e-test-utils/src/create-new-post.js @@ -7,7 +7,6 @@ import { addQueryArgs } from '@wordpress/url'; * Internal dependencies */ import { visitAdminPage } from './visit-admin-page'; -import { disableNavigationMode } from './keyboard-mode'; /** * Creates new post. @@ -37,6 +36,4 @@ export async function createNewPost( { if ( enableTips ) { await page.reload(); } - - await disableNavigationMode(); } diff --git a/packages/e2e-test-utils/src/index.js b/packages/e2e-test-utils/src/index.js index 40feec0101458..4d78447dec087 100644 --- a/packages/e2e-test-utils/src/index.js +++ b/packages/e2e-test-utils/src/index.js @@ -42,7 +42,6 @@ export { selectBlockByClientId } from './select-block-by-client-id'; export { setBrowserViewport } from './set-browser-viewport'; export { setPostContent } from './set-post-content'; export { switchEditorModeTo } from './switch-editor-mode-to'; -export { disableNavigationMode } from './keyboard-mode'; export { switchUserToAdmin } from './switch-user-to-admin'; export { switchUserToTest } from './switch-user-to-test'; export { toggleMoreMenu } from './toggle-more-menu'; diff --git a/packages/e2e-test-utils/src/keyboard-mode.js b/packages/e2e-test-utils/src/keyboard-mode.js index 8928c220b28f6..8b137891791fe 100644 --- a/packages/e2e-test-utils/src/keyboard-mode.js +++ b/packages/e2e-test-utils/src/keyboard-mode.js @@ -1,12 +1 @@ -/** - * Triggers edit mode if not already active. - * - * @return {Promise} Promise resolving after enabling the keyboard edit mode. - */ -export async function disableNavigationMode() { - const focusedElement = await page.$( ':focus' ); - await page.click( '.editor-post-title' ); - if ( focusedElement ) { - await focusedElement.focus(); - } -} + diff --git a/packages/e2e-tests/specs/editor/various/preview.test.js b/packages/e2e-tests/specs/editor/various/preview.test.js index 505f8cca3ba3a..7467a9382ae48 100644 --- a/packages/e2e-tests/specs/editor/various/preview.test.js +++ b/packages/e2e-tests/specs/editor/various/preview.test.js @@ -15,7 +15,6 @@ import { saveDraft, clickOnMoreMenuItem, pressKeyWithModifier, - disableNavigationMode, } from '@wordpress/e2e-test-utils'; async function openPreviewPage( editorPage ) { @@ -206,7 +205,6 @@ describe( 'Preview with Custom Fields enabled', () => { beforeEach( async () => { await createNewPost(); await toggleCustomFieldsOption( true ); - await disableNavigationMode(); } ); afterEach( async () => { diff --git a/packages/e2e-tests/specs/editor/various/reusable-blocks.test.js b/packages/e2e-tests/specs/editor/various/reusable-blocks.test.js index cfcd565254f2e..a160da7a4e789 100644 --- a/packages/e2e-tests/specs/editor/various/reusable-blocks.test.js +++ b/packages/e2e-tests/specs/editor/various/reusable-blocks.test.js @@ -118,6 +118,9 @@ describe( 'Reusable Blocks', () => { // Tab three times to navigate to the block's content await page.keyboard.press( 'Tab' ); await page.keyboard.press( 'Tab' ); + + // Quickly focus the paragraph block + await page.keyboard.press( 'Escape' ); // Enter navigation mode await page.keyboard.press( 'Enter' ); // Enter edit mode // Change the block's content diff --git a/packages/e2e-tests/specs/editor/various/undo.test.js b/packages/e2e-tests/specs/editor/various/undo.test.js index c8c1582eed989..7c1a2602d7bfe 100644 --- a/packages/e2e-tests/specs/editor/various/undo.test.js +++ b/packages/e2e-tests/specs/editor/various/undo.test.js @@ -10,7 +10,6 @@ import { getAllBlocks, saveDraft, publishPost, - disableNavigationMode, } from '@wordpress/e2e-test-utils'; const getSelection = async () => { @@ -331,7 +330,6 @@ describe( 'undo', () => { await page.keyboard.type( 'original' ); await saveDraft(); await page.reload(); - await disableNavigationMode(); // Issue is demonstrated by forcing state merges (multiple inputs) on // an existing text after a fresh reload. diff --git a/packages/e2e-tests/specs/performance/performance.test.js b/packages/e2e-tests/specs/performance/performance.test.js index 6246dfb4dc0d3..7f402dad605ca 100644 --- a/packages/e2e-tests/specs/performance/performance.test.js +++ b/packages/e2e-tests/specs/performance/performance.test.js @@ -11,7 +11,6 @@ import { createNewPost, saveDraft, insertBlock, - disableNavigationMode, } from '@wordpress/e2e-test-utils'; function readFile( filePath ) { @@ -54,7 +53,6 @@ describe( 'Performance', () => { while ( i-- ) { startTime = new Date(); await page.reload( { waitUntil: [ 'domcontentloaded', 'load' ] } ); - await disableNavigationMode(); } await insertBlock( 'Paragraph' ); diff --git a/packages/edit-post/src/components/header/header-toolbar/index.js b/packages/edit-post/src/components/header/header-toolbar/index.js index d02a82156fcfe..92b877e7626cf 100644 --- a/packages/edit-post/src/components/header/header-toolbar/index.js +++ b/packages/edit-post/src/components/header/header-toolbar/index.js @@ -11,6 +11,7 @@ import { BlockToolbar, NavigableToolbar, BlockNavigationDropdown, + ToolSelector, } from '@wordpress/block-editor'; import { TableOfContents, @@ -40,6 +41,7 @@ function HeaderToolbar( { hasFixedToolbar, isLargeViewport, showInserter, isText + { hasFixedToolbar && isLargeViewport && (