Skip to content

Commit

Permalink
Try/expand block list tree on selection (#35817)
Browse files Browse the repository at this point in the history
* Check element ref for active document so we can try to expand the list only when a block is selected outside the block list.
Using an `useEffect` to loop through parent nodes, and expand them when necessary.

* Renamed parent client id array to `selectedBlockParentClientIds`

* Creating a new action type, so we can update the state with one action call.

* Refactoring reducer to accept an array of clientIds.

* Only try to expand nested branch items where there are parent ids

* This commit can potentially be discarded as it might be worth exploring in a new PR.
Here we're calculating the top scroll position of the selected block.

* Tracking the selected block in the tree and checking it against the selected block *should* inform us that a block has been selected elsewhere, e.g., the editor.
When we know this we can execute the hook logic that expands and scrolls to the selected element in the tree if a block is selected elsewhere.
Removing hasFocus.

* Extracted scroll and expand logic to hook

* Revert scroll to logic to be performed in another PR.

* Revert export

* Adding e2e test

* Forgot to pass on the correct args to `updateBlockSelection()`

* Focussing on the cover block before testing the expand element.

* Renaming function and file name to make it clearer to folks what it does.

* Linto!
  • Loading branch information
ramonjd authored Feb 21, 2022
1 parent b44f513 commit 6a72d6c
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 11 deletions.
41 changes: 30 additions & 11 deletions packages/block-editor/src/components/list-view/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,27 @@ import ListViewDropIndicator from './drop-indicator';
import useBlockSelection from './use-block-selection';
import useListViewClientIds from './use-list-view-client-ids';
import useListViewDropZone from './use-list-view-drop-zone';
import useListViewExpandSelectedItem from './use-list-view-expand-selected-item';
import { store as blockEditorStore } from '../../store';

const expanded = ( state, action ) => {
switch ( action.type ) {
case 'expand':
return { ...state, ...{ [ action.clientId ]: true } };
case 'collapse':
return { ...state, ...{ [ action.clientId ]: false } };
default:
return state;
if ( Array.isArray( action.clientIds ) ) {
return {
...state,
...action.clientIds.reduce(
( newState, id ) => ( {
...newState,
[ id ]: action.type === 'expand',
} ),
{}
),
};
}
return state;
};

export const BLOCK_LIST_ITEM_HEIGHT = 36;

/**
* Wrap `ListViewRows` with `TreeGrid`. ListViewRows is a
* recursive component (it renders itself), so this ensures TreeGrid is only
Expand Down Expand Up @@ -96,6 +104,17 @@ function ListView(
const treeGridRef = useMergeRefs( [ elementRef, dropZoneRef, ref ] );

const isMounted = useRef( false );
const { setSelectedTreeId } = useListViewExpandSelectedItem( {
firstSelectedBlockClientId: selectedClientIds[ 0 ],
setExpandedState,
} );
const selectEditorBlock = useCallback(
( event, clientId ) => {
updateBlockSelection( event, clientId );
setSelectedTreeId( clientId );
},
[ setSelectedTreeId, updateBlockSelection ]
);
useEffect( () => {
isMounted.current = true;
}, [] );
Expand All @@ -105,7 +124,7 @@ function ListView(
// See: https://github.com/WordPress/gutenberg/pull/35230 for additional context.
const [ fixedListWindow ] = useFixedWindowList(
elementRef,
36,
BLOCK_LIST_ITEM_HEIGHT,
visibleBlockCount,
{
useWindowing: __experimentalPersistentListViewFeatures,
Expand All @@ -118,7 +137,7 @@ function ListView(
if ( ! clientId ) {
return;
}
setExpandedState( { type: 'expand', clientId } );
setExpandedState( { type: 'expand', clientIds: [ clientId ] } );
},
[ setExpandedState ]
);
Expand All @@ -127,7 +146,7 @@ function ListView(
if ( ! clientId ) {
return;
}
setExpandedState( { type: 'collapse', clientId } );
setExpandedState( { type: 'collapse', clientIds: [ clientId ] } );
},
[ setExpandedState ]
);
Expand Down Expand Up @@ -196,7 +215,7 @@ function ListView(
<ListViewContext.Provider value={ contextValue }>
<ListViewBranch
blocks={ clientIdsTree }
selectBlock={ updateBlockSelection }
selectBlock={ selectEditorBlock }
showNestedBlocks={ showNestedBlocks }
showBlockMovers={ showBlockMovers }
fixedListWindow={ fixedListWindow }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* WordPress dependencies
*/
import { useEffect, useState } from '@wordpress/element';
import { useSelect } from '@wordpress/data';

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

export default function useListViewExpandSelectedItem( {
firstSelectedBlockClientId,
setExpandedState,
} ) {
const [ selectedTreeId, setSelectedTreeId ] = useState( null );
const { selectedBlockParentClientIds } = useSelect(
( select ) => {
const { getBlockParents } = select( blockEditorStore );
return {
selectedBlockParentClientIds: getBlockParents(
firstSelectedBlockClientId,
false
),
};
},
[ firstSelectedBlockClientId ]
);

const parentClientIds =
Array.isArray( selectedBlockParentClientIds ) &&
selectedBlockParentClientIds.length
? selectedBlockParentClientIds
: null;

// Expand tree when a block is selected.
useEffect( () => {
// If the selectedTreeId is the same as the selected block,
// it means that the block was selected using the block list tree.
if ( selectedTreeId === firstSelectedBlockClientId ) {
return;
}

// If the selected block has parents, get the top-level parent.
if ( parentClientIds ) {
// If the selected block has parents,
// expand the tree branch.
setExpandedState( {
type: 'expand',
clientIds: selectedBlockParentClientIds,
} );
}
}, [ firstSelectedBlockClientId ] );

return {
setSelectedTreeId,
};
}
52 changes: 52 additions & 0 deletions packages/e2e-tests/specs/editor/various/list-view.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
createNewPost,
insertBlock,
getEditedPostContent,
openListView,
pressKeyWithModifier,
pressKeyTimes,
} from '@wordpress/e2e-test-utils';
Expand All @@ -20,6 +21,10 @@ async function dragAndDrop( draggableElement, targetElement, offsetY ) {
return await page.mouse.dragAndDrop( draggablePoint, targetPoint );
}

async function getBlockListLeafNodes() {
return await page.$$( '.block-editor-list-view-leaf' );
}

describe( 'List view', () => {
beforeAll( async () => {
await page.setDragInterception( true );
Expand Down Expand Up @@ -97,4 +102,51 @@ describe( 'List view', () => {
// https://github.com/WordPress/gutenberg/issues/38763.
expect( console ).not.toHaveErrored();
} );

it( 'should expand nested list items', async () => {
// Insert some blocks of different types.
await insertBlock( 'Cover' );

// Click first color option from the block placeholder's color picker to make the inner blocks appear.
const colorPickerButton = await page.waitForSelector(
'.wp-block-cover__placeholder-background-options .components-circular-option-picker__option-wrapper:first-child button'
);
await colorPickerButton.click();

// Open list view.
await openListView();

// Things start off expanded.
expect( await getBlockListLeafNodes() ).toHaveLength( 2 );

const blockListExpanders = await page.$$(
'.block-editor-list-view__expander'
);

// Collapse the first block
await blockListExpanders[ 0 ].click();

// Check that we're collapsed
expect( await getBlockListLeafNodes() ).toHaveLength( 1 );

// Focus the cover block. The paragraph is not focussed by default.
const coverBlock = await page.waitForSelector( '.wp-block-cover' );

await coverBlock.focus();

// Click the cover title placeholder.
const coverTitle = await page.waitForSelector(
'.wp-block-cover .wp-block-paragraph'
);

await coverTitle.click();

// The block list should contain two leafs and the second should be selected (and be a paragraph).
const selectedElementText = await page.$eval(
'.block-editor-list-view-leaf.is-selected .block-editor-list-view-block-contents',
( element ) => element.innerText
);

expect( selectedElementText ).toContain( 'Paragraph' );
} );
} );

0 comments on commit 6a72d6c

Please sign in to comment.