(react) react-hook-form Radio example

Our form elements needs to be usable with react-hook-form
This commit is contained in:
Romain Le Cellier
2023-07-26 17:48:22 +02:00
parent d506cab978
commit 4e53857159
3 changed files with 118 additions and 18 deletions

View File

@@ -84,6 +84,15 @@ You can also define `state`, `text` props on the group component
<Story id="components-forms-radio--group-success"/>
</Canvas>
## Usage with react-hook-form
You can use this radio with [react-hook-form](https://react-hook-form.com/docs)
<Canvas sourceState="shown">
<Story id="components-forms-radio--react-hook-form"/>
</Canvas>
### Props
<ArgTypes of={Radio} />

View File

@@ -1,6 +1,15 @@
import { Meta, StoryFn } from "@storybook/react";
import React from "react";
import { useForm } from "react-hook-form";
import * as Yup from "yup";
import { yupResolver } from "@hookform/resolvers/yup";
import { Meta, StoryFn } from "@storybook/react";
import { Radio, RadioGroup } from ":/components/Forms/Radio/index";
import { Button } from ":/components/Button";
import {
getFieldState,
getFieldErrorMessage,
onSubmit,
} from ":/tests/reactHookFormUtils";
export default {
title: "Components/Forms/Radio",
@@ -178,3 +187,79 @@ export const GroupSuccess = () => {
</div>
);
};
export const ReactHookForm = () => {
interface RadioExampleFormValues {
joTown: string;
}
const radioExampleSchema = Yup.object().shape({
joTown: Yup.string()
.required()
.oneOf(["paris"], "That's not the right town!"),
});
const { register, handleSubmit, formState } = useForm<RadioExampleFormValues>(
{
defaultValues: {
joTown: "",
},
mode: "onChange",
reValidateMode: "onChange",
resolver: yupResolver(radioExampleSchema),
},
);
return (
<form
style={{
display: "flex",
flexDirection: "column",
gap: "1rem",
width: "400px",
}}
onSubmit={handleSubmit(onSubmit)}
>
<div className="fs-l fw-bold mb-t">
Where will the 2024 Olympics take place?
</div>
<RadioGroup
state={getFieldState("joTown", formState)}
text={getFieldErrorMessage("joTown", formState)}
>
<Radio
label="Dijon"
value="dijon"
state={getFieldState("joTown", formState)}
{...register("joTown")}
/>
<Radio
label="Paris"
value="paris"
state={getFieldState("joTown", formState)}
{...register("joTown")}
/>
<Radio
label="Düsseldorf"
value="düsseldorf"
state={getFieldState("joTown", formState)}
{...register("joTown")}
/>
<Radio
label="Lubumbashi"
value="Lubumbashi"
state={getFieldState("joTown", formState)}
{...register("joTown")}
/>
<Radio
label="Tokyo"
value="tokyo"
text="This was the town of the 2020 Olympics!"
disabled={true}
{...register("joTown")}
/>
</RadioGroup>
<Button fullWidth={true}>Check it!</Button>
</form>
);
};

View File

@@ -1,4 +1,8 @@
import React, { InputHTMLAttributes, PropsWithChildren } from "react";
import React, {
InputHTMLAttributes,
PropsWithChildren,
forwardRef,
} from "react";
import classNames from "classnames";
import { Field, FieldProps } from ":/components/Forms/Field";
@@ -7,22 +11,24 @@ type Props = InputHTMLAttributes<HTMLInputElement> &
label?: string;
};
export const Radio = ({ label, text, state, ...props }: Props) => {
return (
<label
className={classNames("c__checkbox", "c__radio", {
"c__checkbox--disabled": props.disabled,
})}
>
<Field text={text} compact={true} state={state}>
<div className="c__checkbox__container">
<input type="radio" {...props} />
{label && <div className="c__checkbox__label">{label}</div>}
</div>
</Field>
</label>
);
};
export const Radio = forwardRef<HTMLInputElement, Props>(
({ label, text, state, ...props }: Props, ref) => {
return (
<label
className={classNames("c__checkbox", "c__radio", {
"c__checkbox--disabled": props.disabled,
})}
>
<Field text={text} compact={true} state={state}>
<div className="c__checkbox__container">
<input type="radio" {...props} ref={ref} />
{label && <div className="c__checkbox__label">{label}</div>}
</div>
</Field>
</label>
);
},
);
export const RadioGroup = ({
children,