✨(react) react-hook-form Checkbox example
Our form elements needs to be usable with react-hook-form
This commit is contained in:
@@ -85,6 +85,15 @@ You can also define `state`, `text` props on the group component
|
||||
<Story id="components-forms-checkbox--group-success"/>
|
||||
</Canvas>
|
||||
|
||||
## Usage with react-hook-form
|
||||
|
||||
You can use this input with [react-hook-form](https://react-hook-form.com/docs)
|
||||
|
||||
<Canvas sourceState="shown">
|
||||
<Story id="components-forms-checkbox--react-hook-form"/>
|
||||
</Canvas>
|
||||
|
||||
|
||||
### Props
|
||||
|
||||
<ArgTypes of={Checkbox} />
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
import { Meta, StoryFn } from "@storybook/react";
|
||||
import React from "react";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import { Meta, StoryFn } from "@storybook/react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import * as Yup from "yup";
|
||||
import { Checkbox, CheckboxGroup } from ":/components/Forms/Checkbox/index";
|
||||
import { Button } from ":/components/Button";
|
||||
import {
|
||||
getFieldState,
|
||||
getFieldErrorMessage,
|
||||
onSubmit,
|
||||
} from ":/tests/reactHookFormUtils";
|
||||
|
||||
export default {
|
||||
title: "Components/Forms/Checkbox",
|
||||
@@ -138,3 +147,46 @@ export const GroupSuccess = () => (
|
||||
</CheckboxGroup>
|
||||
</div>
|
||||
);
|
||||
|
||||
export const ReactHookForm = () => {
|
||||
interface CheckboxExampleFormValues {
|
||||
terms: boolean;
|
||||
}
|
||||
|
||||
const checkboxExampleSchema = Yup.object().shape({
|
||||
terms: Yup.boolean()
|
||||
.required()
|
||||
.oneOf([true], "You have to accept the terms of use"),
|
||||
});
|
||||
|
||||
const { register, handleSubmit, formState } =
|
||||
useForm<CheckboxExampleFormValues>({
|
||||
defaultValues: {
|
||||
terms: false,
|
||||
},
|
||||
mode: "onChange",
|
||||
reValidateMode: "onChange",
|
||||
resolver: yupResolver(checkboxExampleSchema),
|
||||
});
|
||||
|
||||
return (
|
||||
<form
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "1rem",
|
||||
width: "400px",
|
||||
}}
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
>
|
||||
<Checkbox
|
||||
label="I accept the terms of use"
|
||||
fullWidth
|
||||
state={getFieldState("terms", formState)}
|
||||
text={getFieldErrorMessage("terms", formState)}
|
||||
{...register("terms")}
|
||||
/>
|
||||
<Button fullWidth={true}>Log-in</Button>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, {
|
||||
InputHTMLAttributes,
|
||||
PropsWithChildren,
|
||||
forwardRef,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
@@ -14,55 +15,68 @@ type Props = InputHTMLAttributes<HTMLInputElement> &
|
||||
label?: string;
|
||||
};
|
||||
|
||||
export const Checkbox = ({
|
||||
indeterminate,
|
||||
className = "",
|
||||
checked,
|
||||
label,
|
||||
text,
|
||||
rightText,
|
||||
state,
|
||||
...props
|
||||
}: Props) => {
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const [value, setValue] = useState<boolean>(!!checked);
|
||||
export const Checkbox = forwardRef<HTMLInputElement, Props>(
|
||||
(
|
||||
{
|
||||
indeterminate,
|
||||
className = "",
|
||||
checked,
|
||||
label,
|
||||
text,
|
||||
rightText,
|
||||
state,
|
||||
...props
|
||||
}: Props,
|
||||
ref,
|
||||
) => {
|
||||
const inputRef = useRef<HTMLInputElement>();
|
||||
const [value, setValue] = useState<boolean>(!!checked);
|
||||
|
||||
useEffect(() => {
|
||||
setValue(!!checked);
|
||||
}, [checked]);
|
||||
useEffect(() => {
|
||||
setValue(!!checked);
|
||||
}, [checked]);
|
||||
|
||||
useEffect(() => {
|
||||
if (inputRef.current) {
|
||||
inputRef.current.indeterminate = !!indeterminate;
|
||||
}
|
||||
}, [indeterminate]);
|
||||
useEffect(() => {
|
||||
if (inputRef.current) {
|
||||
inputRef.current.indeterminate = !!indeterminate;
|
||||
}
|
||||
}, [indeterminate]);
|
||||
|
||||
return (
|
||||
<label
|
||||
className={classNames("c__checkbox", {
|
||||
"c__checkbox--disabled": props.disabled,
|
||||
})}
|
||||
>
|
||||
<Field text={text} rightText={rightText} compact={true} state={state}>
|
||||
<div className="c__checkbox__container">
|
||||
<div className="c__checkbox__wrapper">
|
||||
<input
|
||||
type="checkbox"
|
||||
className={className}
|
||||
onChange={(e) => setValue(e.target.checked)}
|
||||
{...props}
|
||||
checked={value}
|
||||
ref={inputRef}
|
||||
/>
|
||||
<Indeterminate />
|
||||
<Checkmark />
|
||||
return (
|
||||
<label
|
||||
className={classNames("c__checkbox", {
|
||||
"c__checkbox--disabled": props.disabled,
|
||||
})}
|
||||
>
|
||||
<Field text={text} rightText={rightText} compact={true} state={state}>
|
||||
<div className="c__checkbox__container">
|
||||
<div className="c__checkbox__wrapper">
|
||||
<input
|
||||
type="checkbox"
|
||||
className={className}
|
||||
{...props}
|
||||
onChange={(e) => {
|
||||
setValue(e.target.checked);
|
||||
props.onChange?.(e);
|
||||
}}
|
||||
checked={value}
|
||||
ref={(checkboxRef) => {
|
||||
if (typeof ref === "function") {
|
||||
ref(checkboxRef);
|
||||
}
|
||||
inputRef.current = checkboxRef || undefined;
|
||||
}}
|
||||
/>
|
||||
<Indeterminate />
|
||||
<Checkmark />
|
||||
</div>
|
||||
{label && <div className="c__checkbox__label">{label}</div>}
|
||||
</div>
|
||||
{label && <div className="c__checkbox__label">{label}</div>}
|
||||
</div>
|
||||
</Field>
|
||||
</label>
|
||||
);
|
||||
};
|
||||
</Field>
|
||||
</label>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
export const CheckboxGroup = ({
|
||||
children,
|
||||
|
||||
Reference in New Issue
Block a user