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