Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(v3): allow overriding default toggle key #1196

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/docsearch-react/src/DocSearch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export interface DocSearchProps {
initialQuery?: string;
navigator?: AutocompleteOptions<InternalDocSearchHit>['navigator'];
translations?: DocSearchTranslations;
toggleKey?: string;
}

export function DocSearch(props: DocSearchProps) {
Expand All @@ -49,6 +50,7 @@ export function DocSearch(props: DocSearchProps) {
const [initialQuery, setInitialQuery] = React.useState<string | undefined>(
props?.initialQuery || undefined
);
const toggleKey = props?.toggleKey || 'k';

const onOpen = React.useCallback(() => {
setIsOpen(true);
Expand All @@ -72,13 +74,15 @@ export function DocSearch(props: DocSearchProps) {
onClose,
onInput,
searchButtonRef,
toggleKey,
});

return (
<>
<DocSearchButton
ref={searchButtonRef}
translations={props?.translations?.button}
toggleKey={toggleKey}
onClick={onOpen}
/>

Expand Down
7 changes: 5 additions & 2 deletions packages/docsearch-react/src/DocSearchButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export type ButtonTranslations = Partial<{

export type DocSearchButtonProps = React.ComponentProps<'button'> & {
translations?: ButtonTranslations;
toggleKey?: string;
};

const ACTION_KEY_DEFAULT = 'Ctrl' as const;
Expand All @@ -22,7 +23,7 @@ function isAppleDevice() {
export const DocSearchButton = React.forwardRef<
HTMLButtonElement,
DocSearchButtonProps
>(({ translations = {}, ...props }, ref) => {
>(({ translations = {}, toggleKey = 'k', ...props }, ref) => {
const { buttonText = 'Search', buttonAriaLabel = 'Search' } = translations;

const key = useMemo<
Expand Down Expand Up @@ -53,7 +54,9 @@ export const DocSearchButton = React.forwardRef<
<span className="DocSearch-Button-Key">
{key === ACTION_KEY_DEFAULT ? <ControlKeyIcon /> : key}
</span>
<span className="DocSearch-Button-Key">K</span>
<span className="DocSearch-Button-Key">
{toggleKey.toLocaleUpperCase()}
</span>
</>
)}
</span>
Expand Down
39 changes: 39 additions & 0 deletions packages/docsearch-react/src/__tests__/api.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
screen,
act,
} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';

import '@testing-library/jest-dom';
Expand All @@ -27,6 +28,44 @@ describe('api', () => {
expect(document.querySelector('.DocSearch')).toBeInTheDocument();
});

describe('toggleKey', () => {
it('opens and close the modal with the default shortcut', async () => {
render(<DocSearch />);

await waitFor(() => {
userEvent.keyboard('{meta}{k}');
});

expect(document.querySelector('.DocSearch-Modal')).toBeInTheDocument();

await waitFor(() => {
userEvent.keyboard('{meta}{k}');
});

expect(
document.querySelector('.DocSearch-Modal')
).not.toBeInTheDocument();
});

it('overrides the default shortcut', async () => {
render(<DocSearch toggleKey="u" />);

await waitFor(() => {
userEvent.keyboard('{meta}{u}');
});

expect(document.querySelector('.DocSearch-Modal')).toBeInTheDocument();

await waitFor(() => {
userEvent.keyboard('{meta}{u}');
});

expect(
document.querySelector('.DocSearch-Modal')
).not.toBeInTheDocument();
});
});

describe('translations', () => {
it('overrides the default DocSearchButton text', () => {
render(
Expand Down
10 changes: 6 additions & 4 deletions packages/docsearch-react/src/useDocSearchKeyboardEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export interface UseDocSearchKeyboardEventsProps {
onClose: () => void;
onInput?: (event: KeyboardEvent) => void;
searchButtonRef?: React.RefObject<HTMLButtonElement>;
toggleKey: string;
}

function isEditingContent(event: KeyboardEvent): boolean {
Expand All @@ -26,6 +27,7 @@ export function useDocSearchKeyboardEvents({
onClose,
onInput,
searchButtonRef,
toggleKey = 'k',
}: UseDocSearchKeyboardEventsProps) {
React.useEffect(() => {
function onKeyDown(event: KeyboardEvent) {
Expand All @@ -37,9 +39,9 @@ export function useDocSearchKeyboardEvents({
}
}
if (
(event.keyCode === 27 && isOpen) ||
// The `Cmd+K` shortcut both opens and closes the modal.
(event.key === 'k' && (event.metaKey || event.ctrlKey)) ||
(event.key === 'Escape' && isOpen) ||
// The `Cmd+toggleKey` shortcut both opens and closes the modal.
(event.key === toggleKey && (event.metaKey || event.ctrlKey)) ||
// The `/` shortcut opens but doesn't close the modal because it's
// a character.
(!isEditingContent(event) && event.key === '/' && !isOpen)
Expand Down Expand Up @@ -69,5 +71,5 @@ export function useDocSearchKeyboardEvents({
return () => {
window.removeEventListener('keydown', onKeyDown);
};
}, [isOpen, onOpen, onClose, onInput, searchButtonRef]);
}, [isOpen, onOpen, onClose, onInput, searchButtonRef, toggleKey]);
}
11 changes: 11 additions & 0 deletions packages/website/docs/api.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,11 @@ const translations: DocSearchTranslations = {

</div>
</details>
## `toggleKey`

> `type: string` | `default: "k"` | **optional**

Allow overriding the default key to open/close the DocSearch modal.

</TabItem>

Expand Down Expand Up @@ -309,6 +314,12 @@ const translations: DocSearchTranslations = {
</div>
</details>

## `toggleKey`

> `type: string` | `default: "k"` | **optional**

Allow overriding the default key to open/close the DocSearch modal.

</TabItem>

</Tabs>
Expand Down