From b9a38991e411c969459c2bac8a75f29576b46906 Mon Sep 17 00:00:00 2001 From: Bojan Rajh <117360292+bojanrajh@users.noreply.github.com> Date: Wed, 26 Apr 2023 14:11:03 +0200 Subject: [PATCH] fix: prevent calling `onClose()` when `shiftKey`, `ctrlKey` or `metaKey` is pressed (#1870) --- .../docsearch-react/src/DocSearchModal.tsx | 20 +++++++++++++------ packages/docsearch-react/src/Results.tsx | 6 +++--- packages/docsearch-react/src/ScreenState.tsx | 5 ++++- packages/docsearch-react/src/utils/index.ts | 1 + .../src/utils/isModifierEvent.ts | 17 ++++++++++++++++ 5 files changed, 39 insertions(+), 10 deletions(-) create mode 100644 packages/docsearch-react/src/utils/isModifierEvent.ts diff --git a/packages/docsearch-react/src/DocSearchModal.tsx b/packages/docsearch-react/src/DocSearchModal.tsx index b76edd63..686e1275 100644 --- a/packages/docsearch-react/src/DocSearchModal.tsx +++ b/packages/docsearch-react/src/DocSearchModal.tsx @@ -20,7 +20,13 @@ import type { import { useSearchClient } from './useSearchClient'; import { useTouchEvents } from './useTouchEvents'; import { useTrapFocus } from './useTrapFocus'; -import { groupBy, identity, noop, removeHighlightTags } from './utils'; +import { + groupBy, + identity, + noop, + removeHighlightTags, + isModifierEvent, +} from './utils'; export type ModalTranslations = Partial<{ searchBox: SearchBoxTranslations; @@ -156,7 +162,7 @@ export function DocSearchModal({ onSelect({ item, event }) { saveRecentSearch(item); - if (!event.shiftKey && !event.ctrlKey && !event.metaKey) { + if (!isModifierEvent(event)) { onClose(); } }, @@ -172,7 +178,7 @@ export function DocSearchModal({ onSelect({ item, event }) { saveRecentSearch(item); - if (!event.shiftKey && !event.ctrlKey && !event.metaKey) { + if (!isModifierEvent(event)) { onClose(); } }, @@ -256,7 +262,7 @@ export function DocSearchModal({ onSelect({ item, event }) { saveRecentSearch(item); - if (!event.shiftKey && !event.ctrlKey && !event.metaKey) { + if (!isModifierEvent(event)) { onClose(); } }, @@ -431,9 +437,11 @@ export function DocSearchModal({ inputRef={inputRef} translations={screenStateTranslations} getMissingResultsUrl={getMissingResultsUrl} - onItemClick={(item) => { + onItemClick={(item, event) => { saveRecentSearch(item); - onClose(); + if (!isModifierEvent(event)) { + onClose(); + } }} /> diff --git a/packages/docsearch-react/src/Results.tsx b/packages/docsearch-react/src/Results.tsx index 35568d4b..c02341a5 100644 --- a/packages/docsearch-react/src/Results.tsx +++ b/packages/docsearch-react/src/Results.tsx @@ -24,7 +24,7 @@ interface ResultsProps runDeleteTransition: (cb: () => void) => void; runFavoriteTransition: (cb: () => void) => void; }) => React.ReactNode; - onItemClick: (item: TItem) => void; + onItemClick: (item: TItem, event: KeyboardEvent | MouseEvent) => void; hitComponent: DocSearchProps['hitComponent']; } @@ -104,8 +104,8 @@ function Result({ {...getItemProps({ item, source: collection.source, - onClick() { - onItemClick(item); + onClick(event) { + onItemClick(item, event); }, })} > diff --git a/packages/docsearch-react/src/ScreenState.tsx b/packages/docsearch-react/src/ScreenState.tsx index 6696ef80..0d7a9232 100644 --- a/packages/docsearch-react/src/ScreenState.tsx +++ b/packages/docsearch-react/src/ScreenState.tsx @@ -32,7 +32,10 @@ export interface ScreenStateProps state: AutocompleteState; recentSearches: StoredSearchPlugin; favoriteSearches: StoredSearchPlugin; - onItemClick: (item: InternalDocSearchHit) => void; + onItemClick: ( + item: InternalDocSearchHit, + event: KeyboardEvent | MouseEvent + ) => void; inputRef: React.MutableRefObject; hitComponent: DocSearchProps['hitComponent']; indexName: DocSearchProps['indexName']; diff --git a/packages/docsearch-react/src/utils/index.ts b/packages/docsearch-react/src/utils/index.ts index d070520a..a4426836 100644 --- a/packages/docsearch-react/src/utils/index.ts +++ b/packages/docsearch-react/src/utils/index.ts @@ -1,4 +1,5 @@ export * from './groupBy'; export * from './identity'; +export * from './isModifierEvent'; export * from './noop'; export * from './removeHighlightTags'; diff --git a/packages/docsearch-react/src/utils/isModifierEvent.ts b/packages/docsearch-react/src/utils/isModifierEvent.ts new file mode 100644 index 00000000..7701f2ab --- /dev/null +++ b/packages/docsearch-react/src/utils/isModifierEvent.ts @@ -0,0 +1,17 @@ +/** + * Detect when an event is modified with a special key to let the browser + * trigger its default behavior. + */ +export function isModifierEvent( + event: TEvent +): boolean { + const isMiddleClick = (event as MouseEvent).button === 1; + + return ( + isMiddleClick || + event.altKey || + event.ctrlKey || + event.metaKey || + event.shiftKey + ); +}