Skip to content

Commit

Permalink
List View: Allow Escape key to deselect blocks if blocks are selected (
Browse files Browse the repository at this point in the history
…#48708)

* List View: Allow Escape key to deselect blocks if blocks are selected

* Add comment, check which tab is active in post editor

* Add speak call, use clearSelectedBlock action

* Add behaviour to widgets editor, too

* Move clear selection handling down to the List View container so that if focus is on the close or tab buttons, Escape closes the list view instead of clearing

* Try selecting the last selected block when closing the list view if no blocks are selected

* Revert changes

* Try clearing the selection from within the list view

* Revert change

* Add test

* Fix issue where announcement for deselection was not occurring
  • Loading branch information
andrewserong committed Sep 5, 2023
1 parent b49f67b commit 7a4330d
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 33 deletions.
16 changes: 16 additions & 0 deletions packages/block-editor/src/components/list-view/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
import { useDispatch, useSelect } from '@wordpress/data';
import { sprintf, __ } from '@wordpress/i18n';
import { focus } from '@wordpress/dom';
import { ESCAPE } from '@wordpress/keycodes';

/**
* Internal dependencies
Expand Down Expand Up @@ -150,6 +151,20 @@ function ListViewBlock( {
}
}, [] );

// If multiple blocks are selected, deselect all blocks when the user
// presses the escape key.
const onKeyDown = ( event ) => {
if (
event.keyCode === ESCAPE &&
! event.defaultPrevented &&
selectedClientIds.length > 0
) {
event.stopPropagation();
event.preventDefault();
selectBlock( event, undefined );
}
};

const onMouseEnter = useCallback( () => {
setIsHovered( true );
toggleBlockHighlight( clientId, true );
Expand Down Expand Up @@ -257,6 +272,7 @@ function ListViewBlock( {
return (
<ListViewLeaf
className={ classes }
onKeyDown={ onKeyDown }
onMouseEnter={ onMouseEnter }
onMouseLeave={ onMouseLeave }
onFocus={ onMouseEnter }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { speak } from '@wordpress/a11y';
import { __, sprintf } from '@wordpress/i18n';
import { useDispatch, useSelect } from '@wordpress/data';
import { useCallback } from '@wordpress/element';
import { UP, DOWN, HOME, END } from '@wordpress/keycodes';
import { UP, DOWN, HOME, END, ESCAPE } from '@wordpress/keycodes';
import { store as blocksStore } from '@wordpress/blocks';

/**
Expand All @@ -30,7 +30,7 @@ export default function useBlockSelection() {

const updateBlockSelection = useCallback(
async ( event, clientId, destinationClientId, focusPosition ) => {
if ( ! event?.shiftKey ) {
if ( ! event?.shiftKey && event?.keyCode !== ESCAPE ) {
selectBlock( clientId, focusPosition );
return;
}
Expand All @@ -39,6 +39,8 @@ export default function useBlockSelection() {
// the browser default behavior of opening the link in a new window.
event.preventDefault();

const isOnlyDeselection =
event.type === 'keydown' && event.keyCode === ESCAPE;
const isKeyPress =
event.type === 'keydown' &&
( event.keyCode === UP ||
Expand All @@ -63,10 +65,11 @@ export default function useBlockSelection() {
];

if (
isKeyPress &&
! selectedBlocks.some( ( blockId ) =>
clientIdWithParents.includes( blockId )
)
isOnlyDeselection ||
( isKeyPress &&
! selectedBlocks.some( ( blockId ) =>
clientIdWithParents.includes( blockId )
) )
) {
// Ensure that shift-selecting blocks via the keyboard only
// expands the current selection if focusing over already
Expand All @@ -75,35 +78,38 @@ export default function useBlockSelection() {
await clearSelectedBlock();
}

let startTarget = getBlockSelectionStart();
let endTarget = clientId;

// Handle keyboard behavior for selecting multiple blocks.
if ( isKeyPress ) {
if ( ! hasSelectedBlock() && ! hasMultiSelection() ) {
// Set the starting point of the selection to the currently
// focused block, if there are no blocks currently selected.
// This ensures that as the selection is expanded or contracted,
// the starting point of the selection is anchored to that block.
startTarget = clientId;
// Update selection, if not only clearing the selection.
if ( ! isOnlyDeselection ) {
let startTarget = getBlockSelectionStart();
let endTarget = clientId;

// Handle keyboard behavior for selecting multiple blocks.
if ( isKeyPress ) {
if ( ! hasSelectedBlock() && ! hasMultiSelection() ) {
// Set the starting point of the selection to the currently
// focused block, if there are no blocks currently selected.
// This ensures that as the selection is expanded or contracted,
// the starting point of the selection is anchored to that block.
startTarget = clientId;
}
if ( destinationClientId ) {
// If the user presses UP or DOWN, we want to ensure that the block they're
// moving to is the target for selection, and not the currently focused one.
endTarget = destinationClientId;
}
}
if ( destinationClientId ) {
// If the user presses UP or DOWN, we want to ensure that the block they're
// moving to is the target for selection, and not the currently focused one.
endTarget = destinationClientId;
}
}

const startParents = getBlockParents( startTarget );
const endParents = getBlockParents( endTarget );
const startParents = getBlockParents( startTarget );
const endParents = getBlockParents( endTarget );

const { start, end } = getCommonDepthClientIds(
startTarget,
endTarget,
startParents,
endParents
);
await multiSelect( start, end, null );
const { start, end } = getCommonDepthClientIds(
startTarget,
endTarget,
startParents,
endParents
);
await multiSelect( start, end, null );
}

// Announce deselected block, or number of deselected blocks if
// the total number of blocks deselected is greater than one.
Expand Down
15 changes: 14 additions & 1 deletion test/e2e/specs/editor/various/list-view.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ test.describe( 'List View', () => {
).toBeFocused();
} );

test( 'should duplicate and delete blocks using keyboard', async ( {
test( 'should duplicate, delete, and deselect blocks using keyboard', async ( {
editor,
page,
pageUtils,
Expand Down Expand Up @@ -666,6 +666,19 @@ test.describe( 'List View', () => {
{ name: 'core/file', selected: false, focused: true },
] );
}

// Deselect blocks via Escape key.
await page.keyboard.press( 'Escape' );

await expect
.poll(
listViewUtils.getBlocksWithA11yAttributes,
'Pressing Escape should deselect blocks'
)
.toMatchObject( [
{ name: 'core/heading', selected: false, focused: false },
{ name: 'core/file', selected: false, focused: true },
] );
} );

test( 'block settings dropdown menu', async ( {
Expand Down

1 comment on commit 7a4330d

@github-actions
Copy link

@github-actions github-actions bot commented on 7a4330d Sep 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flaky tests detected in 7a4330d.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/6078728815
📝 Reported issues:

Please sign in to comment.