A comprehensive form component inspired by Stripe's checkout experience that automatically generates forms from field definitions with built-in Zod validation, multiple input types, and advanced features like field grouping and conditional visibility.
Overview
The Smart Form component provides a declarative way to build complex forms with minimal boilerplate, drawing inspiration from Stripe's polished checkout experience and modern UI/UX design principles. Like Stripe's forms, it emphasizes clarity, progressive disclosure, and intuitive user flows that reduce friction and abandonment rates.
The component combines elegant visual design with robust functionality, supporting multiple input types, automatic validation with Zod schemas, field grouping, conditional visibility, and customizable layouts. Its design philosophy prioritizes user experience through thoughtful defaults, accessible interactions, and smooth validation feedback that guides users toward successful form completion.
Installation
pnpm dlx shadcn@latest add https://deltacomponents.dev/r/smart-form.json
Usage
1"use client"23import { z } from "zod"45import { FieldDefinition, SmartForm } from "@/registry/blocks/smart-form"67const schema = z.object({8 email: z.string().email("Please enter a valid email"),9 password: z.string().min(8, "Password must be at least 8 characters"),10})1112const fields: FieldDefinition[] = [13 {14 name: "email",15 label: "Email",16 type: "email",17 required: true,18 placeholder: "Enter your email",19 },20 {21 name: "password",22 label: "Password",23 type: "password",24 required: true,25 placeholder: "Enter your password",26 },27]2829export function LoginForm() {30 const handleSubmit = async (data: z.infer<typeof schema>) => {31 console.log("Form data:", data)32 }3334 return (35 <SmartForm36 fields={fields}37 schema={schema}38 onSubmit={handleSubmit}39 submitText="Sign In"40 />41 )42}
API Reference
SmartForm Props
Name | Type | Default | Description |
---|---|---|---|
fields | FieldDefinition[] | - | Array of field definitions that define the form structure |
schema | ZodSchema | - | Zod schema for form validation |
onSubmit | (data: any) => Promise<void> | void | - | Function called when form is submitted with valid data |
submitText | string | "Submit" | Text displayed on the submit button |
cancelText | string | "Cancel" | Text displayed on the cancel button |
onCancel | () => void | - | Function called when cancel button is clicked |
className | string | - | Additional CSS classes for the form container |
fieldClassName | string | - | CSS classes applied to each field container |
submitClassName | string | - | CSS classes for the submit button |
cancelClassName | string | - | CSS classes for the cancel button |
layout | "vertical" | "horizontal" | "grid" | "vertical" | Form layout style |
columns | number | 1 | Number of columns for grid layout |
gap | number | 6 | Gap between form elements |
loading | boolean | false | Whether the form is in loading state |
defaultValues | Record<string, any> | {} | Default values for form fields |
successMessage | string | - | Message displayed on successful submission |
errorMessage | string | - | Message displayed on submission error |
resetOnSuccess | boolean | false | Whether to reset form after successful submission |
hideSubmitButton | boolean | false | Whether to hide the submit button |
renderCustomField | (field, formState, handleChange) => ReactNode | - | Custom renderer for custom field types |
FieldDefinition
Base Properties
Name | Type | Default | Description |
---|---|---|---|
name | string | - | Unique field identifier |
label | string | - | Field label text |
type | FieldType | - | Type of input field |
required | boolean | false | Whether the field is required |
disabled | boolean | false | Whether the field is disabled |
description | string | - | Description text below the label |
hint | string | - | Hint text below the input |
labelVariant | "default" | "muted" | "default" | Style variant for the label |
className | string | - | CSS classes for the field container |
hidden | boolean | (values) => boolean | false | Whether to hide the field or conditional function |
group | string | - | Group name for field grouping |
width | string | number | - | Custom width for the field |
Field Types
The component supports these field types:
- Text Fields:
text
,email
,password
,number
,tel
,url
- Selection:
select
,radio
,checkbox
,switch
- Input:
textarea
,date
,file
,otp
,tags
- Custom:
custom
(with custom renderer)
Variants
Most input types support these variants:
default
: Standard shadcn/ui styling with shadows and borderspill
: Rounded styling with muted background
Special Properties by Type
Text Fields (text
, email
, password
, etc.):
placeholder
: Placeholder textdefaultValue
: Default text valuevariant
: Input variant style
Select Fields:
options
: Array of{value, label, disabled?}
objectsplaceholder
: Placeholder textdefaultValue
: Default selected value
Radio Fields:
options
: Array of{value, label, description?, disabled?}
objectsorientation
:"vertical" | "horizontal"
defaultValue
: Default selected value
Checkbox/Switch Fields:
defaultChecked
: Default checked statevariant
: For switch:"pill" | "rectangular"
Textarea Fields:
placeholder
: Placeholder textrows
: Number of text rowsdefaultValue
: Default text valuesize
:"sm" | "md" | "lg"
Date Fields:
placeholder
: Placeholder textdefaultValue
: Default date valueminDate
: Minimum selectable datemaxDate
: Maximum selectable datedateFormat
: Date format string
File Fields:
accept
: Accepted file typesmultiple
: Allow multiple filesmaxSize
: Maximum file size in bytesmaxFiles
: Maximum number of filesshowPreviews
: Show file previewsshowIcons
: Show file type icons
OTP Fields:
length
: Number of digits (default: 6)maskChar
: Character for maskingmask
: Whether to mask inputautoFocus
: Auto focus first inputseparator
: Show separators between groupsgroupSize
: Size of each groupautoSubmit
: Auto submit when completeonComplete
: Callback when OTP is complete
Tags Fields:
defaultValue
: Array of default tagstriggerKey
: Key to trigger tag creation ("Enter" | "Space" | "Comma"
)
Features
Field Grouping
Group related fields together by setting the group
property:
1const fields = [2 { name: "firstName", label: "First Name", type: "text", group: "name" },3 { name: "lastName", label: "Last Name", type: "text", group: "name" },4]
Conditional Visibility
Show/hide fields based on form values:
1const fields = [2 { name: "hasAccount", label: "I have an account", type: "checkbox" },3 {4 name: "password",5 label: "Password",6 type: "password",7 hidden: (values) => !values.hasAccount,8 },9]
Custom Field Rendering
Implement custom field types with the renderCustomField
prop:
1<SmartForm2 fields={fields}3 schema={schema}4 onSubmit={handleSubmit}5 renderCustomField={(field, formState, handleChange) => {6 if (field.type === "custom") {7 return <CustomComponent {...field} onChange={handleChange} />8 }9 }}10/>
Examples
Pill Variant
Registration Form
A comprehensive example showing multiple field types, grouping, validation, switch inputs, and tags input: