Installation
Complete project setup first. Your configuration
must select react/base and include your Design System ID.
pnpm exec frontfriend download form -f react --primitive baseReview dependencies reported by the downloader and keep your source changes in version control.
Usage
import { useForm } from "react-hook-form";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import {
Form,
FormField,
FormItem,
FormLabel,
FormControl,
FormMessage,
} from "@/components/ui/form";
import { cn } from "@frontfriend/sdk/cn";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
const FiltersSchema = z.object({
login: z.string().min(2, { message: "Login must be at least 2 characters" }),
password: z
.string()
.min(2, { message: "Password must be at least 2 characters" }),
});
function FormVertical({
orientation,
}: {
orientation?: "vertical" | "horizontal";
}) {
const emptyValue = {
login: "",
string: "",
};
const form = useForm<z.infer<typeof FiltersSchema>>({
resolver: zodResolver(FiltersSchema),
defaultValues: emptyValue,
});
function onSubmit(values: z.infer<typeof FiltersSchema>) {
console.log(values);
}
return (
<div>
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className={cn(
"flex gap-8 self-stretch w-full",
orientation === "horizontal"
? "flex-row items-end"
: "flex-col items-start",
)}
id="filters_form"
>
<FormField
control={form.control}
name="login"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>Login</FormLabel>
<FormControl>
<Input className="w-full" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="password"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>Password</FormLabel>
<FormControl>
<Input className="w-full" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button
type="submit"
className={cn(orientation === "horizontal" ? "w-fit" : "w-full")}
variant="main"
>
Submit
</Button>
</form>
</Form>
</div>
);
}
<FormVertical orientation="vertical" />; Examples
Default
import { useForm } from "react-hook-form";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import {
Form,
FormField,
FormItem,
FormLabel,
FormControl,
FormMessage,
} from "@/components/ui/form";
import { cn } from "@frontfriend/sdk/cn";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
const FiltersSchema = z.object({
login: z.string().min(2, { message: "Login must be at least 2 characters" }),
password: z
.string()
.min(2, { message: "Password must be at least 2 characters" }),
});
function FormVertical({
orientation,
}: {
orientation?: "vertical" | "horizontal";
}) {
const emptyValue = {
login: "",
string: "",
};
const form = useForm<z.infer<typeof FiltersSchema>>({
resolver: zodResolver(FiltersSchema),
defaultValues: emptyValue,
});
function onSubmit(values: z.infer<typeof FiltersSchema>) {
console.log(values);
}
return (
<div>
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className={cn(
"flex gap-8 self-stretch w-full",
orientation === "horizontal"
? "flex-row items-end"
: "flex-col items-start",
)}
id="filters_form"
>
<FormField
control={form.control}
name="login"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>Login</FormLabel>
<FormControl>
<Input className="w-full" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="password"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>Password</FormLabel>
<FormControl>
<Input className="w-full" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button
type="submit"
className={cn(orientation === "horizontal" ? "w-fit" : "w-full")}
variant="main"
>
Submit
</Button>
</form>
</Form>
</div>
);
}
<FormVertical orientation="vertical" />; Horizontal
import { useForm } from "react-hook-form";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import {
Form,
FormField,
FormItem,
FormLabel,
FormControl,
FormMessage,
} from "@/components/ui/form";
import { cn } from "@frontfriend/sdk/cn";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
const FiltersSchema = z.object({
login: z.string().min(2, { message: "Login must be at least 2 characters" }),
password: z
.string()
.min(2, { message: "Password must be at least 2 characters" }),
});
function FormVertical({
orientation,
}: {
orientation?: "vertical" | "horizontal";
}) {
const emptyValue = {
login: "",
string: "",
};
const form = useForm<z.infer<typeof FiltersSchema>>({
resolver: zodResolver(FiltersSchema),
defaultValues: emptyValue,
});
function onSubmit(values: z.infer<typeof FiltersSchema>) {
console.log(values);
}
return (
<div>
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className={cn(
"flex gap-8 self-stretch w-full",
orientation === "horizontal"
? "flex-row items-end"
: "flex-col items-start",
)}
id="filters_form"
>
<FormField
control={form.control}
name="login"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>Login</FormLabel>
<FormControl>
<Input className="w-full" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="password"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>Password</FormLabel>
<FormControl>
<Input className="w-full" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button
type="submit"
className={cn(orientation === "horizontal" ? "w-fit" : "w-full")}
variant="main"
>
Submit
</Button>
</form>
</Form>
</div>
);
}
<FormVertical orientation="horizontal" />; API reference
Frontfriend-owned props. Native HTML and inherited primitive props remain documented by Base UI.
FormItem
| Prop | Type | Default | Description |
|---|---|---|---|
orientation | "vertical" | "horizontal" | "vertical" |
FormLabel
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "main" | "secondary" | — |
Configuration determines the actual classes and available styling hooks. See Theming & component configuration before introducing a repeated local override.