diff --git a/lib/api/src/lib/shortcut.ts b/lib/api/src/lib/shortcut.ts index 6394c07ead28..057dd5a21930 100644 --- a/lib/api/src/lib/shortcut.ts +++ b/lib/api/src/lib/shortcut.ts @@ -63,11 +63,10 @@ export const shortcutMatchesShortcut = ( inputShortcut: KeyCollection, shortcut: KeyCollection ): boolean => { - return ( - inputShortcut && - inputShortcut.length === shortcut.length && - !inputShortcut.find((key, i) => key !== shortcut[i]) - ); + if (!inputShortcut || !shortcut) return false; + if (inputShortcut.join('') === 'shift/') inputShortcut.shift(); // shift is optional for `/` + if (inputShortcut.length !== shortcut.length) return false; + return !inputShortcut.find((key, i) => key !== shortcut[i]); }; // Should this keyboard event trigger this keyboard shortcut? diff --git a/lib/api/src/modules/layout.ts b/lib/api/src/modules/layout.ts index 93f26915f730..0118fa325c4c 100644 --- a/lib/api/src/modules/layout.ts +++ b/lib/api/src/modules/layout.ts @@ -202,13 +202,14 @@ export const init: ModuleFn = ({ store, provider }) => { ); }, - focusOnUIElement(elementId?: string) { + focusOnUIElement(elementId?: string, select?: boolean) { if (!elementId) { return; } const element = document.getElementById(elementId); if (element) { element.focus(); + if (select) element.select(); } }, diff --git a/lib/api/src/modules/shortcuts.ts b/lib/api/src/modules/shortcuts.ts index fb4783547637..702a5490fed3 100644 --- a/lib/api/src/modules/shortcuts.ts +++ b/lib/api/src/modules/shortcuts.ts @@ -167,7 +167,7 @@ export const init: ModuleFn = ({ store, fullAPI }) => { } setTimeout(() => { - fullAPI.focusOnUIElement(focusableUIElements.storySearchField); + fullAPI.focusOnUIElement(focusableUIElements.storySearchField, true); }, 0); break; } diff --git a/lib/ui/src/components/sidebar/Search.tsx b/lib/ui/src/components/sidebar/Search.tsx index ce0e50524414..4090972a81b6 100644 --- a/lib/ui/src/components/sidebar/Search.tsx +++ b/lib/ui/src/components/sidebar/Search.tsx @@ -5,7 +5,7 @@ import Downshift, { DownshiftState, StateChangeOptions } from 'downshift'; import Fuse, { FuseOptions } from 'fuse.js'; import { document } from 'global'; import { transparentize } from 'polished'; -import React, { useEffect, useMemo, useRef, useState, useCallback } from 'react'; +import React, { useMemo, useRef, useState, useCallback } from 'react'; import { DEFAULT_REF_ID } from './data'; import { @@ -21,7 +21,6 @@ import { isCloseType, } from './types'; import { searchItem } from './utils'; -import { matchesKeyCode, matchesModifiers } from '../../keybinding'; const DEFAULT_MAX_SEARCH_RESULTS = 50; @@ -173,26 +172,6 @@ export const Search = React.memo<{ [api, inputRef, showAllComponents, DEFAULT_REF_ID] ); - useEffect(() => { - const focusSearch = (event: KeyboardEvent) => { - if (!enableShortcuts || isLoading || event.repeat) return; - if (!inputRef.current || inputRef.current === document.activeElement) return; - if ( - // Shift is required to type `/` on some keyboard layouts - matchesModifiers({ ctrl: false, alt: false, meta: false }, event) && - matchesKeyCode('Slash', event) - ) { - inputRef.current.focus(); - inputRef.current.select(); - event.preventDefault(); - } - }; - - // Keyup prevents slashes from ending up in the input field when held down - document.addEventListener('keyup', focusSearch); - return () => document.removeEventListener('keyup', focusSearch); - }, [inputRef, isLoading, enableShortcuts]); - const list: SearchItem[] = useMemo(() => { return dataset.entries.reduce((acc: SearchItem[], [refId, { stories }]) => { if (stories) { @@ -209,17 +188,20 @@ export const Search = React.memo<{ if (!input) return []; let results: DownshiftItem[] = []; - const componentResults = (fuse.search(input) as SearchResult[]).filter( - ({ item }) => item.isComponent - ); + const resultIds: Set = new Set(); + const distinctResults = (fuse.search(input) as SearchResult[]).filter(({ item }) => { + if (!(item.isComponent || item.isLeaf) || resultIds.has(item.parent)) return false; + resultIds.add(item.id); + return true; + }); - if (componentResults.length) { - results = componentResults.slice(0, allComponents ? 1000 : DEFAULT_MAX_SEARCH_RESULTS); - if (componentResults.length > DEFAULT_MAX_SEARCH_RESULTS && !allComponents) { + if (distinctResults.length) { + results = distinctResults.slice(0, allComponents ? 1000 : DEFAULT_MAX_SEARCH_RESULTS); + if (distinctResults.length > DEFAULT_MAX_SEARCH_RESULTS && !allComponents) { results.push({ showAll: () => showAllComponents(true), - totalCount: componentResults.length, - moreCount: componentResults.length - DEFAULT_MAX_SEARCH_RESULTS, + totalCount: distinctResults.length, + moreCount: distinctResults.length - DEFAULT_MAX_SEARCH_RESULTS, }); } }