# LambdaCurry Forms - Complete Implementation Guide for LLMs
This comprehensive guide covers everything needed to implement forms using the `@lambdacurry/forms` remix-hook-form components, including the new FormError component for form-level error handling. This documentation is specifically designed for LLMs to understand all features, patterns, and best practices.
## Core Architecture Overview
The library provides **form-aware wrapper components** in the `remix-hook-form` directory that automatically integrate with React Router forms and Remix Hook Form context. These components eliminate boilerplate while maintaining full customization capabilities.
### Key Principle: Zero Boilerplate Form Integration
- Components automatically access form context via `useRemixFormContext()`
- No need to manually pass `control` props
- Automatic error handling and validation display
- Built-in accessibility features
## Form-Level Error Handling with FormError
The `FormError` component provides standardized form-level error handling, complementing the existing field-level error system.
### FormError Component Usage
```typescript
// Import form-aware FormError component
import { FormError } from '@lambdacurry/forms';
// Basic usage - looks for errors._form by default
// Custom error key
// With custom styling and placement
// With custom component override
```
### Server Action Pattern for Form-Level Errors
```typescript
export const action = async ({ request }: ActionFunctionArgs) => {
const { data, errors } = await getValidatedFormData(
request,
zodResolver(formSchema)
);
// Return field-level validation errors
if (errors) {
return { errors };
}
// Business logic validation
try {
await processForm(data);
return { message: 'Success!' };
} catch (error) {
// Return form-level error using _form key
return {
errors: {
_form: { message: 'Unable to process form. Please try again.' }
}
};
}
};
```
### Error Hierarchy Guidelines
**Field-Level Errors (use FormMessage automatically in form components):**
- Validation errors: "Email is required", "Password too short"
- Format errors: "Invalid email format"
- Field-specific business rules: "Username already taken"
**Form-Level Errors (use FormError component):**
- Server errors: "Server temporarily unavailable"
- Authentication failures: "Invalid credentials"
- Network issues: "Connection timeout"
- General business logic: "Account suspended"
- Rate limiting: "Too many attempts, try again later"
## Basic Form Setup Pattern
## Import Structure
The `@lambdacurry/forms` library follows a clear import structure:
### Form-Aware Components (from `@lambdacurry/forms`)
These components automatically integrate with React Router forms and Remix Hook Form context:
- `TextField` - Form-aware text input with automatic validation
- `Textarea` - Form-aware textarea with automatic validation
- `Checkbox` - Form-aware checkbox with automatic validation
- `Switch` - Form-aware switch/toggle with automatic validation
- `RadioGroup` - Form-aware radio group with automatic validation
- `RadioGroupItem` - Individual radio items for RadioGroup
- `DatePicker` - Form-aware date picker with automatic validation
- `DropdownMenuSelect` - Form-aware dropdown select with automatic validation
- `OtpInput` - Form-aware OTP/PIN input with automatic validation
- `FormError` - Component for displaying form-level errors
- `FormLabel`, `FormControl`, `FormDescription`, `FormMessage` - Form field components
- `useFormField` - Hook for accessing form field context
- Data table components: `DataTableRouterForm`, `DataTableRouterToolbar`, etc.
### UI Components (from `@lambdacurry/forms/ui`)
These are the underlying UI components without form integration:
- `Button` - Button component with variants
- `Calendar` - Calendar component for date selection
- `Badge` - Badge/chip component for labels
- `Dialog` - Modal dialog component
- `Popover` - Popover/tooltip component
- `Select` - Basic select dropdown
- `Separator` - Visual separator/divider
- `Slider` - Range slider component
- `Table` - Table components for data display
- `Tabs` - Tab navigation component
- `Command` - Command palette/search component
- Field variants: `CheckboxField`, `TextareaField`, `TextField`, `SwitchField`, etc.
- And many more UI primitives
## Component Reference
### Complete List of Form-Aware Components (`@lambdacurry/forms`)
```typescript
// Form input components (automatically integrate with form context)
import {
TextField, // Text input with validation
Textarea, // Multi-line text input with validation
Checkbox, // Checkbox with validation
Switch, // Toggle switch with validation
RadioGroup, // Radio button group with validation
RadioGroupItem, // Individual radio button
DatePicker, // Date selection with validation
DropdownMenuSelect, // Dropdown select with validation
OtpInput, // OTP/PIN input with validation
// Form structure components
FormError, // Form-level error display
FormLabel, // Form field labels
FormControl, // Form field wrapper
FormDescription, // Form field descriptions
FormMessage, // Form field error messages
useFormField, // Hook for form field context
// Data table components
DataTableRouterForm,
DataTableRouterToolbar,
useDataTableUrlState,
} from '@lambdacurry/forms';
```
### Complete List of UI Components (`@lambdacurry/forms/ui`)
```typescript
// Basic UI components (no form integration)
import {
// Buttons and actions
Button, // Button with variants
// Form inputs (non-form-aware versions)
CheckboxField, // Checkbox without form integration
TextareaField, // Textarea without form integration
TextField, // Text input without form integration
SwitchField, // Switch without form integration
RadioGroupField, // Radio group without form integration
DatePickerField, // Date picker without form integration
DropdownMenuSelectField, // Dropdown without form integration
OtpInputField, // OTP input without form integration
FormErrorField, // Error display without form integration
// Layout and navigation
Dialog, // Modal dialogs
Popover, // Popover/tooltips
Tabs, // Tab navigation
Separator, // Visual dividers
// Data display
Table, // Table components
Badge, // Labels and badges
Calendar, // Calendar component
// Form primitives
Label, // Basic labels
Select, // Basic select dropdown
Slider, // Range slider
Command, // Command palette
// Data table system
DataTable, // Data table components
DataTableFilter, // Table filtering
// Utilities
DebouncedInput, // Debounced input
} from '@lambdacurry/forms/ui';
```
### 1. Required Imports
```typescript
import { zodResolver } from '@hookform/resolvers/zod';
import { RemixFormProvider, useRemixForm, getValidatedFormData } from 'remix-hook-form';
import { z } from 'zod';
import { useFetcher, type ActionFunctionArgs } from 'react-router';
// Import form-aware components from main package
import { TextField, Checkbox, FormError } from '@lambdacurry/forms';
// Import UI components from /ui subpath
import { Button } from '@lambdacurry/forms/ui';
```
### 2. Zod Schema Definition
```typescript
const formSchema = z.object({
username: z.string().min(3, 'Username must be at least 3 characters'),
email: z.string().email('Invalid email address'),
terms: z.boolean().refine(val => val === true, 'You must accept the terms'),
age: z.coerce.number().min(18, 'Must be at least 18 years old'),
});
type FormData = z.infer;
```
### 3. Complete Login Form Example with FormError
```typescript
const LoginForm = () => {
const fetcher = useFetcher<{
message?: string;
errors?: Record
}>();
const methods = useRemixForm({
resolver: zodResolver(formSchema),
defaultValues: {
email: '',
password: '',
},
fetcher,
submitConfig: {
action: '/login',
method: 'post',
},
});
const isSubmitting = fetcher.state === 'submitting';
return (
);
};
// Server action handler
export const action = async ({ request }: ActionFunctionArgs) => {
const { data, errors } = await getValidatedFormData(
request,
zodResolver(formSchema)
);
if (errors) {
return { errors };
}
// Additional server-side validation
const existingUser = await getUserByEmail(data.email);
if (existingUser) {
return {
errors: {
email: { message: 'This email address is already registered' }
}
};
}
try {
// Create user account
const user = await createUser({
firstName: data.firstName,
lastName: data.lastName,
email: data.email,
birthDate: data.birthDate,
accountType: data.accountType,
country: data.country,
bio: data.bio,
preferences: {
notifications: data.notifications,
newsletter: data.newsletter,
},
});
return {
message: 'Account created successfully! Welcome aboard!',
redirectTo: '/dashboard'
};
} catch (error) {
console.error('Account creation failed:', error);
return {
errors: {
_form: { message: 'Failed to create account. Please try again.' }
}
};
}
};
export default ComprehensiveForm;
```
**This example demonstrates:**
- ✅ All major form components (TextField, Textarea, Checkbox, RadioGroup, DatePicker, DropdownMenuSelect)
- ✅ Complex validation with Zod schemas
- ✅ Conditional field display based on form values
- ✅ Custom submit handlers with data transformation
- ✅ Loading states and disabled inputs during submission
- ✅ Error handling for both client and server-side validation
- ✅ Success messages and redirect handling
- ✅ Responsive layout with proper spacing and styling
- ✅ Accessibility features built-in to all components
This comprehensive example serves as a complete reference for implementing any form using the LambdaCurry Forms library!
---
## Key Implementation Notes for LLMs
### Essential Patterns to Follow:
1. **Form Provider Setup**
```typescript
{/* Form components */}
```
2. **Error Handling**
- Errors display automatically via `FormMessage` component
- Server errors: `return { errors }` from action
- Field-specific: `errors.fieldName.message`
- Form-level: `errors._form.message`
3. **Loading States**
```typescript
const isSubmitting = fetcher.state === 'submitting';
```
4. **Conditional Fields**
```typescript
const watchValue = methods.watch('fieldName');
{watchValue === 'condition' && }
```
5. **Data Transformation**
```typescript
submitHandlers: {
onValid: (data) => {
const transformed = { ...data, computed: 'value' };
fetcher.submit(createFormData(transformed), { method: 'post' });
}
}
```
6. **Server Validation**
```typescript
export const action = async ({ request }) => {
const { data, errors } = await getValidatedFormData(request, zodResolver(schema));
if (errors) return { errors };
// Process data...
};
```
7. **FormError Placement Options**
```typescript
// Below inputs, above submit button (most common)
// Between sections
// Top of form (for critical errors that need immediate attention)
// Multiple placements with different styling
```
8. **Custom FormError Styling**
```typescript
const CustomErrorMessage = (props: React.ComponentPropsWithoutRef) => (
);
```
9. **Server Action Error Patterns**
```typescript
// Field-level error
return {
errors: {
email: { message: 'Email already exists' }
}
};
// Form-level error
return {
errors: {
_form: { message: 'Server error occurred' }
}
};
// Multiple error types
return {
errors: {
email: { message: 'Email already exists' },
_form: { message: 'Please fix the errors above' }
}
};
```
## FormError Best Practices
### 1. Error Key Conventions
- Use `_form` for general form-level errors
- Use descriptive keys for specific categories (`payment`, `shipping`, `auth`)
- Be consistent across your application
### 2. Error Message Guidelines
- **Be specific**: "Server temporarily unavailable" vs "Error occurred"
- **Be actionable**: "Please try again in a few minutes" vs "Failed"
- **Be user-friendly**: Avoid technical jargon and error codes
### 3. Placement Strategy
- **Below inputs, above submit button**: Most common placement - users see errors after completing form fields but before submitting
- **Top placement**: For critical errors that need immediate attention before users start filling the form
- **Inline placement**: For contextual errors related to specific sections
- **Multiple placements**: FormError can be placed anywhere in the form and styled differently for various use cases
### 4. Component Integration
- FormError works seamlessly with all existing form components
- Maintains the same component override pattern as other form components
- Automatically integrates with form context and validation state
### Important Reminders:
- 🔥 **Import form-aware components from `@lambdacurry/forms`** - these automatically integrate with form context
- 🔥 **Import UI components from `@lambdacurry/forms/ui`** - these are the underlying UI primitives
- 🔥 **Use `createFormData()` for custom submissions** to ensure proper formatting
- 🔥 **All components are accessible by default** - no additional ARIA setup needed
- 🔥 **Form context is automatic** - no need to pass `control` props manually
- 🔥 **FormError provides form-level error handling** - use it for server errors, auth failures, and general business logic errors
This comprehensive guide provides everything needed to implement forms with both field-level and form-level error handling using the LambdaCurry Forms library!