# KLZ Forms System A comprehensive, reusable form system for Next.js applications with full TypeScript support, accessibility features, and consistent styling. ## Features - **Complete Form Components**: All essential form inputs with consistent styling - **Validation System**: Built-in validation with custom rules - **Type Safety**: Full TypeScript support - **Accessibility**: ARIA attributes and keyboard navigation - **Internationalization**: Ready for i18n - **Customizable**: Flexible props for different use cases - **Animation**: Smooth transitions and animations - **Error Handling**: Multiple error display modes - **Auto-resize**: Smart textarea resizing - **Character Count**: Built-in character counting ## Installation The form system is already included in the project. All components use the existing design system tokens. ## Components ### FormField Wrapper component that provides consistent form field experience. ```tsx setValue(e.target.value)} /> ``` **Supported Types**: `text`, `email`, `tel`, `textarea`, `select`, `checkbox`, `radio`, `number`, `password`, `date`, `time`, `url` ### FormInput Base input component with icon support and clear button. ```tsx } showClear value={value} onChange={handleChange} /> ``` ### FormTextarea Textarea with auto-resize and character counting. ```tsx ``` ### FormSelect Select dropdown with search and multi-select support. ```tsx ``` ### FormCheckbox Single checkbox or checkbox group with indeterminate state. ```tsx // Single checkbox setChecked(values.length > 0)} /> // Checkbox group setSelectedValues(values)} /> ``` ### FormRadio Radio button group with custom styling. ```tsx setValue(value)} /> ``` ### FormError Error message display with multiple variants. ```tsx ``` ### FormSuccess Success message with auto-dismiss option. ```tsx setShowSuccess(false)} /> ``` ## Hooks ### useForm Main form state management hook with validation and submission handling. ```tsx const form = useForm({ initialValues: { name: '', email: '', }, validationRules: { name: { required: true, minLength: { value: 2, message: 'Too short' } }, email: { required: true, email: true }, }, onSubmit: async (values) => { // Handle submission await api.submit(values); }, }); // In your component
form.setFieldValue('name', e.target.value)} /> {form.errors.name && } ``` ### useFormField Hook for managing individual field state. ```tsx const field = useFormField({ initialValue: '', validate: (value) => value.length < 2 ? 'Too short' : null, }); // field.value, field.error, field.touched, field.handleChange, etc. ``` ### useFormValidation Validation logic and utilities. ```tsx const { validateField, validateForm } = useFormValidation(); const errors = validateField(value, { required: true, email: true, }, 'email'); ``` ## Validation Rules Available validation rules: ```typescript { required: boolean | string; // Required field minLength: { value: number, message: string }; maxLength: { value: number, message: string }; pattern: { value: RegExp, message: string }; min: { value: number, message: string }; max: { value: number, message: string }; email: boolean | string; url: boolean | string; number: boolean | string; custom: (value) => string | null; // Custom validation } ``` ## Examples ### Simple Contact Form ```tsx import { useForm, FormField, Button } from '@/components/forms'; export function ContactForm() { const form = useForm({ initialValues: { name: '', email: '', message: '' }, validationRules: { name: { required: true, minLength: { value: 2 } }, email: { required: true, email: true }, message: { required: true }, }, onSubmit: async (values) => { await sendEmail(values); alert('Sent!'); form.reset(); }, }); return (
form.setFieldValue('name', e.target.value)} /> form.setFieldValue('email', e.target.value)} /> form.setFieldValue('message', e.target.value)} /> ); } ``` ### Registration Form ```tsx import { useForm, FormField, Button } from '@/components/forms'; export function RegistrationForm() { const form = useForm({ initialValues: { firstName: '', lastName: '', email: '', password: '', confirmPassword: '', terms: false, }, validationRules: { firstName: { required: true, minLength: { value: 2 } }, lastName: { required: true, minLength: { value: 2 } }, email: { required: true, email: true }, password: { required: true, minLength: { value: 8 }, pattern: { value: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/ } }, confirmPassword: { required: true, custom: (value) => value === form.values.password ? null : 'Passwords do not match' }, terms: { required: 'You must accept terms', custom: (value) => value ? null : 'Required' }, }, onSubmit: async (values) => { await registerUser(values); alert('Registered!'); }, }); return (
form.setFieldValue('firstName', e.target.value)} /> form.setFieldValue('lastName', e.target.value)} />
form.setFieldValue('email', e.target.value)} />
form.setFieldValue('password', e.target.value)} /> form.setFieldValue('confirmPassword', e.target.value)} />
form.setFieldValue('terms', values.length > 0)} /> ); } ``` ### Search and Filter Form ```tsx import { useForm, FormField, Button } from '@/components/forms'; export function SearchForm() { const form = useForm({ initialValues: { search: '', category: '', status: '', }, validationRules: {}, onSubmit: async (values) => { await performSearch(values); }, }); const categoryOptions = [ { value: '', label: 'All' }, { value: 'cables', label: 'Cables' }, { value: 'connectors', label: 'Connectors' }, ]; return (
} showClear value={form.values.search} onChange={(e) => form.setFieldValue('search', e.target.value)} /> form.setFieldValue('category', e.target.value)} />
); } ``` ## Best Practices ### 1. Always Use FormField for Consistency ```tsx // ✅ Good // ❌ Avoid
``` ### 2. Validate Before Submit ```tsx const form = useForm({ validationRules: { email: { required: true, email: true }, }, onSubmit: async (values) => { // Validation happens automatically // Only called if isValid is true }, }); ``` ### 3. Show Errors Only After Touch ```tsx {form.touched.email && form.errors.email && ( )} ``` ### 4. Disable Submit When Invalid ```tsx ``` ### 5. Reset After Success ```tsx onSubmit: async (values) => { await submit(values); form.reset(); } ``` ## Accessibility All components include: - Proper ARIA attributes - Keyboard navigation support - Focus management - Screen reader support - Required field indicators ## Styling Components use the design system: - Colors: `--color-primary`, `--color-danger`, `--color-success` - Spacing: `--spacing-sm`, `--spacing-md`, etc. - Typography: `--font-size-sm`, `--font-size-base` - Borders: `--radius-md` - Transitions: `--transition-fast` ## TypeScript Support Full TypeScript support with proper interfaces: ```typescript import type { FormFieldProps, FormInputProps, ValidationRules, FormErrors } from '@/components/forms'; ``` ## Testing Example test setup: ```tsx import { render, screen, fireEvent } from '@testing-library/react'; import { useForm } from '@/components/forms'; test('form validation', () => { const TestComponent = () => { const form = useForm({ initialValues: { email: '' }, validationRules: { email: { required: true, email: true } }, onSubmit: jest.fn(), }); return (
form.setFieldValue('email', e.target.value)} />
); }; render(); const input = screen.getByRole('textbox'); fireEvent.change(input, { target: { value: 'invalid' } }); // Validation should trigger }); ``` ## Performance Tips 1. **Memoize validation rules** if they depend on external values 2. **Use useCallback** for event handlers 3. **Avoid unnecessary re-renders** by splitting large forms 4. **Lazy load** form examples for better initial load ## Migration from Legacy Forms If migrating from old form components: ```tsx // Old setEmail(e.target.value)} className={error ? 'error' : ''} /> // New form.setFieldValue('email', e.target.value)} /> ``` ## Troubleshooting ### Common Issues 1. **Validation not working**: Ensure `validationRules` match `initialValues` keys 2. **Form not submitting**: Check `isValid` state and `required` fields 3. **Type errors**: Import proper types from the forms module 4. **Styling issues**: Ensure design system CSS is imported ### Getting Help Check the examples in `FormExamples.tsx` for complete implementations. ## License Internal KLZ Cables component system