Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
5c390ba
List View: Don’t focus the last Table cell on keyboard activation
shail-mehta Aug 23, 2026
d0de0f2
Added Changelog Entry
shail-mehta Aug 23, 2026
7ee2897
fix lint
shail-mehta Aug 23, 2026
e6b987e
Merge branch 'trunk' into fix/list-view-table-keyboard-focus
shail-mehta Aug 24, 2026
87e58c5
Apply Feedback Changes
shail-mehta Aug 24, 2026
84f2c33
Merge branch 'trunk' into fix/list-view-table-keyboard-focus
shail-mehta Aug 26, 2026
cf0678a
Reverted the List View change to place the caret at the end of the bl…
shail-mehta Aug 26, 2026
b4e04cc
Reverted Test Changes
shail-mehta Aug 26, 2026
15c86dd
Reverted Test Changes
shail-mehta Aug 26, 2026
05d853e
Apply Feedback changes
shail-mehta Aug 26, 2026
c7bd916
Merge branch 'trunk' into fix/list-view-table-keyboard-focus
shail-mehta Aug 26, 2026
fde8a73
Merge branch 'trunk' into fix/list-view-table-keyboard-focus
shail-mehta Aug 26, 2026
f7027ac
Merge branch 'trunk' into fix/list-view-table-keyboard-focus
shail-mehta Aug 27, 2026
7b38686
Check Conflict
shail-mehta Aug 27, 2026
562bdfd
Check Conflict
shail-mehta Aug 27, 2026
16a8cc2
Merge branch 'trunk' into fix/list-view-table-keyboard-focus
shail-mehta Aug 27, 2026
9a59c90
Reverted missing test files changes
shail-mehta Aug 27, 2026
9dcdc7e
Merge branch 'trunk' into fix/list-view-table-keyboard-focus
shail-mehta Aug 27, 2026
83daff9
Change caret placement test from end to start
shail-mehta Aug 28, 2026
b5dcec3
Merge branch 'trunk' into fix/list-view-table-keyboard-focus
shail-mehta Aug 28, 2026
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
1 change: 1 addition & 0 deletions packages/block-editor/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
- `useInsertionPoint`: Leave the insertion cue alone when it belongs to the in-between inserter. The cue is shared state and the in-between inserter mounts inside its popover, so the sidebar inserter hiding it tore down the inline inserter that had just been opened ([#76241](https://github.com/WordPress/gutenberg/pull/76241)).
- `BorderPanel`: Match a chosen drop shadow against the presets from every origin rather than the first origin that defines any, so theme and default presets keep being stored as `var:preset|shadow|<slug>` once a custom preset exists ([#81346](https://github.com/WordPress/gutenberg/pull/81346)).
- `InserterMenu`: Cancel the animation frame that focuses the active tab when the menu unmounts before it runs, so an unmount right after mount no longer throws [#81918](https://github.com/WordPress/gutenberg/pull/81918).
- `ListView`: On keyboard activation, focus the start of the first field instead of the end of the last. A Table no longer focuses its last cell. Clicking a List View item still keeps focus in the list ([#81964](https://github.com/WordPress/gutenberg/pull/81964)).

### Internal

Expand Down
9 changes: 5 additions & 4 deletions packages/block-editor/src/components/list-view/block.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -431,11 +431,12 @@ function ListViewBlock( {
const selectEditorBlock = useCallback(
( event ) => {
// For keyboard activation (Enter/Space on a link), transfer focus
// to the canvas with the caret at the end of the block.
// For mouse clicks, keep focus in the list view so that subsequent
// keyboard operations (arrow navigation, copy/paste) still work.
// to the canvas at the default initial position (start of the first
// field). For mouse clicks, keep focus in the list view so that
// subsequent keyboard operations (arrow navigation, copy/paste)
// still work.
const isKeyboardActivation = event?.detail === 0;
selectBlock( event, clientId, isKeyboardActivation ? -1 : null );
selectBlock( event, clientId, isKeyboardActivation ? 0 : null );
event.preventDefault();
},
[ clientId, selectBlock ]
Expand Down
67 changes: 59 additions & 8 deletions test/e2e/specs/editor/various/list-view.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1445,7 +1445,7 @@ test.describe( 'List View', () => {
).toBeVisible();
} );

test( 'should place the caret at the end of the block when activating from List View', async ( {
test( 'should place the caret at the start of the block when activating from List View', async ( {
editor,
page,
listViewUtils,
Expand All @@ -1465,33 +1465,84 @@ test.describe( 'List View', () => {

// Click the first paragraph in List View to select it,
// then press Enter to activate it (transfer focus to canvas).
// Keyboard activation (Enter/Space) places the caret at the end
// of the block, while mouse click keeps focus in the list view.
// Keyboard activation places the caret at the start of the first
// field. Mouse click keeps focus in the list view.
await listView
.getByRole( 'gridcell', { name: 'Paragraph' } )
.first()
.click();
await page.keyboard.press( 'Enter' );

// Press Enter to split the block at the caret position.
// If the caret is at the end, this creates a new block after the first paragraph.
// If the caret is at the start, this creates a new block before the first paragraph.
// With the caret at the start, this creates a new block before
// the first paragraph.
await page.keyboard.press( 'Enter' );

// Verify the block order: if the caret was at the end, the new empty
// block should be after the first paragraph, not before it.
await expect.poll( editor.getBlocks ).toMatchObject( [
{ name: 'core/paragraph', attributes: { content: '' } },
{
name: 'core/paragraph',
attributes: { content: 'First paragraph' },
},
{ name: 'core/paragraph', attributes: { content: '' } },
{
name: 'core/paragraph',
attributes: { content: 'Second paragraph' },
},
] );
} );

test( 'should focus the first cell of a Table when activating from List View', async ( {
editor,
page,
listViewUtils,
} ) => {
await editor.insertBlock( {
name: 'core/table',
attributes: {
body: [
{
cells: [
{ content: 'R1C1', tag: 'td' },
{ content: 'R1C2', tag: 'td' },
],
},
{
cells: [
{ content: 'R2C1', tag: 'td' },
{ content: 'R2C2', tag: 'td' },
],
},
],
},
} );

const listView = await listViewUtils.openListView();
await listView.getByRole( 'gridcell', { name: 'Table' } ).click();
await page.keyboard.press( 'Enter' );
await page.keyboard.type( 'X' );

await expect.poll( editor.getBlocks ).toMatchObject( [
{
name: 'core/table',
attributes: {
body: [
{
cells: [
{ content: 'XR1C1', tag: 'td' },
{ content: 'R1C2', tag: 'td' },
],
},
{
cells: [
{ content: 'R2C1', tag: 'td' },
{ content: 'R2C2', tag: 'td' },
],
},
],
},
},
] );
} );
} );

/** @typedef {import('@playwright/test').Locator} Locator */
Expand Down
Loading