@zuilib/form
v0.0.0
Published
Form components for @zuilib component library - Built on react-hook-form.
Downloads
10
Maintainers
Readme
@zuilib/form - Form Components for ZUI
React Hook Form integration components for the ZUI design system.
Installation
# Install both packages
pnpm add @zuilib/core @zuilib/form react-hook-formUsage
Basic Example
import { useForm } from 'react-hook-form'
import Form from '@zuilib/form/form'
import FormField from '@zuilib/form/form-field'
import FormControl from '@zuilib/form/form-control'
import Label from '@zuilib/core/label'
import Description from '@zuilib/core/description'
import Message from '@zuilib/core/message'
import Input from '@zuilib/core/input'
import Button from '@zuilib/core/button'
interface FormData {
email: string
password: string
}
function LoginForm() {
const form = useForm<FormData>({
defaultValues: {
email: '',
password: ''
}
})
const onSubmit = (data: FormData) => {
console.log(data)
}
return (
<Form form={form} onSubmit={onSubmit}>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormControl>
<Label>Email</Label>
<Input {...field} type="email" placeholder="[email protected]" />
<Description>We'll never share your email.</Description>
<Message />
</FormControl>
)}
/>
<FormField
control={form.control}
name="password"
render={({ field }) => (
<FormControl>
<Label required>Password</Label>
<Input {...field} type="password" />
<Message />
</FormControl>
)}
/>
<Button type="submit">Login</Button>
</Form>
)
}Component Examples
Input
<FormField
control={form.control}
name="username"
render={({ field }) => (
<FormControl>
<Label>Username</Label>
<Input {...field} placeholder="Enter username" />
<Message />
</FormControl>
)}
/>Textarea
import Textarea from '@zuilib/core/textarea'
<FormField
control={form.control}
name="bio"
render={({ field }) => (
<FormControl>
<Label>Bio</Label>
<Textarea {...field} rows={4} />
<Description>Tell us about yourself</Description>
<Message />
</FormControl>
)}
/>Checkbox
import Checkbox from '@zuilib/core/checkbox'
<FormField
control={form.control}
name="terms"
render={({ field }) => (
<FormControl>
<Checkbox
checked={field.value}
onChange={field.onChange}
label="Accept terms and conditions"
/>
<Message />
</FormControl>
)}
/>Switch
import Switch from '@zuilib/core/switch'
<FormField
control={form.control}
name="notifications"
render={({ field }) => (
<FormControl>
<Switch
checked={field.value}
onChange={field.onChange}
label="Enable notifications"
description="Receive email updates"
/>
<Message />
</FormControl>
)}
/>Select (Native)
import Select from '@zuilib/core/select'
<FormField
control={form.control}
name="country"
render={({ field }) => (
<FormControl>
<Label>Country</Label>
<Select {...field}>
<option value="">Select a country</option>
<option value="us">United States</option>
<option value="ca">Canada</option>
<option value="uk">United Kingdom</option>
</Select>
<Message />
</FormControl>
)}
/>Listbox
import Listbox from '@zuilib/core/listbox'
const options = [
{ value: 'admin', label: 'Admin' },
{ value: 'user', label: 'User' },
{ value: 'guest', label: 'Guest' }
]
<FormField
control={form.control}
name="role"
render={({ field }) => (
<FormControl>
<Label>Role</Label>
<Listbox
value={field.value}
onChange={field.onChange}
options={options}
/>
<Message />
</FormControl>
)}
/>Combobox
import Combobox from '@zuilib/core/combobox'
const users = [
{ value: 1, label: 'John Doe' },
{ value: 2, label: 'Jane Smith' },
{ value: 3, label: 'Bob Johnson' }
]
<FormField
control={form.control}
name="assignee"
render={({ field }) => (
<FormControl>
<Label>Assignee</Label>
<Combobox
value={field.value}
onChange={field.onChange}
options={users}
placeholder="Search users..."
/>
<Message />
</FormControl>
)}
/>RadioGroup
import RadioGroup from '@zuilib/core/radio-group'
const plans = [
{ value: 'free', label: 'Free', description: 'Basic features' },
{ value: 'pro', label: 'Pro', description: 'Advanced features' },
{ value: 'enterprise', label: 'Enterprise', description: 'All features' }
]
<FormField
control={form.control}
name="plan"
render={({ field }) => (
<FormControl>
<RadioGroup
value={field.value}
onChange={field.onChange}
options={plans}
label="Select a plan"
/>
<Message />
</FormControl>
)}
/>RichTextarea
import RichTextArea from '@zuilib/core/rich-textarea'
<FormField
control={form.control}
name="description"
render={({ field }) => (
<FormControl>
<RichTextArea
{...field}
label="Description"
showCharCount
maxLength={500}
/>
<Message />
</FormControl>
)}
/>Form Validation
Use Zod or Yup for schema validation:
import { zodResolver } from '@hookform/resolvers/zod'
import * as z from 'zod'
const schema = z.object({
email: z.string().email('Invalid email address'),
password: z.string().min(8, 'Password must be at least 8 characters')
})
const form = useForm<FormData>({
resolver: zodResolver(schema),
defaultValues: {
email: '',
password: ''
}
})API Reference
Form
Wraps form element with FormProvider context.
Props:
form:UseFormReturn<TFieldValues>- React Hook Form instanceonSubmit:(data: TFieldValues) => void | Promise<void>- Submit handler- Standard HTML form attributes
FormField
Connects a form field to React Hook Form's Controller.
Props:
- All
Controllerprops from react-hook-form
FormControl
Layout wrapper using FormItem from @zuilib/core.
Props:
children: React.ReactNode
Label (from @zuilib/core)
Accessible label with optional required indicator and dirty state.
Props:
required:boolean- Show required asteriskisDirty:boolean- Show unsaved indicator- Standard HTML label attributes
Description (from @zuilib/core)
Helper text for form fields.
Props:
- Standard HTML paragraph attributes
Message (from @zui/core)
Error message display. Shows validation errors automatically.
Props:
error:FieldError- React Hook Form error object- Standard HTML paragraph attributes
Notes
Label,Description, andMessageare now part of@zui/coreas they're generic components- Only show
Descriptionwhen there is no errorMessage FormItemis part of@zui/coreas it's a generic layout component- Native inputs (Input, Textarea, Select) remain uncontrolled by default
- Controlled components (Checkbox, Switch, etc.) require explicit
checked/valueandonChange
License
MIT
