Skip to main content

Overview

The Smart Form component provides a complete form solution with Zod schema validation, TanStack Query integration for mutations, and support for multiple field types. It automatically handles loading states, error handling, and cache invalidation.

Installation

npx shadcn@latest add https://rigidui.com/r/smart-form.json

Usage

import { SmartForm, SmartFormField } from "@/components/smart-form"
import { z } from "zod"

const userSchema = z.object({
  name: z.string().min(2, "Name must be at least 2 characters"),
  email: z.string().email("Invalid email address"),
  role: z.enum(["admin", "user", "moderator"]),
  isActive: z.boolean(),
})

type UserFormData = z.infer<typeof userSchema>

export default function MyForm() {
  const handleSubmit = async (data: UserFormData) => {
    await new Promise(resolve => setTimeout(resolve, 1000))
    console.log('Form submitted:', data)
    return { success: true, data }
  }

  return (
    <div className="max-w-md">
      <SmartForm
        schema={userSchema}
        mutationFn={handleSubmit}
        onSuccess={(data) => console.log("Success:", data)}
      >
        {(form) => (
          <>
            <SmartFormField
              form={form}
              name="name"
              type="text"
              label="Name"
              placeholder="Enter your name"
            />
            <SmartFormField
              form={form}
              name="email"
              type="email"
              label="Email"
              placeholder="Enter your email"
            />
            <SmartFormField
              form={form}
              name="role"
              type="select"
              label="Role"
              options={[
                { value: "admin", label: "Admin" },
                { value: "user", label: "User" },
                { value: "moderator", label: "Moderator" },
              ]}
            />
            <SmartFormField
              form={form}
              name="isActive"
              type="checkbox"
              label="Active user"
            />
          </>
        )}
      </SmartForm>
    </div>
  )
}

Features

Zod Schema Validation

Built-in integration with Zod for runtime type safety and comprehensive validation rules.

TanStack Query Integration

Seamless integration with TanStack Query for mutations, loading states, and cache invalidation.

Multiple Field Types

Support for text, email, password, number, textarea, select, checkbox, radio, and color field types.

TypeScript Support

Full TypeScript support with type inference from Zod schemas for complete type safety.

Conditional Fields

Show/hide fields based on other field values using the ConditionalField component.

Form Sections

Organize complex forms into logical sections with titles and descriptions.

API Reference

SmartForm

The main form component that handles validation, submission, and state management.
schema
z.ZodSchema<T>
required
Zod schema for form validation and type safety.
mutationFn
(data: T) => Promise<any>
required
Async function to handle form submission (API call).
children
(form: UseFormReturn<T>) => React.ReactNode
required
Render function that receives the form instance for building form fields.
queryKey
string[]
default:"[]"
TanStack Query key for cache invalidation after successful submission.
mode
'create' | 'edit'
default:"'create'"
Form mode that affects submit button text and behavior.
defaultValues
Partial<T>
Default values for form fields.
onSuccess
(data: any) => void
Callback function called on successful form submission.
onError
(error: Error) => void
Callback function called when form submission fails.
submitText
string
Custom text for submit button (overrides mode-based text).
className
string
Additional CSS classes for the form container.

SmartFormField

Renders individual form fields with appropriate input components.
form
UseFormReturn<T>
required
React Hook Form instance passed from SmartForm.
name
FieldPath<T>
required
Field name that matches the schema property.
type
'text' | 'email' | 'password' | 'number' | 'textarea' | 'select' | 'checkbox' | 'radio' | 'color'
required
Input type that determines the rendered field component.
label
string
Label text displayed above the field.
placeholder
string
Placeholder text for input fields.
description
string
Help text displayed below the field.
options
FormFieldOption[]
default:"[]"
Options for select and radio field types.
disabled
boolean
default:"false"
Whether the field is disabled.
className
string
Additional CSS classes for the field container.

ConditionalField

Conditionally renders fields based on other field values.
form
UseFormReturn<T>
required
React Hook Form instance passed from SmartForm.
when
FieldPath<T>
required
The field name to watch for changes.
equals
any
required
The value to compare against the watched field.
children
React.ReactNode
required
Content to render when the condition is met.

FormSection

Groups related fields into logical sections.
title
string
required
The title text displayed for the form section.
children
React.ReactNode
required
Form fields and other content to display in the section.
description
string
Optional description text displayed below the title.
className
string
Additional CSS classes for styling the section.

TypeScript Interfaces

SmartFormProps

interface SmartFormProps<T extends FieldValues = FieldValues> {
  schema: z.ZodSchema<T>
  mutationFn: (data: T) => Promise<any>
  queryKey?: string[]
  mode?: 'create' | 'edit'
  defaultValues?: Partial<T>
  onSuccess?: (data: any) => void
  onError?: (error: Error) => void
  submitText?: string
  className?: string
  children: (form: UseFormReturn<T>) => React.ReactNode
}

FormFieldOption

interface FormFieldOption {
  value: string
  label: string
}

Advanced Examples

Conditional Fields

import { SmartForm, SmartFormField, ConditionalField } from "@/components/smart-form"
import { z } from "zod"

const schema = z.object({
  role: z.enum(["admin", "user"]),
  adminCode: z.string().optional(),
  email: z.string().email(),
})

export default function ConditionalForm() {
  return (
    <SmartForm schema={schema} mutationFn={handleSubmit}>
      {(form) => (
        <>
          <SmartFormField form={form} name="role" type="select" label="Role"
            options={[
              { value: "admin", label: "Admin" },
              { value: "user", label: "User" },
            ]}
          />
          
          <ConditionalField form={form} when="role" equals="admin">
            <SmartFormField
              form={form}
              name="adminCode"
              type="password"
              label="Admin Code"
              description="Required for admin access"
            />
          </ConditionalField>
          
          <SmartFormField form={form} name="email" type="email" label="Email" />
        </>
      )}
    </SmartForm>
  )
}

Form Sections

import { SmartForm, SmartFormField, FormSection } from "@/components/smart-form"
import { z } from "zod"

const schema = z.object({
  firstName: z.string(),
  lastName: z.string(),
  email: z.string().email(),
  company: z.string(),
  position: z.string(),
})

export default function SectionedForm() {
  return (
    <SmartForm schema={schema} mutationFn={handleSubmit}>
      {(form) => (
        <>
          <FormSection title="Personal Information" description="Basic details about you">
            <SmartFormField form={form} name="firstName" type="text" label="First Name" />
            <SmartFormField form={form} name="lastName" type="text" label="Last Name" />
            <SmartFormField form={form} name="email" type="email" label="Email" />
          </FormSection>
          
          <FormSection title="Professional Information" description="Your work details">
            <SmartFormField form={form} name="company" type="text" label="Company" />
            <SmartFormField form={form} name="position" type="text" label="Position" />
          </FormSection>
        </>
      )}
    </SmartForm>
  )
}
The SmartForm component automatically handles form state management, validation, and submission. You only need to focus on defining your schema and fields.
When using with TanStack Query, provide a queryKey to automatically invalidate cached data after successful form submission.
Always validate data on the server-side in addition to client-side Zod validation for security purposes.

Build docs developers (and LLMs) love