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

List View: Add keyboard shortcut to collapse list view items other than the focused item #59978

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion packages/block-editor/src/components/block-tools/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* WordPress dependencies
*/
import { useSelect, useDispatch } from '@wordpress/data';
import { isTextField } from '@wordpress/dom';
import { Popover } from '@wordpress/components';
import { __unstableUseShortcutEventMatch as useShortcutEventMatch } from '@wordpress/keyboard-shortcuts';
import { useRef } from '@wordpress/element';
Expand All @@ -20,6 +21,7 @@ import { store as blockEditorStore } from '../../store';
import usePopoverScroll from '../block-popover/use-popover-scroll';
import ZoomOutModeInserters from './zoom-out-mode-inserters';
import { useShowBlockTools } from './use-show-block-tools';
import { unlock } from '../../lock-unlock';

function selector( select ) {
const {
Expand Down Expand Up @@ -79,7 +81,8 @@ export default function BlockTools( {
selectBlock,
moveBlocksUp,
moveBlocksDown,
} = useDispatch( blockEditorStore );
expandBlock,
} = unlock( useDispatch( blockEditorStore ) );

function onKeyDown( event ) {
if ( event.defaultPrevented ) return;
Expand Down Expand Up @@ -140,6 +143,20 @@ export default function BlockTools( {
// In effect, to the user this feels like deselecting the multi-selection.
selectBlock( clientIds[ 0 ] );
}
} else if ( isMatch( 'core/block-editor/collapse-list-view', event ) ) {
// If focus is currently within a text field, such as a rich text block or other editable field,
// skip collapsing the list view, and allow the keyboard shortcut to be handled by the text field.
// This condition checks for both the active element and the active element within an iframed editor.
if (
isTextField( event.target ) ||
isTextField(
event.target?.contentWindow?.document?.activeElement
)
) {
return;
}
event.preventDefault();
expandBlock( clientId );
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,17 @@ function KeyboardShortcutsRegister() {
character: 'y',
},
} );

// List view shortcuts.
registerShortcut( {
name: 'core/block-editor/collapse-list-view',
category: 'list-view',
description: __( 'Collapse all other items.' ),
keyCombination: {
modifier: 'alt',
character: 'l',
},
} );
}, [ registerShortcut ] );

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ function ListViewBlockSelectButton(
getPreviousBlockClientId,
getBlockRootClientId,
getBlockOrder,
getBlockParents,
getBlocksByClientId,
canRemoveBlocks,
} = useSelect( blockEditorStore );
Expand All @@ -73,7 +74,7 @@ function ListViewBlockSelectButton(
const isMatch = useShortcutEventMatch();
const isSticky = blockInformation?.positionType === 'sticky';
const images = useListViewImages( { clientId, isExpanded } );
const { rootClientId } = useListViewContext();
const { collapseAll, expand, rootClientId } = useListViewContext();

const positionLabel = blockInformation?.positionLabel
? sprintf(
Expand Down Expand Up @@ -228,6 +229,17 @@ function ListViewBlockSelectButton(
blockClientIds[ blockClientIds.length - 1 ],
null
);
} else if ( isMatch( 'core/block-editor/collapse-list-view', event ) ) {
if ( event.defaultPrevented ) {
return;
}
event.preventDefault();
const { firstBlockClientId } = getBlocksToUpdate();
const blockParents = getBlockParents( firstBlockClientId, false );
// Collapse all blocks.
collapseAll();
// Expand all parents of the current block.
expand( blockParents );
}
}

Expand Down
19 changes: 18 additions & 1 deletion packages/block-editor/src/components/list-view/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import ListViewDropIndicatorPreview from './drop-indicator';
import useBlockSelection from './use-block-selection';
import useListViewBlockIndexes from './use-list-view-block-indexes';
import useListViewClientIds from './use-list-view-client-ids';
import useListViewCollapseItems from './use-list-view-collapse-items';
import useListViewDropZone from './use-list-view-drop-zone';
import useListViewExpandSelectedItem from './use-list-view-expand-selected-item';
import { store as blockEditorStore } from '../../store';
Expand All @@ -45,6 +46,9 @@ import { focusListItem } from './utils';
import useClipboardHandler from './use-clipboard-handler';

const expanded = ( state, action ) => {
if ( action.type === 'clear' ) {
return {};
}
if ( Array.isArray( action.clientIds ) ) {
return {
...state,
Expand Down Expand Up @@ -194,7 +198,10 @@ function ListViewComponent(
if ( ! clientId ) {
return;
}
setExpandedState( { type: 'expand', clientIds: [ clientId ] } );
const clientIds = Array.isArray( clientId )
? clientId
: [ clientId ];
setExpandedState( { type: 'expand', clientIds } );
},
[ setExpandedState ]
);
Expand All @@ -207,6 +214,9 @@ function ListViewComponent(
},
[ setExpandedState ]
);
const collapseAll = useCallback( () => {
setExpandedState( { type: 'clear' } );
}, [ setExpandedState ] );
const expandRow = useCallback(
( row ) => {
expand( row?.dataset?.block );
Expand All @@ -232,6 +242,11 @@ function ListViewComponent(
[ updateBlockSelection ]
);

useListViewCollapseItems( {
collapseAll,
expand,
} );

const firstDraggedBlockClientId = draggedClientIds?.[ 0 ];

// Convert a blockDropTarget into indexes relative to the blocks in the list view.
Expand Down Expand Up @@ -282,6 +297,7 @@ function ListViewComponent(
expand,
firstDraggedBlockIndex,
collapse,
collapseAll,
BlockSettingsMenu,
listViewInstanceId: instanceId,
AdditionalBlockContent,
Expand All @@ -299,6 +315,7 @@ function ListViewComponent(
expand,
firstDraggedBlockIndex,
collapse,
collapseAll,
BlockSettingsMenu,
instanceId,
AdditionalBlockContent,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* WordPress dependencies
*/
import { useEffect } from '@wordpress/element';
import { useSelect } from '@wordpress/data';

/**
* Internal dependencies
*/
import { store as blockEditorStore } from '../../store';
import { unlock } from '../../lock-unlock';

export default function useListViewCollapseItems( { collapseAll, expand } ) {
const { expandedBlock, getBlockParents } = useSelect( ( select ) => {
const { getBlockParents: _getBlockParents, getExpandedBlock } = unlock(
select( blockEditorStore )
);
return {
expandedBlock: getExpandedBlock(),
getBlockParents: _getBlockParents,
};
}, [] );

// Collapse all but the specified block when the expanded block client Id changes.
useEffect( () => {
if ( expandedBlock ) {
const blockParents = getBlockParents( expandedBlock, false );
// Collapse all blocks and expand the block's parents.
collapseAll();
expand( blockParents );
}
}, [ collapseAll, expand, expandedBlock, getBlockParents ] );
}
12 changes: 12 additions & 0 deletions packages/block-editor/src/store/private-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -376,3 +376,15 @@ export function stopDragging() {
type: 'STOP_DRAGGING',
};
}

/**
* @param {string|null} clientId The block's clientId, or `null` to clear.
*
* @return {Object} Action object.
*/
export function expandBlock( clientId ) {
return {
type: 'SET_BLOCK_EXPANDED_IN_LIST_VIEW',
clientId,
};
}
11 changes: 11 additions & 0 deletions packages/block-editor/src/store/private-selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -353,3 +353,14 @@ export function getLastFocus( state ) {
export function isDragging( state ) {
return state.isDragging;
}

/**
* Retrieves the expanded block from the state.
*
* @param {Object} state Block editor state.
*
* @return {string|null} The client ID of the expanded block, if set.
*/
export function getExpandedBlock( state ) {
return state.expandedBlock;
}
22 changes: 22 additions & 0 deletions packages/block-editor/src/store/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -1889,6 +1889,27 @@ export function highlightedBlock( state, action ) {
return state;
}

/**
* Reducer returning current expanded block in the list view.
*
* @param {string|null} state Current expanded block.
* @param {Object} action Dispatched action.
*
* @return {string|null} Updated state.
*/
export function expandedBlock( state = null, action ) {
switch ( action.type ) {
case 'SET_BLOCK_EXPANDED_IN_LIST_VIEW':
return action.clientId;
case 'SELECT_BLOCK':
if ( action.clientId !== state ) {
return null;
}
}

return state;
}

/**
* Reducer returning the block insertion event list state.
*
Expand Down Expand Up @@ -2064,6 +2085,7 @@ const combinedReducers = combineReducers( {
lastFocus,
editorMode,
hasBlockMovingClientId,
expandedBlock,
highlightedBlock,
lastBlockInserted,
temporarilyEditingAsBlocks,
Expand Down
10 changes: 10 additions & 0 deletions packages/block-editor/src/store/test/private-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import {
hideBlockInterface,
showBlockInterface,
expandBlock,
__experimentalUpdateSettings,
setOpenedBlockSettingsMenu,
startDragging,
Expand Down Expand Up @@ -113,4 +114,13 @@ describe( 'private actions', () => {
} );
} );
} );

describe( 'expandBlock', () => {
it( 'should return the SET_BLOCK_EXPANDED_IN_LIST_VIEW action', () => {
expect( expandBlock( 'block-1' ) ).toEqual( {
type: 'SET_BLOCK_EXPANDED_IN_LIST_VIEW',
clientId: 'block-1',
} );
} );
} );
} );
13 changes: 13 additions & 0 deletions packages/block-editor/src/store/test/private-selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
isBlockSubtreeDisabled,
getEnabledClientIdsTree,
getEnabledBlockParents,
getExpandedBlock,
isDragging,
} from '../private-selectors';
import { getBlockEditingMode } from '../selectors';
Expand Down Expand Up @@ -496,4 +497,16 @@ describe( 'private selectors', () => {
expect( isDragging( state ) ).toBe( false );
} );
} );

describe( 'getExpandedBlock', () => {
it( 'should return the expanded block', () => {
const state = {
expandedBlock: '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f',
};

expect( getExpandedBlock( state ) ).toBe(
'9b9c5c3f-2e46-4f02-9e14-9fe9515b958f'
);
} );
} );
} );
26 changes: 26 additions & 0 deletions packages/block-editor/src/store/test/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
lastBlockInserted,
blockEditingModes,
openedBlockSettingsMenu,
expandedBlock,
} from '../reducer';

const noop = () => {};
Expand Down Expand Up @@ -3459,4 +3460,29 @@ describe( 'state', () => {
expect( state ).toBe( null );
} );
} );

describe( 'expandedBlock', () => {
it( 'should return null by default', () => {
expect( expandedBlock( undefined, {} ) ).toBe( null );
} );

it( 'should set client id for expanded block', () => {
const state = expandedBlock( null, {
type: 'SET_BLOCK_EXPANDED_IN_LIST_VIEW',
clientId: '14501cc2-90a6-4f52-aa36-ab6e896135d1',
} );
expect( state ).toBe( '14501cc2-90a6-4f52-aa36-ab6e896135d1' );
} );

it( 'should clear the state when a block is selected', () => {
const state = expandedBlock(
'14501cc2-90a6-4f52-aa36-ab6e896135d1',
{
type: 'SELECT_BLOCK',
clientId: 'a-different-block',
}
);
expect( state ).toBe( null );
} );
} );
} );
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ export function KeyboardShortcutHelpModal( { isModalActive, toggleModal } ) {
title={ __( 'Text formatting' ) }
shortcuts={ textFormattingShortcuts }
/>
<ShortcutCategorySection
title={ __( 'List View shortcuts' ) }
categoryName="list-view"
/>
</Modal>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,10 @@ export default function KeyboardShortcutHelpModal() {
title={ __( 'Text formatting' ) }
shortcuts={ textFormattingShortcuts }
/>
<ShortcutCategorySection
title={ __( 'List View shortcuts' ) }
categoryName="list-view"
/>
</Modal>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ export default function KeyboardShortcutHelpModal( {
title={ __( 'Text formatting' ) }
shortcuts={ textFormattingShortcuts }
/>
<ShortcutCategorySection
title={ __( 'List View shortcuts' ) }
categoryName="list-view"
/>
</Modal>
);
}
Loading
Loading