diff --git a/package-lock.json b/package-lock.json index 33979c26..d51e2bfd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,9 @@ "@mui/icons-material": "5.11.0", "@mui/lab": "5.0.0-alpha.114", "@mui/material": "5.11.2", + "@use-it/event-listener": "^0.1.7", "commonmark": "0.30.0", + "keycode": "^2.2.1", "svg-pan-zoom": "3.6.1" }, "devDependencies": { @@ -3856,6 +3858,14 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@use-it/event-listener": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@use-it/event-listener/-/event-listener-0.1.7.tgz", + "integrity": "sha512-hgfExDzUU9uTRTPDCpw2s9jWTxcxmpJya3fK5ADpf5VDpSy8WYwY/kh28XE0tUcbsljeP8wfan48QvAQTSSa3Q==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/@webassemblyjs/ast": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", @@ -8707,6 +8717,11 @@ "node": ">=4.0" } }, + "node_modules/keycode": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.1.tgz", + "integrity": "sha512-Rdgz9Hl9Iv4QKi8b0OlCRQEzp4AgVxyCtz5S/+VIHezDmrDhkp2N2TqBWOLz0/gbeREXOOiI9/4b8BY9uw2vFg==" + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -18967,6 +18982,12 @@ "eslint-visitor-keys": "^3.3.0" } }, + "@use-it/event-listener": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@use-it/event-listener/-/event-listener-0.1.7.tgz", + "integrity": "sha512-hgfExDzUU9uTRTPDCpw2s9jWTxcxmpJya3fK5ADpf5VDpSy8WYwY/kh28XE0tUcbsljeP8wfan48QvAQTSSa3Q==", + "requires": {} + }, "@webassemblyjs/ast": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", @@ -22690,6 +22711,11 @@ "object.assign": "^4.1.3" } }, + "keycode": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.1.tgz", + "integrity": "sha512-Rdgz9Hl9Iv4QKi8b0OlCRQEzp4AgVxyCtz5S/+VIHezDmrDhkp2N2TqBWOLz0/gbeREXOOiI9/4b8BY9uw2vFg==" + }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", diff --git a/package.json b/package.json index 27c3ceb4..34401043 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,9 @@ "@mui/icons-material": "5.11.0", "@mui/lab": "5.0.0-alpha.114", "@mui/material": "5.11.2", + "@use-it/event-listener": "^0.1.7", "commonmark": "0.30.0", + "keycode": "^2.2.1", "svg-pan-zoom": "3.6.1" }, "devDependencies": { diff --git a/src/components/doc-explorer/DocExplorer.tsx b/src/components/doc-explorer/DocExplorer.tsx index fdcd7380..918ca3d8 100644 --- a/src/components/doc-explorer/DocExplorer.tsx +++ b/src/components/doc-explorer/DocExplorer.tsx @@ -135,7 +135,7 @@ export default class DocExplorer extends Component<
{renderNavigation(previousNav, currentNav)} diff --git a/src/components/utils/SearchBox.tsx b/src/components/utils/SearchBox.tsx index 42168a9e..9ba9cbf6 100644 --- a/src/components/utils/SearchBox.tsx +++ b/src/components/utils/SearchBox.tsx @@ -3,7 +3,9 @@ import Box from '@mui/material/Box'; import IconButton from '@mui/material/IconButton'; import Input from '@mui/material/Input'; import InputAdornment from '@mui/material/InputAdornment'; -import { useEffect, useState } from 'react'; +import useEventListener from '@use-it/event-listener'; +import keycode from 'keycode'; +import { useEffect, useRef, useState } from 'react'; interface SearchBoxProps { placeholder: string; @@ -15,11 +17,25 @@ export default function SearchBox(props: SearchBoxProps) { const [value, setValue] = useState(props.value ?? ''); const { placeholder, onSearch } = props; + const inputRef = useRef(); + useEffect(() => { const timeout = setTimeout(() => onSearch(value), 200); return () => clearTimeout(timeout); }, [onSearch, value]); + useEventListener('keydown', (event: KeyboardEvent) => { + if ( + inputRef.current && + ['/', 's'].includes(keycode(event)) && + document.activeElement?.nodeName.toLowerCase() === 'body' && + document.activeElement !== inputRef.current + ) { + event.preventDefault(); + inputRef.current.focus(); + } + }); + return ( setValue(event.target.value)} + inputRef={inputRef} type="text" className="search-box" endAdornment={ diff --git a/tests/demo.spec.ts b/tests/demo.spec.ts index ea2f5e12..c31b73c6 100644 --- a/tests/demo.spec.ts +++ b/tests/demo.spec.ts @@ -148,3 +148,44 @@ test('use search params to pass url', async ({ page }) => { 'display-schema-from-url.png', ); }); + +test.describe('search input focus with hotkey', () => { + test('pressing / key to focus the search input', async ({ page }) => { + const voyagerPage = await gotoVoyagerPage(page); + + await voyagerPage.waitForGraphToBeLoaded(); + await expect(voyagerPage.page).toHaveScreenshot( + 'before-search-input-focus.png', + ); + + await voyagerPage.page.keyboard.press('/'); + await expect(voyagerPage.page).toHaveScreenshot( + 'after-search-input-focus.png', + ); + + await voyagerPage.page.keyboard.press('/'); + await expect(voyagerPage.page).toHaveScreenshot( + 'after-search-input-typing-forward-slash.png', + ); + }); + + test('should not focus on the search input if any other input is focused', async ({ + page, + }) => { + const voyagerPage = await gotoVoyagerPage(page); + const { changeSchemaDialog } = voyagerPage; + const { sdlTab } = changeSchemaDialog; + await voyagerPage.waitForGraphToBeLoaded(); + + await changeSchemaDialog.openButton.click(); + await sdlTab.tab.click(); + await expect(voyagerPage.page).toHaveScreenshot( + 'sdl-tab-before-typing-forward-slash.png', + ); + + await sdlTab.sdlTextArea.fill('/'); + await expect(voyagerPage.page).toHaveScreenshot( + 'sdl-tab-after-typing-forward-slash.png', + ); + }); +}); diff --git a/tests/demo.spec.ts-snapshots/after-search-input-focus-Demo-linux.png b/tests/demo.spec.ts-snapshots/after-search-input-focus-Demo-linux.png new file mode 100644 index 00000000..75f9e640 Binary files /dev/null and b/tests/demo.spec.ts-snapshots/after-search-input-focus-Demo-linux.png differ diff --git a/tests/demo.spec.ts-snapshots/after-search-input-typing-forward-slash-Demo-linux.png b/tests/demo.spec.ts-snapshots/after-search-input-typing-forward-slash-Demo-linux.png new file mode 100644 index 00000000..b77da1d9 Binary files /dev/null and b/tests/demo.spec.ts-snapshots/after-search-input-typing-forward-slash-Demo-linux.png differ diff --git a/tests/demo.spec.ts-snapshots/before-search-input-focus-Demo-linux.png b/tests/demo.spec.ts-snapshots/before-search-input-focus-Demo-linux.png new file mode 100644 index 00000000..d21f9489 Binary files /dev/null and b/tests/demo.spec.ts-snapshots/before-search-input-focus-Demo-linux.png differ diff --git a/tests/demo.spec.ts-snapshots/demo-after-resize-Demo-linux.png b/tests/demo.spec.ts-snapshots/demo-after-resize-Demo-linux.png index 4190e576..16e2df04 100644 Binary files a/tests/demo.spec.ts-snapshots/demo-after-resize-Demo-linux.png and b/tests/demo.spec.ts-snapshots/demo-after-resize-Demo-linux.png differ diff --git a/tests/demo.spec.ts-snapshots/demo-before-resize-Demo-linux.png b/tests/demo.spec.ts-snapshots/demo-before-resize-Demo-linux.png index eead0781..1d4899b1 100644 Binary files a/tests/demo.spec.ts-snapshots/demo-before-resize-Demo-linux.png and b/tests/demo.spec.ts-snapshots/demo-before-resize-Demo-linux.png differ diff --git a/tests/demo.spec.ts-snapshots/display-introspection-Demo-linux.png b/tests/demo.spec.ts-snapshots/display-introspection-Demo-linux.png index 4e236445..79604f0b 100644 Binary files a/tests/demo.spec.ts-snapshots/display-introspection-Demo-linux.png and b/tests/demo.spec.ts-snapshots/display-introspection-Demo-linux.png differ diff --git a/tests/demo.spec.ts-snapshots/display-schema-from-url-Demo-linux.png b/tests/demo.spec.ts-snapshots/display-schema-from-url-Demo-linux.png index 4e236445..79604f0b 100644 Binary files a/tests/demo.spec.ts-snapshots/display-schema-from-url-Demo-linux.png and b/tests/demo.spec.ts-snapshots/display-schema-from-url-Demo-linux.png differ diff --git a/tests/demo.spec.ts-snapshots/display-sdl-Demo-linux.png b/tests/demo.spec.ts-snapshots/display-sdl-Demo-linux.png index 4e236445..79604f0b 100644 Binary files a/tests/demo.spec.ts-snapshots/display-sdl-Demo-linux.png and b/tests/demo.spec.ts-snapshots/display-sdl-Demo-linux.png differ diff --git a/tests/demo.spec.ts-snapshots/display-sdl-with-unknown-directives-Demo-linux.png b/tests/demo.spec.ts-snapshots/display-sdl-with-unknown-directives-Demo-linux.png index 2691fec4..2daf00a7 100644 Binary files a/tests/demo.spec.ts-snapshots/display-sdl-with-unknown-directives-Demo-linux.png and b/tests/demo.spec.ts-snapshots/display-sdl-with-unknown-directives-Demo-linux.png differ diff --git a/tests/demo.spec.ts-snapshots/loaded-demo-Demo-linux.png b/tests/demo.spec.ts-snapshots/loaded-demo-Demo-linux.png index 2d536e81..d21f9489 100644 Binary files a/tests/demo.spec.ts-snapshots/loaded-demo-Demo-linux.png and b/tests/demo.spec.ts-snapshots/loaded-demo-Demo-linux.png differ diff --git a/tests/demo.spec.ts-snapshots/loading-animation-Demo-linux.png b/tests/demo.spec.ts-snapshots/loading-animation-Demo-linux.png index 1d45a19c..9b8db19d 100644 Binary files a/tests/demo.spec.ts-snapshots/loading-animation-Demo-linux.png and b/tests/demo.spec.ts-snapshots/loading-animation-Demo-linux.png differ diff --git a/tests/demo.spec.ts-snapshots/sdl-tab-after-typing-forward-slash-Demo-linux.png b/tests/demo.spec.ts-snapshots/sdl-tab-after-typing-forward-slash-Demo-linux.png new file mode 100644 index 00000000..88d43837 Binary files /dev/null and b/tests/demo.spec.ts-snapshots/sdl-tab-after-typing-forward-slash-Demo-linux.png differ diff --git a/tests/demo.spec.ts-snapshots/sdl-tab-before-typing-forward-slash-Demo-linux.png b/tests/demo.spec.ts-snapshots/sdl-tab-before-typing-forward-slash-Demo-linux.png new file mode 100644 index 00000000..9cd0a5f9 Binary files /dev/null and b/tests/demo.spec.ts-snapshots/sdl-tab-before-typing-forward-slash-Demo-linux.png differ diff --git a/tests/demo.spec.ts-snapshots/show-github-preset-Demo-linux.png b/tests/demo.spec.ts-snapshots/show-github-preset-Demo-linux.png index b469e006..9abe67dc 100644 Binary files a/tests/demo.spec.ts-snapshots/show-github-preset-Demo-linux.png and b/tests/demo.spec.ts-snapshots/show-github-preset-Demo-linux.png differ diff --git a/tests/demo.spec.ts-snapshots/show-shopify-storefront-preset-Demo-linux.png b/tests/demo.spec.ts-snapshots/show-shopify-storefront-preset-Demo-linux.png index b1a69b83..9334d531 100644 Binary files a/tests/demo.spec.ts-snapshots/show-shopify-storefront-preset-Demo-linux.png and b/tests/demo.spec.ts-snapshots/show-shopify-storefront-preset-Demo-linux.png differ diff --git a/tests/demo.spec.ts-snapshots/show-star-wars-preset-Demo-linux.png b/tests/demo.spec.ts-snapshots/show-star-wars-preset-Demo-linux.png index 2d536e81..d21f9489 100644 Binary files a/tests/demo.spec.ts-snapshots/show-star-wars-preset-Demo-linux.png and b/tests/demo.spec.ts-snapshots/show-star-wars-preset-Demo-linux.png differ diff --git a/tests/demo.spec.ts-snapshots/show-yelp-preset-Demo-linux.png b/tests/demo.spec.ts-snapshots/show-yelp-preset-Demo-linux.png index 6874b48e..c67802ef 100644 Binary files a/tests/demo.spec.ts-snapshots/show-yelp-preset-Demo-linux.png and b/tests/demo.spec.ts-snapshots/show-yelp-preset-Demo-linux.png differ diff --git a/tests/webpack.spec.ts-snapshots/loaded-webpack-example-WebpackExample-linux.png b/tests/webpack.spec.ts-snapshots/loaded-webpack-example-WebpackExample-linux.png index 8f8916df..8a38988c 100644 Binary files a/tests/webpack.spec.ts-snapshots/loaded-webpack-example-WebpackExample-linux.png and b/tests/webpack.spec.ts-snapshots/loaded-webpack-example-WebpackExample-linux.png differ