Skip to content

Commit d54ae58

Browse files
Add baseline Storybook story with autofill attributes
1 parent 461abfe commit d54ae58

1 file changed

Lines changed: 152 additions & 0 deletions

File tree

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
import { zodResolver } from '@hookform/resolvers/zod';
2+
import { TextField } from '@lambdacurry/forms/remix-hook-form/text-field';
3+
import { Button } from '@lambdacurry/forms/ui/button';
4+
import type { Meta, StoryObj } from '@storybook/react-vite';
5+
import { type ActionFunctionArgs, useFetcher } from 'react-router';
6+
import { RemixFormProvider, getValidatedFormData, useRemixForm } from 'remix-hook-form';
7+
import { z } from 'zod';
8+
import { withReactRouterStubDecorator } from '../lib/storybook/react-router-stub';
9+
10+
const formSchema = z.object({
11+
name: z.string().min(1, 'Name is required'),
12+
email: z.string().email('Invalid email address'),
13+
phone: z.string().min(1, 'Phone number is required'),
14+
address: z.string().min(1, 'Address is required'),
15+
city: z.string().min(1, 'City is required'),
16+
state: z.string().min(1, 'State is required'),
17+
zipCode: z.string().min(1, 'Zip code is required'),
18+
});
19+
20+
type FormData = z.infer<typeof formSchema>;
21+
22+
const AutofillBaselineExample = () => {
23+
const fetcher = useFetcher<{ message: string }>();
24+
const methods = useRemixForm<FormData>({
25+
resolver: zodResolver(formSchema),
26+
defaultValues: {
27+
name: '',
28+
email: '',
29+
phone: '',
30+
address: '',
31+
city: '',
32+
state: '',
33+
zipCode: '',
34+
},
35+
fetcher,
36+
submitConfig: {
37+
action: '/',
38+
method: 'post',
39+
},
40+
});
41+
42+
return (
43+
<RemixFormProvider {...methods}>
44+
<fetcher.Form onSubmit={methods.handleSubmit}>
45+
<div className="space-y-4 max-w-md mx-auto">
46+
<h2 className="text-xl font-bold mb-4">Personal Information Form</h2>
47+
<p className="text-sm text-gray-500 mb-6">
48+
This form demonstrates browser autofill functionality. Try using your browser's autofill feature to populate these fields.
49+
</p>
50+
51+
<div className="space-y-4">
52+
<TextField
53+
name="name"
54+
label="Full Name"
55+
autoComplete="name"
56+
/>
57+
58+
<TextField
59+
name="email"
60+
label="Email Address"
61+
type="email"
62+
autoComplete="email"
63+
/>
64+
65+
<TextField
66+
name="phone"
67+
label="Phone Number"
68+
type="tel"
69+
autoComplete="tel"
70+
/>
71+
72+
<TextField
73+
name="address"
74+
label="Street Address"
75+
autoComplete="street-address"
76+
/>
77+
78+
<div className="grid grid-cols-2 gap-4">
79+
<TextField
80+
name="city"
81+
label="City"
82+
autoComplete="address-level2"
83+
/>
84+
85+
<TextField
86+
name="state"
87+
label="State"
88+
autoComplete="address-level1"
89+
/>
90+
</div>
91+
92+
<TextField
93+
name="zipCode"
94+
label="Zip Code"
95+
autoComplete="postal-code"
96+
/>
97+
98+
<Button type="submit" className="w-full mt-6">
99+
Submit
100+
</Button>
101+
102+
{fetcher.data?.message && (
103+
<p className="mt-2 text-green-600">{fetcher.data.message}</p>
104+
)}
105+
</div>
106+
</div>
107+
</fetcher.Form>
108+
</RemixFormProvider>
109+
);
110+
};
111+
112+
const handleFormSubmission = async (request: Request) => {
113+
const { data, errors } = await getValidatedFormData<FormData>(request, zodResolver(formSchema));
114+
115+
if (errors) {
116+
return { errors };
117+
}
118+
119+
return { message: 'Form submitted successfully' };
120+
};
121+
122+
const meta: Meta<typeof TextField> = {
123+
title: 'RemixHookForm/AutofillBaseline',
124+
component: TextField,
125+
parameters: {
126+
layout: 'centered',
127+
docs: {
128+
description: {
129+
component: 'A baseline example showing form fields with standard HTML autocomplete attributes for browser autofill.'
130+
}
131+
}
132+
},
133+
tags: ['autodocs'],
134+
};
135+
136+
export default meta;
137+
type Story = StoryObj<typeof meta>;
138+
139+
export const AutofillExample: Story = {
140+
decorators: [
141+
withReactRouterStubDecorator({
142+
routes: [
143+
{
144+
path: '/',
145+
Component: AutofillBaselineExample,
146+
action: async ({ request }: ActionFunctionArgs) => handleFormSubmission(request),
147+
},
148+
],
149+
}),
150+
],
151+
};
152+

0 commit comments

Comments
 (0)