diff --git a/packages/ui-patterns/form/FormLayout/FormLayout.stories.tsx b/packages/ui-patterns/form/FormLayout/FormLayout.stories.tsx new file mode 100644 index 00000000000..3f0c1bc59fb --- /dev/null +++ b/packages/ui-patterns/form/FormLayout/FormLayout.stories.tsx @@ -0,0 +1,223 @@ +import { zodResolver } from '@hookform/resolvers/zod' +import { StoryContext, StoryObj } from '@storybook/react' +import { useForm } from 'react-hook-form' +import { + Button, + FormControl_Shadcn_, + FormField_Shadcn_, + FormItem_Shadcn_, + Form_Shadcn_, + SelectContent_Shadcn_, + SelectItem_Shadcn_, + SelectTrigger_Shadcn_, + SelectValue_Shadcn_, + Select_Shadcn_, +} from 'ui' +import { z } from 'zod' +import { transformSourceForm } from '../../lib/transformSource' +import { FormLayout } from './FormLayout' +import { Input } from '../../data-inputs/Input' + +// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export +export default { + title: 'Form/FormLayout', + component: FormLayout, + decorators: [ + (Story: any) => { + return + }, + ], + parameters: { + // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout + layout: 'centered', + docs: { + // controls: { exclude: ['style'] }, + source: { + language: 'tsx', + transform: (code: string, StoryContext: StoryContext) => + transformSourceForm(code, StoryContext).replace('_c', 'FormInput'), + }, + }, + }, + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs + tags: ['autodocs'], + // More on argTypes: https://storybook.js.org/docs/api/argtypes + // argTypes: {}, +} + +// export default meta + +type Story = StoryObj + +export const Primary: Story = { + render: function Render(args) { + const formSchema = z.object({ + username: z.string().min(2, { + message: 'Username must be at least 2 characters.', + }), + }) + + // 1. Define your form. + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + username: '', + }, + }) + + // 2. Define a submit handler. + function onSubmit(values: z.infer) { + // Do something with the form values. + // ✅ This will be type-safe and validated. + console.log(values) + // action('form form.handleSubmit(onSubmit)')(values) + } + return ( + +
+ ( + + + + + + + + )} + /> + + +
+ ) + }, + args: { + label: 'Username', + description: 'this is the description', + labelOptional: 'optional', + placeholder: 'shadcn', + }, +} + +export const withSelect: Story = { + render: function Render(args) { + const FormSchema = z.object({ + email: z + .string({ + required_error: 'Please select an email to display.', + }) + .email(), + }) + + const form = useForm>({ + resolver: zodResolver(FormSchema), + }) + + // 2. Define a submit handler. + function onSubmit(values: z.infer) { + // Do something with the form values. + // ✅ This will be type-safe and validated. + console.log(values) + // action('form form.handleSubmit(onSubmit)')(values) + } + + return ( + +
+ ( + + + + + + + + + + + m@example.com + m@google.com + m@support.com + + + + + + )} + /> + + +
+ ) + }, + args: { + label: 'Username', + description: 'this is the description', + labelOptional: 'optional', + placeholder: 'shadcn', + }, +} + +export const withLayoutChange: Story = { + render: function Render(args) { + const formSchema = z.object({ + username: z.string().min(2, { + message: 'Username must be at least 2 characters.', + }), + }) + + // 1. Define your form. + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + username: '', + }, + }) + + // 2. Define a submit handler. + function onSubmit(values: z.infer) { + // Do something with the form values. + // ✅ This will be type-safe and validated. + console.log(values) + // action('form form.handleSubmit(onSubmit)')(values) + } + return ( + +
+ ( + + + + + + + + )} + /> + + +
+ ) + }, + args: { + layout: 'horizontal', + label: 'Username', + description: 'this is the description', + labelOptional: 'optional', + placeholder: 'shadcn', + }, +} diff --git a/packages/ui-patterns/form/FormLayout/FormLayout.tsx b/packages/ui-patterns/form/FormLayout/FormLayout.tsx new file mode 100644 index 00000000000..833eb51b17a --- /dev/null +++ b/packages/ui-patterns/form/FormLayout/FormLayout.tsx @@ -0,0 +1,39 @@ +import { ComponentPropsWithoutRef, ElementRef, forwardRef } from 'react' +import { FormLayout as FormLayoutPrimitive, FormLayoutProps } from './../../forms/layout/FormLayout' + +const FormLayout = forwardRef< + ElementRef, + ComponentPropsWithoutRef & FormLayoutProps // Use any as placeholder types +>( + ( + { + afterLabel, + beforeLabel, + labelOptional, + layout, + label, + description, + isReactForm = true, + ...props + }, + ref + ) => ( + + {props.children} + + ) +) + +FormLayout.displayName = 'FormLayout' + +export { FormLayout }