Form
retab-ui/formFreeComponent
React Hook Form field primitives with accessible labels, descriptions, and messages.
Install it
npx shadcn@latest add https://ui.retab.com/r/form.jsonSource
1"use client";23import * as React from "react";4import type { Label as LabelPrimitive } from "radix-ui";5import { Slot } from "radix-ui";6import {7 Controller,8 FormProvider,9 useFormContext,10 useFormState,11 type ControllerProps,12 type FieldPath,13 type FieldValues,14} from "react-hook-form";1516import { cn } from "@/lib/utils";17import { Label } from "@/components/ui/label";1819const Form = FormProvider;2021type FormFieldContextValue<22 TFieldValues extends FieldValues = FieldValues,23 TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,24> = {25 name: TName;26};2728const FormFieldContext = React.createContext<FormFieldContextValue>(29 {} as FormFieldContextValue,30);3132const FormField = <33 TFieldValues extends FieldValues = FieldValues,34 TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,35>({36 ...props37}: ControllerProps<TFieldValues, TName>) => {38 return (39 <FormFieldContext.Provider value={{ name: props.name }}>40 <Controller {...props} />41 </FormFieldContext.Provider>42 );43};4445const useFormField = () => {46 const fieldContext = React.useContext(FormFieldContext);47 const itemContext = React.useContext(FormItemContext);48 const { getFieldState } = useFormContext();49 const formState = useFormState({ name: fieldContext.name });50 const fieldState = getFieldState(fieldContext.name, formState);5152 if (!fieldContext) {53 throw new Error("useFormField should be used within <FormField>");54 }5556 const { id } = itemContext;5758 return {59 id,60 name: fieldContext.name,61 formItemId: `${id}-form-item`,62 formDescriptionId: `${id}-form-item-description`,63 formMessageId: `${id}-form-item-message`,64 ...fieldState,65 };66};6768type FormItemContextValue = {69 id: string;70};7172const FormItemContext = React.createContext<FormItemContextValue>(73 {} as FormItemContextValue,74);7576function FormItem({ className, ...props }: React.ComponentProps<"div">) {77 const id = React.useId();7879 return (80 <FormItemContext.Provider value={{ id }}>81 <div82 data-slot="form-item"83 className={cn("grid gap-2", className)}84 {...props}85 />86 </FormItemContext.Provider>87 );88}8990function FormLabel({91 className,92 ...props93}: React.ComponentProps<typeof LabelPrimitive.Root>) {94 const { error, formItemId } = useFormField();9596 return (97 <Label98 data-slot="form-label"99 data-error={!!error}100 className={cn("data-[error=true]:text-destructive", className)}101 htmlFor={formItemId}102 {...props}103// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from retab-ui
All 130 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Alertalert | retab-ui | Components | Free | 1 dep | |
| Alert Dialogalert-dialog | retab-ui | Components | Free | 1 dep | |
| Aspect Ratioaspect-ratio | retab-ui | Components | Free | no deps | |
| Attachment Sidebarattachment-sidebar | retab-ui | Components | Free | 1 dep | |
| Autocompleteautocomplete | retab-ui | Components | Free | 2 deps | |
| Calendarcalendar | retab-ui | Components | Free | 2 deps | |
| Code Viewercode-viewer | retab-ui | Components | Free | 2 deps · 32 files | |
| Commandcommand | retab-ui | Components | Free | 2 deps |
