diff options
| author | Armand Philippot <git@armandphilippot.com> | 2023-11-21 16:10:20 +0100 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2023-11-21 18:17:47 +0100 |
| commit | c6212f927daf3c928f479afa052e4772216a2d8a (patch) | |
| tree | 6bb71d9cea03e110d10120ba4bf24e3a6f4ff7d0 /src/components/organisms/forms/search-form | |
| parent | 70b4f633a6fbedb58c8b9134ac64ede854d489de (diff) | |
refactor(components): replace items prop in Navbar component
* replace `items` prop with `children` prop: it is more readable this
way,
* handle navbar item state inside NavbarItem component: it avoid using
three differents states and their methods to do exactly the same thing
* remove useAutofocus hook since we can't use it anymore
* add `onActivation` and `activationHandlerDelay` prop to NavbarItem
component to be able to focus the search input only when the item is
activated (it replicates the functioning of useAutofocus hook)
* replace `ref` type in SearchForm component: it does not make sense to
use an input ref for a form. Instead I use useImperativeHandle to
provide different a focus method to the given ref.
Diffstat (limited to 'src/components/organisms/forms/search-form')
| -rw-r--r-- | src/components/organisms/forms/search-form/search-form.test.tsx | 17 | ||||
| -rw-r--r-- | src/components/organisms/forms/search-form/search-form.tsx | 32 |
2 files changed, 44 insertions, 5 deletions
diff --git a/src/components/organisms/forms/search-form/search-form.test.tsx b/src/components/organisms/forms/search-form/search-form.test.tsx index d1fdfa9..8b4379b 100644 --- a/src/components/organisms/forms/search-form/search-form.test.tsx +++ b/src/components/organisms/forms/search-form/search-form.test.tsx @@ -1,7 +1,8 @@ import { describe, expect, it, jest } from '@jest/globals'; import { userEvent } from '@testing-library/user-event'; -import { render, screen as rtlScreen } from '../../../../../tests/utils'; -import { SearchForm } from './search-form'; +import type { Ref } from 'react'; +import { act, render, screen as rtlScreen } from '../../../../../tests/utils'; +import { SearchForm, type SearchFormRef } from './search-form'; describe('SearchForm', () => { it('renders a search input with a submit button', () => { @@ -36,4 +37,16 @@ describe('SearchForm', () => { expect(onSubmit).toHaveBeenCalledTimes(1); expect(onSubmit).toHaveBeenCalledWith({ query }); }); + + it('can give focus to the search input', () => { + const ref: Ref<SearchFormRef> = { current: null }; + + render(<SearchForm ref={ref} />); + + act(() => { + ref.current?.focus(); + }); + + expect(rtlScreen.getByRole('searchbox')).toHaveFocus(); + }); }); diff --git a/src/components/organisms/forms/search-form/search-form.tsx b/src/components/organisms/forms/search-form/search-form.tsx index 3f16ad0..3d0efa2 100644 --- a/src/components/organisms/forms/search-form/search-form.tsx +++ b/src/components/organisms/forms/search-form/search-form.tsx @@ -1,4 +1,10 @@ -import { forwardRef, type ForwardRefRenderFunction, useId } from 'react'; +import { + forwardRef, + type ForwardRefRenderFunction, + useId, + useImperativeHandle, + useRef, +} from 'react'; import { useIntl } from 'react-intl'; import { type FormSubmitHandler, useForm } from '../../../../utils/hooks'; import { @@ -29,8 +35,15 @@ export type SearchFormProps = Omit<FormProps, 'children' | 'onSubmit'> & { onSubmit?: SearchFormSubmit; }; +export type SearchFormRef = { + /** + * A method to focus the search input. + */ + focus: () => void; +}; + const SearchFormWithRef: ForwardRefRenderFunction< - HTMLInputElement, + SearchFormRef, SearchFormProps > = ({ className = '', isLabelHidden = false, onSubmit, ...props }, ref) => { const intl = useIntl(); @@ -39,6 +52,7 @@ const SearchFormWithRef: ForwardRefRenderFunction< submitHandler: onSubmit, }); const id = useId(); + const inputRef = useRef<HTMLInputElement>(null); const formClass = [ styles.wrapper, styles[isLabelHidden ? 'wrapper--no-label' : 'wrapper--has-label'], @@ -57,6 +71,18 @@ const SearchFormWithRef: ForwardRefRenderFunction< }), }; + useImperativeHandle( + ref, + () => { + return { + focus() { + inputRef.current?.focus(); + }, + }; + }, + [] + ); + return ( <Form {...props} className={formClass} onSubmit={submit}> <LabelledField @@ -68,7 +94,7 @@ const SearchFormWithRef: ForwardRefRenderFunction< // eslint-disable-next-line react/jsx-no-literals name="query" onChange={update} - ref={ref} + ref={inputRef} // eslint-disable-next-line react/jsx-no-literals type="search" value={values.query} |
