Skip to content

Commit 3523bd4

Browse files
committed
fix(Table): allow changing list indention inside tables
Fixes: #8744 Signed-off-by: Jonas <jonas@freesources.org>
1 parent 1ac7b79 commit 3523bd4

3 files changed

Lines changed: 84 additions & 4 deletions

File tree

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
import { expect, mergeTests } from '@playwright/test'
7+
import { test as editorTest } from '../support/fixtures/editor'
8+
import { test as uploadFileTest } from '../support/fixtures/upload-file'
9+
10+
const test = mergeTests(editorTest, uploadFileTest)
11+
12+
test.describe('Tab navigation inside table cell', () => {
13+
test('indents list item inside table cell', async ({ editor, open }) => {
14+
await open()
15+
await editor.getMenu('Table').click()
16+
17+
const firstCell = editor.content.locator('table td').first()
18+
await firstCell.click()
19+
await editor.type('- one')
20+
await editor.content.press('Enter')
21+
await editor.type('two')
22+
23+
await editor.content.press('Tab')
24+
25+
const nested = firstCell.locator('ul > li').first().locator('ul > li')
26+
await expect(nested).toHaveText('two')
27+
28+
await editor.content.press('Shift+Tab')
29+
await expect(firstCell.locator('> ul > li')).toHaveCount(2)
30+
await expect(firstCell.locator('> ul > li > ul')).toHaveCount(0)
31+
})
32+
33+
test('navigates cells when caret is not inside a list', async ({ editor, open }) => {
34+
await open()
35+
await editor.getMenu('Table').click()
36+
37+
const header = editor.content.locator('table th').first()
38+
await header.click()
39+
await editor.type('h1')
40+
await editor.content.press('Tab')
41+
await editor.type('h2')
42+
43+
const headers = editor.content.locator('table th')
44+
await expect(headers.nth(0)).toContainText('h1')
45+
await expect(headers.nth(0)).toContainText('h1')
46+
})
47+
})

playwright/support/sections/EditorSection.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export class EditorSection {
4747
}
4848

4949
public getMenu(name: string): Locator {
50-
return this.el.getByRole('button', { name })
50+
return this.menubar.getByRole('button', { name })
5151
}
5252

5353
public getMenuItem(name: string): Locator {

src/nodes/Table/Table.js

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,21 @@ function findSameCellInNextRow($cell) {
7272
}
7373
}
7474

75+
/**
76+
* Return the node type name if the selection sits inside a listItem/taskItem.
77+
*
78+
* @param {object} selection - the editor selection
79+
*/
80+
function findListItemAtSelection(selection) {
81+
const { $from } = selection
82+
for (let depth = $from.depth; depth > 0; depth--) {
83+
const name = $from.node(depth).type.name
84+
if (name === 'listItem' || name === 'taskItem') {
85+
return name
86+
}
87+
}
88+
}
89+
7590
export default Table.extend({
7691
content: 'tableCaption? tableHeadRow tableRow*',
7792

@@ -319,11 +334,29 @@ export default Table.extend({
319334
...this.parent(),
320335
/**
321336
* <Tab> inside a table cell
322-
* Jump to next cell or outside table if already in last cell
337+
* When inside a list, indent the list item. Otherwise jump to
338+
* the next cell (or out of the table if in the last cell).
323339
*/
324-
Tab: () =>
340+
Tab: () => {
341+
const listItemName = findListItemAtSelection(this.editor.state.selection)
342+
if (listItemName && this.editor.commands.sinkListItem(listItemName)) {
343+
return true
344+
}
325345
this.editor.commands.goToNextCell()
326-
|| this.editor.commands.leaveTable(),
346+
|| this.editor.commands.leaveTable()
347+
},
348+
/**
349+
* <Tab> inside a table cell
350+
* When inside a list, indent the list item. Otherwise jump to
351+
* the next cell (or out of the table if in the last cell).
352+
*/
353+
'Shift-Tab': () => {
354+
const listItemName = findListItemAtSelection(this.editor.state.selection)
355+
if (listItemName && this.editor.commands.liftListItem(listItemName)) {
356+
return true
357+
}
358+
this.editor.commands.goToPreviousCell()
359+
},
327360
}
328361
},
329362
})

0 commit comments

Comments
 (0)