) }
diff --git a/packages/block-editor/src/components/list-view/branch.js b/packages/block-editor/src/components/list-view/branch.js
index ccc0010b96a05..8f6d71b3683bc 100644
--- a/packages/block-editor/src/components/list-view/branch.js
+++ b/packages/block-editor/src/components/list-view/branch.js
@@ -25,16 +25,13 @@ export default function ListViewBranch( props ) {
showNestedBlocks,
parentBlockClientId,
level = 1,
- terminatedLevels = [],
- path = [],
+ path = '',
isBranchSelected = false,
isLastOfBranch = false,
} = props;
const {
expandedState,
- expand,
- collapse,
draggedClientIds,
selectedClientIds,
} = useListViewContext();
@@ -56,11 +53,12 @@ export default function ListViewBranch( props ) {
{ map( filteredBlocks, ( block, index ) => {
const { clientId, innerBlocks } = block;
const position = index + 1;
- const isLastRowAtLevel = rowCount === position;
- const updatedTerminatedLevels = isLastRowAtLevel
- ? [ ...terminatedLevels, level ]
- : terminatedLevels;
- const updatedPath = [ ...path, position ];
+ // If the string value changes, it's used to trigger an animation change.
+ // This may be removed if we use a different animation library in the future.
+ const updatedPath =
+ path.length > 0
+ ? `${ path }_${ position }`
+ : `${ position }`;
const hasNestedBlocks =
showNestedBlocks && !! innerBlocks && !! innerBlocks.length;
const hasNestedAppender = itemHasAppender( clientId );
@@ -84,20 +82,6 @@ export default function ListViewBranch( props ) {
? expandedState[ clientId ] ?? true
: undefined;
- const selectBlockWithClientId = ( event ) => {
- event.stopPropagation();
- selectBlock( clientId );
- };
-
- const toggleExpanded = ( event ) => {
- event.stopPropagation();
- if ( isExpanded === true ) {
- collapse( clientId );
- } else if ( isExpanded === false ) {
- expand( clientId );
- }
- };
-
// Make updates to the selected or dragged blocks synchronous,
// but asynchronous for any other block.
const isDragged = !! draggedClientIds?.includes( clientId );
@@ -106,8 +90,7 @@ export default function ListViewBranch( props ) {
@@ -132,7 +114,6 @@ export default function ListViewBranch( props ) {
showNestedBlocks={ showNestedBlocks }
parentBlockClientId={ clientId }
level={ level + 1 }
- terminatedLevels={ updatedTerminatedLevels }
path={ updatedPath }
/>
) }
@@ -145,8 +126,11 @@ export default function ListViewBranch( props ) {
position={ rowCount }
rowCount={ appenderPosition }
level={ level }
- terminatedLevels={ terminatedLevels }
- path={ [ ...path, appenderPosition ] }
+ path={
+ path.length > 0
+ ? `${ path }_${ appenderPosition }`
+ : `${ appenderPosition }`
+ }
/>
) }
>
diff --git a/packages/block-editor/src/components/list-view/leaf.js b/packages/block-editor/src/components/list-view/leaf.js
index 8098d44647fc9..41bf4bc34cc66 100644
--- a/packages/block-editor/src/components/list-view/leaf.js
+++ b/packages/block-editor/src/components/list-view/leaf.js
@@ -30,7 +30,7 @@ export default function ListViewLeaf( {
isSelected,
adjustScrolling: false,
enableAnimation: true,
- triggerAnimationOnChange: path.join( '_' ),
+ triggerAnimationOnChange: path,
} );
return (
diff --git a/packages/components/src/tree-grid/roving-tab-index-item.js b/packages/components/src/tree-grid/roving-tab-index-item.js
index ef9a28cf87e29..af0e095cfb939 100644
--- a/packages/components/src/tree-grid/roving-tab-index-item.js
+++ b/packages/components/src/tree-grid/roving-tab-index-item.js
@@ -1,7 +1,7 @@
/**
* WordPress dependencies
*/
-import { useRef, forwardRef } from '@wordpress/element';
+import { useRef, forwardRef, useCallback } from '@wordpress/element';
/**
* Internal dependencies
@@ -24,7 +24,10 @@ export default forwardRef( function RovingTabIndexItem(
tabIndex = lastFocusedElement === ref.current ? 0 : -1;
}
- const onFocus = ( event ) => setLastFocusedElement( event.target );
+ const onFocus = useCallback(
+ ( event ) => setLastFocusedElement( event.target ),
+ [ setLastFocusedElement ]
+ );
const allProps = { ref, tabIndex, onFocus, ...props };
if ( typeof children === 'function' ) {
diff --git a/packages/e2e-test-utils/README.md b/packages/e2e-test-utils/README.md
index aa7d460dac56d..2e29a1b8475bd 100644
--- a/packages/e2e-test-utils/README.md
+++ b/packages/e2e-test-utils/README.md
@@ -111,6 +111,10 @@ _Parameters_
Undocumented declaration.
+### closeListView
+
+Closes list view
+
### createEmbeddingMatcher
Creates a function to determine if a request is embedding a certain URL.
@@ -505,6 +509,10 @@ Clicks on the button in the header which opens Document Settings sidebar when it
Opens the global block inserter.
+### openListView
+
+Opens list view
+
### openPreviewPage
Opens the preview page of an edited post.
diff --git a/packages/e2e-test-utils/src/index.js b/packages/e2e-test-utils/src/index.js
index b0613bc3a7d41..6901625577e96 100644
--- a/packages/e2e-test-utils/src/index.js
+++ b/packages/e2e-test-utils/src/index.js
@@ -90,5 +90,6 @@ export {
rest as __experimentalRest,
batch as __experimentalBatch,
} from './rest-api';
+export { openListView, closeListView } from './list-view';
export * from './mocks';
diff --git a/packages/e2e-test-utils/src/list-view.js b/packages/e2e-test-utils/src/list-view.js
new file mode 100644
index 0000000000000..03121c5f84af7
--- /dev/null
+++ b/packages/e2e-test-utils/src/list-view.js
@@ -0,0 +1,33 @@
+async function toggleListView() {
+ await page.click(
+ '.edit-post-header-toolbar__list-view-toggle, .edit-site-header-toolbar__list-view-toggle'
+ );
+}
+
+async function isListViewOpen() {
+ return await page.evaluate( () => {
+ return !! document.querySelector(
+ '.edit-post-header-toolbar__list-view-toggle.is-pressed, .edit-site-header-toolbar__list-view-toggle.is-pressed'
+ );
+ } );
+}
+
+/**
+ * Opens list view
+ */
+export async function openListView() {
+ const isOpen = await isListViewOpen();
+ if ( ! isOpen ) {
+ await toggleListView();
+ }
+}
+
+/**
+ * Closes list view
+ */
+export async function closeListView() {
+ const isOpen = await isListViewOpen();
+ if ( isOpen ) {
+ await toggleListView();
+ }
+}
diff --git a/packages/e2e-tests/config/performance-reporter.js b/packages/e2e-tests/config/performance-reporter.js
index 6c314917f8ac2..549855bf29713 100644
--- a/packages/e2e-tests/config/performance-reporter.js
+++ b/packages/e2e-tests/config/performance-reporter.js
@@ -37,6 +37,7 @@ class PerformanceReporter {
firstBlock,
type,
focus,
+ listViewOpen,
inserterOpen,
inserterHover,
inserterSearch,
@@ -90,6 +91,21 @@ Fastest time to select a block: ${ success(
) }` );
}
+ if ( listViewOpen && listViewOpen.length ) {
+ // eslint-disable-next-line no-console
+ console.log( `
+${ title( 'Opening List View Performance:' ) }
+Average time to open list view: ${ success(
+ round( average( listViewOpen ) ) + 'ms'
+ ) }
+Slowest time to open list view: ${ success(
+ round( Math.max( ...listViewOpen ) ) + 'ms'
+ ) }
+Fastest time to open list view: ${ success(
+ round( Math.min( ...listViewOpen ) ) + 'ms'
+ ) }` );
+ }
+
if ( inserterOpen && inserterOpen.length ) {
// eslint-disable-next-line no-console
console.log( `
diff --git a/packages/e2e-tests/specs/performance/post-editor.test.js b/packages/e2e-tests/specs/performance/post-editor.test.js
index f9862f18c9448..fa1893923a29f 100644
--- a/packages/e2e-tests/specs/performance/post-editor.test.js
+++ b/packages/e2e-tests/specs/performance/post-editor.test.js
@@ -11,9 +11,10 @@ import { sum } from 'lodash';
import {
createNewPost,
saveDraft,
- insertBlock,
openGlobalBlockInserter,
closeGlobalBlockInserter,
+ openListView,
+ closeListView,
} from '@wordpress/e2e-test-utils';
/**
@@ -41,6 +42,7 @@ describe( 'Post Editor Performance', () => {
firstBlock: [],
type: [],
focus: [],
+ listViewOpen: [],
inserterOpen: [],
inserterHover: [],
inserterSearch: [],
@@ -118,7 +120,9 @@ describe( 'Post Editor Performance', () => {
it( 'Typing', async () => {
// Measuring typing performance
- await insertBlock( 'Paragraph' );
+ await openListView();
+ await page.click( '.edit-post-visual-editor__post-title-wrapper' );
+ await page.keyboard.press( 'Enter' );
let i = 20;
await page.tracing.start( {
path: traceFile,
@@ -157,6 +161,7 @@ describe( 'Post Editor Performance', () => {
it( 'Selecting blocks', async () => {
// Measuring block selection performance
await createNewPost();
+ await openListView();
await page.evaluate( () => {
const { createBlock } = window.wp.blocks;
const { dispatch } = window.wp.data;
@@ -184,6 +189,26 @@ describe( 'Post Editor Performance', () => {
results.focus = focusEvents;
} );
+ it( 'Opening persistent list view', async () => {
+ // Measure time to open inserter
+ await page.waitForSelector( '.edit-post-layout' );
+ for ( let j = 0; j < 10; j++ ) {
+ await page.tracing.start( {
+ path: traceFile,
+ screenshots: false,
+ categories: [ 'devtools.timeline' ],
+ } );
+ await openListView();
+ await page.tracing.stop();
+ traceResults = JSON.parse( readFile( traceFile ) );
+ const [ mouseClickEvents ] = getClickEventDurations( traceResults );
+ for ( let k = 0; k < mouseClickEvents.length; k++ ) {
+ results.listViewOpen.push( mouseClickEvents[ k ] );
+ }
+ await closeListView();
+ }
+ } );
+
it( 'Opening the inserter', async () => {
// Measure time to open inserter
await page.waitForSelector( '.edit-post-layout' );
diff --git a/packages/e2e-tests/specs/performance/site-editor.test.js b/packages/e2e-tests/specs/performance/site-editor.test.js
index 80fa8cecc3c95..0b7196fb805dc 100644
--- a/packages/e2e-tests/specs/performance/site-editor.test.js
+++ b/packages/e2e-tests/specs/performance/site-editor.test.js
@@ -13,7 +13,7 @@ import {
canvas,
createNewPost,
saveDraft,
- insertBlock,
+ openListView,
} from '@wordpress/e2e-test-utils';
/**
@@ -55,6 +55,7 @@ describe( 'Site Editor Performance', () => {
inserterOpen: [],
inserterHover: [],
inserterSearch: [],
+ listViewOpen: [],
};
const html = readFile(
@@ -117,7 +118,13 @@ describe( 'Site Editor Performance', () => {
await canvas().click(
'[data-type="core/post-content"] [data-type="core/paragraph"]'
);
- await insertBlock( 'Paragraph' );
+ await openListView();
+ await canvas().click(
+ '[data-type="core/post-content"] [data-type="core/paragraph"]'
+ );
+ await page.keyboard.press( 'Enter' );
+ await page.keyboard.press( 'Enter' );
+ await page.keyboard.press( 'ArrowUp' );
i = 200;
const traceFile = __dirname + '/trace.json';
await page.tracing.start( {