Form
Shadcn ui: Form
Default
Saved
Saved locallyimport { zodResolver } from "@hookform/resolvers/zod" import { useForm } from "react-hook-form" import { z } from "zod" import { useEffect, useState } from "react" import { Toaster as Sonner } from "sonner" import { CircleCheckIcon, InfoIcon, Loader2Icon, OctagonXIcon, TriangleAlertIcon, } from "lucide-react" import { Button } from "@/components/ui/button" import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form" import { Input } from "@/components/ui/input" import { toast } from "sonner" // Simple Toaster wrapper that works in Sandpack without next-themes function SandpackToaster() { const [theme, setTheme] = useState<"light" | "dark">("light") useEffect(() => { const checkTheme = () => { const isDark = document.documentElement.classList.contains("dark") setTheme(isDark ? "dark" : "light") } checkTheme() const observer = new MutationObserver(checkTheme) observer.observe(document.documentElement, { attributes: true, attributeFilter: ["class"], }) return () => observer.disconnect() }, []) return ( <Sonner position="top-left" theme={theme} icons={{ success: <CircleCheckIcon className="size-4" />, info: <InfoIcon className="size-4" />, warning: <TriangleAlertIcon className="size-4" />, error: <OctagonXIcon className="size-4" />, loading: <Loader2Icon className="size-4 animate-spin" />, }} style={ { "--normal-bg": "var(--popover)", "--normal-text": "var(--popover-foreground)", "--normal-border": "var(--border)", "--border-radius": "var(--radius)", } as React.CSSProperties } /> ) } const FormSchema = z.object({ username: z.string().min(2, { message: "Username must be at least 2 characters.", }), }) export default function FormPreview() { const form = useForm<z.infer<typeof FormSchema>>({ resolver: zodResolver(FormSchema), defaultValues: { username: "", }, }) function onSubmit(data: z.infer<typeof FormSchema>) { toast("You submitted the following values:", { description: ( <pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4"> <code className="text-white">{JSON.stringify(data, null, 2)}</code> </pre> ), }) } return ( <> <SandpackToaster /> <Form {...form}> <form onSubmit={form.handleSubmit(onSubmit)} className="w-2/3 space-y-6"> <FormField control={form.control} name="username" render={({ field }) => ( <FormItem> <FormLabel>Username</FormLabel> <FormControl> <Input placeholder="shadcn" {...field} /> </FormControl> <FormDescription> This is your public display name. </FormDescription> <FormMessage /> </FormItem> )} /> <Button type="submit">Submit</Button> </form> </Form> </> ) } export default function App() { return <FormPreview />; }