aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/organisms/forms/search-form/search-form.tsx
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2023-11-03 23:03:06 +0100
committerArmand Philippot <git@armandphilippot.com>2023-11-11 18:15:27 +0100
commitce4a18899f24ba89b63ef743476ec0dbf1999ecf (patch)
tree003a59ee62bc5f1f97110926559d941a978090ac /src/components/organisms/forms/search-form/search-form.tsx
parentddd45e29745b73e7fe1684e197dcff598b375644 (diff)
refactor(components): rewrite SearchForm component
* remove searchPage prop (the consumer should handle the submit) * change onSubmit type * use `useForm` hook to handle the form
Diffstat (limited to 'src/components/organisms/forms/search-form/search-form.tsx')
-rw-r--r--src/components/organisms/forms/search-form/search-form.tsx113
1 files changed, 60 insertions, 53 deletions
diff --git a/src/components/organisms/forms/search-form/search-form.tsx b/src/components/organisms/forms/search-form/search-form.tsx
index 5c685c0..3f16ad0 100644
--- a/src/components/organisms/forms/search-form/search-form.tsx
+++ b/src/components/organisms/forms/search-form/search-form.tsx
@@ -1,20 +1,22 @@
-import { useRouter } from 'next/router';
-import {
- type ChangeEvent,
- type FormEvent,
- forwardRef,
- type ForwardRefRenderFunction,
- useId,
- useState,
- useCallback,
-} from 'react';
+import { forwardRef, type ForwardRefRenderFunction, useId } from 'react';
import { useIntl } from 'react-intl';
-import { Button, Form, Icon, Input, Label } from '../../../atoms';
+import { type FormSubmitHandler, useForm } from '../../../../utils/hooks';
+import {
+ Button,
+ Form,
+ type FormProps,
+ Icon,
+ Input,
+ Label,
+} from '../../../atoms';
import { LabelledField } from '../../../molecules';
import styles from './search-form.module.scss';
-export type SearchFormProps = {
- className?: string;
+export type SearchFormData = { query: string };
+
+export type SearchFormSubmit = FormSubmitHandler<SearchFormData>;
+
+export type SearchFormProps = Omit<FormProps, 'children' | 'onSubmit'> & {
/**
* Should the label be visually hidden?
*
@@ -22,75 +24,80 @@ export type SearchFormProps = {
*/
isLabelHidden?: boolean;
/**
- * The search page url.
+ * A callback function to handle search form submit.
*/
- searchPage: string;
+ onSubmit?: SearchFormSubmit;
};
const SearchFormWithRef: ForwardRefRenderFunction<
HTMLInputElement,
SearchFormProps
-> = ({ className = '', isLabelHidden = false, searchPage }, ref) => {
+> = ({ className = '', isLabelHidden = false, onSubmit, ...props }, ref) => {
const intl = useIntl();
- const fieldLabel = intl.formatMessage({
- defaultMessage: 'Search for:',
- description: 'SearchForm: field accessible label',
- id: 'X8oujO',
- });
- const buttonLabel = intl.formatMessage({
- defaultMessage: 'Search',
- description: 'SearchForm: button accessible name',
- id: 'WMqQrv',
+ const { values, submit, submitStatus, update } = useForm<SearchFormData>({
+ initialValues: { query: '' },
+ submitHandler: onSubmit,
});
-
- const router = useRouter();
- const [value, setValue] = useState<string>('');
-
- const submitHandler = useCallback(
- (e: FormEvent) => {
- e.preventDefault();
- router.push({ pathname: searchPage, query: { s: value } });
- setValue('');
- },
- [router, searchPage, value]
- );
-
- const updateForm = useCallback((e: ChangeEvent<HTMLInputElement>) => {
- setValue(e.target.value);
- }, []);
-
const id = useId();
- const formClass = `${styles.wrapper} ${className}`;
+ const formClass = [
+ styles.wrapper,
+ styles[isLabelHidden ? 'wrapper--no-label' : 'wrapper--has-label'],
+ className,
+ ].join(' ');
+ const labels = {
+ button: intl.formatMessage({
+ defaultMessage: 'Search',
+ description: 'SearchForm: button accessible name',
+ id: 'WMqQrv',
+ }),
+ field: intl.formatMessage({
+ defaultMessage: 'Search for:',
+ description: 'SearchForm: field accessible label',
+ id: 'X8oujO',
+ }),
+ };
return (
- <Form className={formClass} onSubmit={submitHandler}>
+ <Form {...props} className={formClass} onSubmit={submit}>
<LabelledField
className={styles.field}
field={
<Input
- className={styles.field}
- id={`search-form-${id}`}
- name="search-form"
- onChange={updateForm}
+ className={styles.input}
+ id={id}
+ // eslint-disable-next-line react/jsx-no-literals
+ name="query"
+ onChange={update}
ref={ref}
+ // eslint-disable-next-line react/jsx-no-literals
type="search"
- value={value}
+ value={values.query}
/>
}
label={
- <Label htmlFor={`search-form-${id}`} isHidden={isLabelHidden}>
- {fieldLabel}
+ <Label htmlFor={id} isHidden={isLabelHidden}>
+ {labels.field}
</Label>
}
/>
<Button
- aria-label={buttonLabel}
+ aria-label={labels.button}
className={styles.btn}
+ isLoading={submitStatus === 'PENDING'}
+ // eslint-disable-next-line react/jsx-no-literals
kind="neutral"
+ // eslint-disable-next-line react/jsx-no-literals
shape="initial"
type="submit"
>
- <Icon className={styles.btn__icon} shape="magnifying-glass" />
+ <Icon
+ aria-hidden
+ className={styles.icon}
+ // eslint-disable-next-line react/jsx-no-literals
+ shape="magnifying-glass"
+ // eslint-disable-next-line react/jsx-no-literals
+ size="lg"
+ />
</Button>
</Form>
);