diff options
| author | Armand Philippot <git@armandphilippot.com> | 2023-09-22 19:34:01 +0200 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2023-10-24 12:23:48 +0200 |
| commit | a6ff5eee45215effb3344cb5d631a27a7c0369aa (patch) | |
| tree | 5051747acf72318b4fc5c18d603e3757fbefdfdb /src/components/organisms/forms/search-form/search-form.tsx | |
| parent | 651ea4fc992e77d2f36b3c68f8e7a70644246067 (diff) | |
refactor(components): rewrite form components
Diffstat (limited to 'src/components/organisms/forms/search-form/search-form.tsx')
| -rw-r--r-- | src/components/organisms/forms/search-form/search-form.tsx | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/src/components/organisms/forms/search-form/search-form.tsx b/src/components/organisms/forms/search-form/search-form.tsx new file mode 100644 index 0000000..826e6c8 --- /dev/null +++ b/src/components/organisms/forms/search-form/search-form.tsx @@ -0,0 +1,98 @@ +import { useRouter } from 'next/router'; +import { + ChangeEvent, + FormEvent, + forwardRef, + ForwardRefRenderFunction, + useId, + useState, +} from 'react'; +import { useIntl } from 'react-intl'; +import { Button, Form, Input, Label, MagnifyingGlass } from '../../../atoms'; +import { LabelledField } from '../../../molecules'; +import styles from './search-form.module.scss'; + +export type SearchFormProps = { + /** + * Should the label be visually hidden? + * + * @default false + */ + isLabelHidden?: boolean; + /** + * The search page url. + */ + searchPage: string; +}; + +const SearchFormWithRef: ForwardRefRenderFunction< + HTMLInputElement, + SearchFormProps +> = ({ isLabelHidden = false, searchPage }, 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 router = useRouter(); + const [value, setValue] = useState<string>(''); + + const submitHandler = (e: FormEvent) => { + e.preventDefault(); + router.push({ pathname: searchPage, query: { s: value } }); + setValue(''); + }; + + const updateForm = (e: ChangeEvent<HTMLInputElement>) => { + setValue(e.target.value); + }; + + const id = useId(); + + return ( + <Form className={styles.wrapper} onSubmit={submitHandler}> + <LabelledField + className={styles.field} + field={ + <Input + className={styles.field} + id={`search-form-${id}`} + name="search-form" + onChange={updateForm} + ref={ref} + type="search" + value={value} + /> + } + label={ + <Label htmlFor={`search-form-${id}`} isHidden={isLabelHidden}> + {fieldLabel} + </Label> + } + /> + <Button + aria-label={buttonLabel} + className={styles.btn} + kind="neutral" + shape="initial" + type="submit" + > + <MagnifyingGlass className={styles.btn__icon} /> + </Button> + </Form> + ); +}; + +/** + * SearchForm component + * + * Render a search form. + */ +export const SearchForm = forwardRef(SearchFormWithRef); |
