Skip to content

Commit c04f036

Browse files
migrate from <Form /> to <Field /> (#1433)
1 parent 0c58d19 commit c04f036

File tree

9 files changed

+419
-267
lines changed

9 files changed

+419
-267
lines changed

apps/nextjs/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"@acme/ui": "workspace:*",
2020
"@acme/validators": "workspace:*",
2121
"@t3-oss/env-nextjs": "^0.13.8",
22+
"@tanstack/react-form": "catalog:",
2223
"@tanstack/react-query": "catalog:",
2324
"@trpc/client": "catalog:",
2425
"@trpc/server": "catalog:",

apps/nextjs/src/app/_components/posts.tsx

Lines changed: 73 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"use client";
22

3+
import { useForm } from "@tanstack/react-form";
34
import {
45
useMutation,
56
useQueryClient,
@@ -11,27 +12,19 @@ import { CreatePostSchema } from "@acme/db/schema";
1112
import { cn } from "@acme/ui";
1213
import { Button } from "@acme/ui/button";
1314
import {
14-
Form,
15-
FormControl,
16-
FormField,
17-
FormItem,
18-
FormMessage,
19-
useForm,
20-
} from "@acme/ui/form";
15+
Field,
16+
FieldContent,
17+
FieldError,
18+
FieldGroup,
19+
FieldLabel,
20+
} from "@acme/ui/field";
2121
import { Input } from "@acme/ui/input";
2222
import { toast } from "@acme/ui/toast";
2323

2424
import { useTRPC } from "~/trpc/react";
2525

2626
export function CreatePostForm() {
2727
const trpc = useTRPC();
28-
const form = useForm({
29-
schema: CreatePostSchema,
30-
defaultValues: {
31-
content: "",
32-
title: "",
33-
},
34-
});
3528

3629
const queryClient = useQueryClient();
3730
const createPost = useMutation(
@@ -50,41 +43,77 @@ export function CreatePostForm() {
5043
}),
5144
);
5245

46+
const form = useForm({
47+
defaultValues: {
48+
content: "",
49+
title: "",
50+
},
51+
validators: {
52+
onSubmit: CreatePostSchema,
53+
},
54+
onSubmit: (data) => createPost.mutate(data.value),
55+
});
56+
5357
return (
54-
<Form {...form}>
55-
<form
56-
className="flex w-full max-w-2xl flex-col gap-4"
57-
onSubmit={form.handleSubmit((data) => {
58-
createPost.mutate(data);
59-
})}
60-
>
61-
<FormField
62-
control={form.control}
58+
<form
59+
className="w-full max-w-2xl"
60+
onSubmit={(event) => {
61+
event.preventDefault();
62+
void form.handleSubmit();
63+
}}
64+
>
65+
<FieldGroup>
66+
<form.Field
6367
name="title"
64-
render={({ field }) => (
65-
<FormItem>
66-
<FormControl>
67-
<Input {...field} placeholder="Title" />
68-
</FormControl>
69-
<FormMessage />
70-
</FormItem>
71-
)}
68+
children={(field) => {
69+
const isInvalid =
70+
field.state.meta.isTouched && !field.state.meta.isValid;
71+
return (
72+
<Field data-invalid={isInvalid}>
73+
<FieldContent>
74+
<FieldLabel htmlFor={field.name}>Bug Title</FieldLabel>
75+
</FieldContent>
76+
<Input
77+
id={field.name}
78+
name={field.name}
79+
value={field.state.value}
80+
onBlur={field.handleBlur}
81+
onChange={(e) => field.handleChange(e.target.value)}
82+
aria-invalid={isInvalid}
83+
placeholder="Title"
84+
/>
85+
{isInvalid && <FieldError errors={field.state.meta.errors} />}
86+
</Field>
87+
);
88+
}}
7289
/>
73-
<FormField
74-
control={form.control}
90+
<form.Field
7591
name="content"
76-
render={({ field }) => (
77-
<FormItem>
78-
<FormControl>
79-
<Input {...field} placeholder="Content" />
80-
</FormControl>
81-
<FormMessage />
82-
</FormItem>
83-
)}
92+
children={(field) => {
93+
const isInvalid =
94+
field.state.meta.isTouched && !field.state.meta.isValid;
95+
return (
96+
<Field data-invalid={isInvalid}>
97+
<FieldContent>
98+
<FieldLabel htmlFor={field.name}>Content</FieldLabel>
99+
</FieldContent>
100+
<Input
101+
id={field.name}
102+
name={field.name}
103+
value={field.state.value}
104+
onBlur={field.handleBlur}
105+
onChange={(e) => field.handleChange(e.target.value)}
106+
aria-invalid={isInvalid}
107+
placeholder="Content"
108+
/>
109+
{isInvalid && <FieldError errors={field.state.meta.errors} />}
110+
</Field>
111+
);
112+
}}
84113
/>
85-
<Button>Create</Button>
86-
</form>
87-
</Form>
114+
</FieldGroup>
115+
<Button type="submit">Create</Button>
116+
</form>
88117
);
89118
}
90119

packages/ui/package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
".": "./src/index.ts",
77
"./button": "./src/button.tsx",
88
"./dropdown-menu": "./src/dropdown-menu.tsx",
9-
"./form": "./src/form.tsx",
9+
"./field": "./src/field.tsx",
1010
"./input": "./src/input.tsx",
1111
"./label": "./src/label.tsx",
12+
"./separator": "./src/separator.tsx",
1213
"./theme": "./src/theme.tsx",
1314
"./toast": "./src/toast.tsx"
1415
},
@@ -21,12 +22,10 @@
2122
"ui-add": "pnpm dlx shadcn@latest add && prettier src --write --list-different"
2223
},
2324
"dependencies": {
24-
"@hookform/resolvers": "^5.2.2",
2525
"@radix-ui/react-icons": "^1.3.2",
2626
"class-variance-authority": "^0.7.1",
2727
"next-themes": "^0.4.6",
2828
"radix-ui": "^1.4.3",
29-
"react-hook-form": "^7.65.0",
3029
"sonner": "^2.0.7",
3130
"tailwind-merge": "^3.3.1"
3231
},

0 commit comments

Comments
 (0)