konobangu/apps/storybook/stories/form.stories.tsx

86 lines
2.1 KiB
TypeScript

import { zodResolver } from '@hookform/resolvers/zod';
import { action } from '@storybook/addon-actions';
import type { Meta, StoryObj } from '@storybook/react';
import { useForm } from 'react-hook-form';
import * as z from 'zod';
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@konobangu/design-system/components/ui/form';
/**
* Building forms with React Hook Form and Zod.
*/
const meta: Meta<typeof Form> = {
title: 'ui/Form',
component: Form,
tags: ['autodocs'],
argTypes: {},
render: (args) => <ProfileForm {...args} />,
} satisfies Meta<typeof Form>;
export default meta;
type Story = StoryObj<typeof meta>;
const formSchema = z.object({
username: z.string().min(2, {
message: 'Username must be at least 2 characters.',
}),
});
const ProfileForm = (args: Story['args']) => {
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
username: '',
},
});
function onSubmit(values: z.infer<typeof formSchema>) {
action('onSubmit')(values);
}
return (
<Form {...args} {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<FormField
control={form.control}
name="username"
render={({ field }) => (
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<input
className="w-full rounded-md border border-input bg-background px-3 py-2"
placeholder="username"
{...field}
/>
</FormControl>
<FormDescription>
This is your public display name.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<button
className="rounded bg-primary px-4 py-2 text-primary-foreground"
type="submit"
>
Submit
</button>
</form>
</Form>
);
};
/**
* The default form of the form.
*/
export const Default: Story = {};