fix(editor): prevent Tab key propagation outside editor (#11531)
Closes: BS-2964
This commit is contained in:
@@ -42,6 +42,7 @@ import type { ExtensionType } from '@blocksuite/store';
|
|||||||
import { RootBlockAdapterExtensions } from '../adapters/extension';
|
import { RootBlockAdapterExtensions } from '../adapters/extension';
|
||||||
import { clipboardConfigs } from '../clipboard';
|
import { clipboardConfigs } from '../clipboard';
|
||||||
import { builtinToolbarConfig } from '../configs/toolbar';
|
import { builtinToolbarConfig } from '../configs/toolbar';
|
||||||
|
import { fallbackKeymap } from '../keyboard/keymap';
|
||||||
import {
|
import {
|
||||||
innerModalWidget,
|
innerModalWidget,
|
||||||
linkedDocWidget,
|
linkedDocWidget,
|
||||||
@@ -94,6 +95,7 @@ export const CommonSpecs: ExtensionType[] = [
|
|||||||
viewportOverlayWidget,
|
viewportOverlayWidget,
|
||||||
scrollAnchoringWidget,
|
scrollAnchoringWidget,
|
||||||
toolbarWidget,
|
toolbarWidget,
|
||||||
|
fallbackKeymap,
|
||||||
|
|
||||||
ToolbarModuleExtension({
|
ToolbarModuleExtension({
|
||||||
id: BlockFlavourIdentifier(NoteBlockSchema.model.flavour),
|
id: BlockFlavourIdentifier(NoteBlockSchema.model.flavour),
|
||||||
|
|||||||
16
blocksuite/affine/blocks/root/src/keyboard/keymap.ts
Normal file
16
blocksuite/affine/blocks/root/src/keyboard/keymap.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { KeymapExtension } from '@blocksuite/std';
|
||||||
|
|
||||||
|
export const fallbackKeymap = KeymapExtension(() => {
|
||||||
|
return {
|
||||||
|
Tab: ctx => {
|
||||||
|
const event = ctx.get('defaultState').event;
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
},
|
||||||
|
'Shift-Tab': ctx => {
|
||||||
|
const event = ctx.get('defaultState').event;
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { toolbarButtons } from '@affine-test/kit/bs/linked-toolbar';
|
||||||
import { test } from '@affine-test/kit/playwright';
|
import { test } from '@affine-test/kit/playwright';
|
||||||
import {
|
import {
|
||||||
pressArrowUp,
|
pressArrowUp,
|
||||||
@@ -7,6 +8,7 @@ import {
|
|||||||
import { openHomePage } from '@affine-test/kit/utils/load-page';
|
import { openHomePage } from '@affine-test/kit/utils/load-page';
|
||||||
import {
|
import {
|
||||||
clickNewPageButton,
|
clickNewPageButton,
|
||||||
|
createLinkedPage,
|
||||||
type,
|
type,
|
||||||
waitForEditorLoad,
|
waitForEditorLoad,
|
||||||
} from '@affine-test/kit/utils/page-logic';
|
} from '@affine-test/kit/utils/page-logic';
|
||||||
@@ -77,4 +79,41 @@ test.describe('split list', () => {
|
|||||||
listLocator.nth(4).locator('.affine-list-block__numbered')
|
listLocator.nth(4).locator('.affine-list-block__numbered')
|
||||||
).toHaveText('4.');
|
).toHaveText('4.');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('tab in list should not propagate out of editor', async ({ page }) => {
|
||||||
|
await pressEnter(page);
|
||||||
|
await type(page, '1. aaa');
|
||||||
|
await page.keyboard.press('Enter');
|
||||||
|
await page.keyboard.press('Tab');
|
||||||
|
await createLinkedPage(page, 'Test Page');
|
||||||
|
const inlineLink = page.locator('affine-reference');
|
||||||
|
const { switchViewBtn, cardViewBtn } = toolbarButtons(page);
|
||||||
|
const list = page.locator('affine-list');
|
||||||
|
const card = page.locator('affine-embed-linked-doc-block');
|
||||||
|
|
||||||
|
const pressWithCount = async (key: string, count: number) => {
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 5));
|
||||||
|
await page.keyboard.press(key);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
await inlineLink.hover();
|
||||||
|
await switchViewBtn.click();
|
||||||
|
await cardViewBtn.click();
|
||||||
|
|
||||||
|
await expect(list.filter({ has: card })).toHaveCount(1);
|
||||||
|
|
||||||
|
await page.keyboard.press('Shift+Tab');
|
||||||
|
|
||||||
|
await expect(list.filter({ hasNot: card })).toHaveCount(1);
|
||||||
|
|
||||||
|
await pressWithCount('Tab', 5);
|
||||||
|
|
||||||
|
await expect(list.filter({ has: card })).toHaveCount(1);
|
||||||
|
|
||||||
|
await pressWithCount('Shift+Tab', 5);
|
||||||
|
|
||||||
|
await expect(list.filter({ hasNot: card })).toHaveCount(1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { toolbarButtons } from '@affine-test/kit/bs/linked-toolbar';
|
||||||
import { waitNextFrame } from '@affine-test/kit/bs/misc';
|
import { waitNextFrame } from '@affine-test/kit/bs/misc';
|
||||||
import { test } from '@affine-test/kit/playwright';
|
import { test } from '@affine-test/kit/playwright';
|
||||||
import { clickEdgelessModeButton } from '@affine-test/kit/utils/editor';
|
import { clickEdgelessModeButton } from '@affine-test/kit/utils/editor';
|
||||||
@@ -27,22 +28,6 @@ test.beforeEach(async ({ page }) => {
|
|||||||
await waitForEmptyEditor(page);
|
await waitForEmptyEditor(page);
|
||||||
});
|
});
|
||||||
|
|
||||||
function toolbarButtons(page: Page) {
|
|
||||||
const toolbar = page.locator('affine-toolbar-widget editor-toolbar');
|
|
||||||
const switchViewBtn = toolbar.getByLabel('Switch view');
|
|
||||||
const inlineViewBtn = toolbar.getByLabel('Inline view');
|
|
||||||
const cardViewBtn = toolbar.getByLabel('Card view');
|
|
||||||
const embedViewBtn = toolbar.getByLabel('Embed view');
|
|
||||||
|
|
||||||
return {
|
|
||||||
toolbar,
|
|
||||||
switchViewBtn,
|
|
||||||
inlineViewBtn,
|
|
||||||
cardViewBtn,
|
|
||||||
embedViewBtn,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async function enableEmojiDocIcon(page: Page) {
|
async function enableEmojiDocIcon(page: Page) {
|
||||||
// Opens settings panel
|
// Opens settings panel
|
||||||
await openEditorSetting(page);
|
await openEditorSetting(page);
|
||||||
|
|||||||
17
tests/kit/src/bs/linked-toolbar.ts
Normal file
17
tests/kit/src/bs/linked-toolbar.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import type { Page } from '@playwright/test';
|
||||||
|
|
||||||
|
export function toolbarButtons(page: Page) {
|
||||||
|
const toolbar = page.locator('affine-toolbar-widget editor-toolbar');
|
||||||
|
const switchViewBtn = toolbar.getByLabel('Switch view');
|
||||||
|
const inlineViewBtn = toolbar.getByLabel('Inline view');
|
||||||
|
const cardViewBtn = toolbar.getByLabel('Card view');
|
||||||
|
const embedViewBtn = toolbar.getByLabel('Embed view');
|
||||||
|
|
||||||
|
return {
|
||||||
|
toolbar,
|
||||||
|
switchViewBtn,
|
||||||
|
inlineViewBtn,
|
||||||
|
cardViewBtn,
|
||||||
|
embedViewBtn,
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user