Skip to content

Commit 0c68ffe

Browse files
authored
Merge pull request #14062 from storybookjs/search-stories
UI: Enable search for stories and fix `/` event listener
2 parents 8395e54 + 056a04a commit 0c68ffe

4 files changed

Lines changed: 19 additions & 37 deletions

File tree

lib/api/src/lib/shortcut.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,10 @@ export const shortcutMatchesShortcut = (
6363
inputShortcut: KeyCollection,
6464
shortcut: KeyCollection
6565
): boolean => {
66-
return (
67-
inputShortcut &&
68-
inputShortcut.length === shortcut.length &&
69-
!inputShortcut.find((key, i) => key !== shortcut[i])
70-
);
66+
if (!inputShortcut || !shortcut) return false;
67+
if (inputShortcut.join('') === 'shift/') inputShortcut.shift(); // shift is optional for `/`
68+
if (inputShortcut.length !== shortcut.length) return false;
69+
return !inputShortcut.find((key, i) => key !== shortcut[i]);
7170
};
7271

7372
// Should this keyboard event trigger this keyboard shortcut?

lib/api/src/modules/layout.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,13 +202,14 @@ export const init: ModuleFn = ({ store, provider }) => {
202202
);
203203
},
204204

205-
focusOnUIElement(elementId?: string) {
205+
focusOnUIElement(elementId?: string, select?: boolean) {
206206
if (!elementId) {
207207
return;
208208
}
209209
const element = document.getElementById(elementId);
210210
if (element) {
211211
element.focus();
212+
if (select) element.select();
212213
}
213214
},
214215

lib/api/src/modules/shortcuts.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ export const init: ModuleFn = ({ store, fullAPI }) => {
167167
}
168168

169169
setTimeout(() => {
170-
fullAPI.focusOnUIElement(focusableUIElements.storySearchField);
170+
fullAPI.focusOnUIElement(focusableUIElements.storySearchField, true);
171171
}, 0);
172172
break;
173173
}

lib/ui/src/components/sidebar/Search.tsx

Lines changed: 12 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import Downshift, { DownshiftState, StateChangeOptions } from 'downshift';
55
import Fuse, { FuseOptions } from 'fuse.js';
66
import { document } from 'global';
77
import { transparentize } from 'polished';
8-
import React, { useEffect, useMemo, useRef, useState, useCallback } from 'react';
8+
import React, { useMemo, useRef, useState, useCallback } from 'react';
99

1010
import { DEFAULT_REF_ID } from './data';
1111
import {
@@ -21,7 +21,6 @@ import {
2121
isCloseType,
2222
} from './types';
2323
import { searchItem } from './utils';
24-
import { matchesKeyCode, matchesModifiers } from '../../keybinding';
2524

2625
const DEFAULT_MAX_SEARCH_RESULTS = 50;
2726

@@ -173,26 +172,6 @@ export const Search = React.memo<{
173172
[api, inputRef, showAllComponents, DEFAULT_REF_ID]
174173
);
175174

176-
useEffect(() => {
177-
const focusSearch = (event: KeyboardEvent) => {
178-
if (!enableShortcuts || isLoading || event.repeat) return;
179-
if (!inputRef.current || inputRef.current === document.activeElement) return;
180-
if (
181-
// Shift is required to type `/` on some keyboard layouts
182-
matchesModifiers({ ctrl: false, alt: false, meta: false }, event) &&
183-
matchesKeyCode('Slash', event)
184-
) {
185-
inputRef.current.focus();
186-
inputRef.current.select();
187-
event.preventDefault();
188-
}
189-
};
190-
191-
// Keyup prevents slashes from ending up in the input field when held down
192-
document.addEventListener('keyup', focusSearch);
193-
return () => document.removeEventListener('keyup', focusSearch);
194-
}, [inputRef, isLoading, enableShortcuts]);
195-
196175
const list: SearchItem[] = useMemo(() => {
197176
return dataset.entries.reduce((acc: SearchItem[], [refId, { stories }]) => {
198177
if (stories) {
@@ -209,17 +188,20 @@ export const Search = React.memo<{
209188
if (!input) return [];
210189

211190
let results: DownshiftItem[] = [];
212-
const componentResults = (fuse.search(input) as SearchResult[]).filter(
213-
({ item }) => item.isComponent
214-
);
191+
const resultIds: Set<string> = new Set();
192+
const distinctResults = (fuse.search(input) as SearchResult[]).filter(({ item }) => {
193+
if (!(item.isComponent || item.isLeaf) || resultIds.has(item.parent)) return false;
194+
resultIds.add(item.id);
195+
return true;
196+
});
215197

216-
if (componentResults.length) {
217-
results = componentResults.slice(0, allComponents ? 1000 : DEFAULT_MAX_SEARCH_RESULTS);
218-
if (componentResults.length > DEFAULT_MAX_SEARCH_RESULTS && !allComponents) {
198+
if (distinctResults.length) {
199+
results = distinctResults.slice(0, allComponents ? 1000 : DEFAULT_MAX_SEARCH_RESULTS);
200+
if (distinctResults.length > DEFAULT_MAX_SEARCH_RESULTS && !allComponents) {
219201
results.push({
220202
showAll: () => showAllComponents(true),
221-
totalCount: componentResults.length,
222-
moreCount: componentResults.length - DEFAULT_MAX_SEARCH_RESULTS,
203+
totalCount: distinctResults.length,
204+
moreCount: distinctResults.length - DEFAULT_MAX_SEARCH_RESULTS,
223205
});
224206
}
225207
}

0 commit comments

Comments
 (0)