diff --git a/packages/bits/src/lib/toolbar/toolbar-keyboard.service.spec.ts b/packages/bits/src/lib/toolbar/toolbar-keyboard.service.spec.ts index d068bcbaa..a8668b0b8 100644 --- a/packages/bits/src/lib/toolbar/toolbar-keyboard.service.spec.ts +++ b/packages/bits/src/lib/toolbar/toolbar-keyboard.service.spec.ts @@ -122,6 +122,27 @@ describe("Services > ", () => { service.onKeyDown(rightButtonPressEvent); expect(spy).toHaveBeenCalled(); }); + + it("should not hijack keyboard events coming from a search input", () => { + const searchInput = document.createElement("input"); + searchInput.type = "search"; + document.body.appendChild(searchInput); + + const event = { + ...keyboardEventMock, + target: searchInput, + } as KeyboardEvent; + + const preventSpy = spyOn(event, "preventDefault"); + const navSpy = spyOn(service as any, "navigateByArrow"); + + service.onKeyDown(event); + + expect(preventSpy).not.toHaveBeenCalled(); + expect(navSpy).not.toHaveBeenCalled(); + + searchInput.remove(); + }); }); }); }); diff --git a/packages/bits/src/lib/toolbar/toolbar-keyboard.service.ts b/packages/bits/src/lib/toolbar/toolbar-keyboard.service.ts index 5dbd28413..6bf27b243 100644 --- a/packages/bits/src/lib/toolbar/toolbar-keyboard.service.ts +++ b/packages/bits/src/lib/toolbar/toolbar-keyboard.service.ts @@ -34,6 +34,13 @@ export class ToolbarKeyboardService { } public onKeyDown(event: KeyboardEvent): void { + // Allow native keyboard handling inside search inputs (e.g. arrow keys move caret) + // instead of hijacking navigation for the whole toolbar. + const target = event.target as HTMLElement | null; + if (this.isSearchTarget(target)) { + return; + } + const { code } = event; if ( @@ -49,6 +56,22 @@ export class ToolbarKeyboardService { } } + private isSearchTarget(target: HTMLElement | null): boolean { + if (!target) { + return false; + } + + // Common ways a search input can be marked in DOM. + // - + // - role="searchbox" + // - a class/data attribute containing "search" + const el = target.closest?.( + "input[type=\"search\"], [role=\"searchbox\"], .search, [class*=\"search\"], [data-testid*=\"search\"], [data-automation-id*=\"search\"]" + ) as HTMLElement | null; + + return !!el; + } + private navigateByArrow(code: KEYBOARD_CODE): void { const activeEl = document.activeElement; const activeIndex = this.toolbarItems.indexOf(activeEl as HTMLElement);