Files
cunningham/packages/react/src/components/Forms/Input/index.stories.tsx
Nathan Vasse b530e966ae (react) add textItems to Field
This allow to add bullet points lists below inputs, the best example
is when we want to list multiple errors from form validation.

Fixes #147
2023-09-05 11:48:04 +02:00

286 lines
6.7 KiB
TypeScript

import { yupResolver } from "@hookform/resolvers/yup";
import { Meta } from "@storybook/react";
import { useForm } from "react-hook-form";
import * as Yup from "yup";
import React, { useRef } from "react";
import {
getFieldState,
getFieldErrorMessage,
onSubmit,
} from ":/components/Forms/Examples/ReactHookForm/reactHookFormUtils";
import { Input } from ":/components/Forms/Input/index";
import { Button } from ":/components/Button";
export default {
title: "Components/Forms/Input",
component: Input,
} as Meta<typeof Input>;
export const Default = {
args: {
defaultValue: "Hello world",
label: "Your name",
},
};
export const Success = {
args: {
defaultValue: "Hello world",
label: "Your name",
state: "success",
icon: <span className="material-icons">person</span>,
text: "This is an optional success message",
},
};
export const Error = {
args: {
defaultValue: "Hello world",
label: "Your name",
state: "error",
icon: <span className="material-icons">person</span>,
text: "This is an optional error message",
},
};
export const ErrorItems = {
args: {
defaultValue: "Hello world",
label: "Your name",
state: "error",
icon: <span className="material-icons">person</span>,
text: "This is an optional error message",
textItems: [
"Text too long",
"Wrong choice",
"Must contain at least 9 characters, uppercase and digits",
],
},
};
export const DisabledEmpty = {
args: {
label: "Your name",
icon: <span className="material-icons">person</span>,
disabled: true,
},
};
export const DisabledFilled = {
args: {
label: "Your name",
defaultValue: "John Doe",
icon: <span className="material-icons">person</span>,
disabled: true,
},
};
export const Empty = {
args: {
label: "Your email",
},
};
export const Icon = {
args: {
label: "Account balance",
icon: <span className="material-icons">attach_money</span>,
defaultValue: "1000",
},
};
export const IconRight = {
args: {
label: "Account balance",
rightIcon: <span className="material-icons">attach_money</span>,
defaultValue: "1000",
},
};
export const IconBoth = {
args: {
label: "Not a recommended use",
icon: <span className="material-icons">attach_money</span>,
rightIcon: <span className="material-icons">attach_money</span>,
defaultValue: "Is isn't recommended to use both icons",
},
};
export const OverflowingText = {
args: {
label: "Your name",
icon: <span className="material-icons">attach_money</span>,
defaultValue: "John Dave Mike Smith Doe Junior Senior Yoda Skywalker",
},
};
export const WithText = {
args: {
defaultValue: "Hello world",
label: "Your name",
text: "This is a text, you can display anything you want here like warnings, informations or errors.",
},
};
export const WithTextRight = {
args: {
defaultValue: "Hello world",
label: "Your name",
rightText: "0/300",
},
};
export const WithBothTexts = {
args: {
defaultValue: "Hello world",
label: "Your name",
text: "This is a text, you can display anything you want here like warnings, informations or errors.",
rightText: "0/300",
},
};
export const FullWidth = {
args: {
defaultValue: "Hello world",
label: "Your name",
fullWidth: true,
text: "This is a text, you can display anything you want here like warnings, informations or errors.",
rightText: "0/300",
},
};
export const CharCounter = {
args: {
defaultValue: "CEO",
label: "Job title",
text: "This is a text, you can display anything you want here like warnings, informations or errors.",
charCounter: true,
charCounterMax: 30,
},
};
export const Controlled = () => {
const [value, setValue] = React.useState("I am controlled");
return (
<div>
<div>
Value: <span>{value}</span>
</div>
<Input
label="Your identity"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
<Button onClick={() => setValue("")}>Reset</Button>
</div>
);
};
export const NonControlled = () => {
return <Input defaultValue="john.doe@example.com" label="Your email" />;
};
export const WithRef = () => {
const ref = useRef<HTMLInputElement>(null);
return (
<div>
<Input label="Your identity" ref={ref} />
<Button onClick={() => ref.current?.focus()}>Focus</Button>
</div>
);
};
export const FormExample = () => {
return (
<div>
<form>
<div>
<Input label="First name" defaultValue="John" />
</div>
<div className="mt-s">
<Input label="Last name" defaultValue="Smith" />
</div>
<div className="mt-s">
<Input
label="Job Title"
defaultValue="Project Manager"
text="Your position in the company"
charCounter={true}
charCounterMax={30}
/>
</div>
<div className="mt-s">
<Input label="Code" defaultValue="XIJZ81" disabled={true} />
</div>
<div className="mt-s">
<Input
label="Address"
defaultValue="1 Infinite Loop"
state="error"
text="Address not found"
icon={<span className="material-icons">apartment</span>}
/>
</div>
<div className="mt-s">
<Input
label="Zip"
defaultValue="96020"
text="Five numbers format"
state="success"
icon={<span className="material-icons">location_on</span>}
/>
</div>
<div className="mt-s">
<Input
label="City"
defaultValue="Palo Alto"
state="success"
icon={<span className="material-icons">map</span>}
/>
</div>
</form>
</div>
);
};
export const ReactHookForm = () => {
interface InputExampleFormValues {
email: string;
}
const inputExampleSchema = Yup.object().shape({
email: Yup.string().email().required(),
});
const { register, handleSubmit, formState } = useForm<InputExampleFormValues>(
{
defaultValues: {
email: "",
},
mode: "onChange",
reValidateMode: "onChange",
resolver: yupResolver(inputExampleSchema),
},
);
return (
<form
style={{
display: "flex",
flexDirection: "column",
gap: "1rem",
width: "400px",
}}
onSubmit={handleSubmit(onSubmit)}
>
<Input
label="Email address"
fullWidth={true}
state={getFieldState("email", formState)}
text={getFieldErrorMessage("email", formState)}
{...register("email")}
/>
<Button fullWidth={true}>Log-in</Button>
</form>
);
};