Skip to main content

Overview

Solarecliente provides a complete set of form components with built-in validation, error handling, and accessibility features. All form components integrate seamlessly with popular form libraries like React Hook Form and Formik.

Form Component

The base Form component provides form state management and submission handling.

Basic Usage

import { Form } from '@/components/forms';

function ClientForm() {
  const handleSubmit = (data) => {
    console.log('Form data:', data);
  };

  return (
    <Form onSubmit={handleSubmit}>
      {/* Form fields */}
    </Form>
  );
}

Props

onSubmit
function
required
Callback function invoked when form is submitted with validated data
initialValues
object
Initial values for form fields
validationSchema
object
Validation schema (Yup or Zod)
className
string
Additional CSS classes to apply to the form

Input Component

The Input component supports various input types with validation and error display.
<Input
  name="clientName"
  label="Client Name"
  placeholder="Enter client name"
  required
/>

Input Props

name
string
required
Unique identifier for the input field
label
string
required
Label text displayed above the input
type
string
default:"text"
Input type: text, email, password, number, tel, url
placeholder
string
Placeholder text displayed when input is empty
required
boolean
default:false
Whether the field is required
disabled
boolean
default:false
Whether the input is disabled
error
string
Error message to display below the input
helperText
string
Helper text displayed below the input

Select Component

Dropdown select component with support for single and multi-select.
<Select
  name="status"
  label="Client Status"
  options={[
    { value: 'active', label: 'Active' },
    { value: 'inactive', label: 'Inactive' },
    { value: 'pending', label: 'Pending' },
  ]}
  placeholder="Select status"
/>

Select Props

options
array
required
Array of options with value and label properties
multiple
boolean
default:false
Enable multi-select functionality
searchable
boolean
default:false
Enable search/filter functionality
clearable
boolean
default:false
Show clear button to reset selection

Textarea Component

Multi-line text input for longer content.
<Textarea
  name="notes"
  label="Additional Notes"
  placeholder="Enter any additional information"
  rows={4}
  maxLength={500}
/>

Textarea Props

rows
number
default:3
Number of visible text rows
maxLength
number
Maximum character count
showCharCount
boolean
default:false
Display character counter

Checkbox Component

<Checkbox
  name="terms"
  label="I agree to the terms and conditions"
  required
/>

Checkbox Group

<CheckboxGroup
  name="features"
  label="Required Features"
  options={[
    { value: 'monitoring', label: 'Real-time Monitoring' },
    { value: 'analytics', label: 'Analytics Dashboard' },
    { value: 'alerts', label: 'Email Alerts' },
  ]}
/>

Radio Component

<RadioGroup
  name="installationType"
  label="Installation Type"
  options={[
    { value: 'residential', label: 'Residential' },
    { value: 'commercial', label: 'Commercial' },
    { value: 'industrial', label: 'Industrial' },
  ]}
  required
/>

DatePicker Component

<DatePicker
  name="installationDate"
  label="Installation Date"
  minDate={new Date()}
  format="MM/DD/YYYY"
  placeholder="Select date"
/>

DatePicker Props

minDate
Date
Minimum selectable date
maxDate
Date
Maximum selectable date
format
string
default:"MM/DD/YYYY"
Date display format
showTimeSelect
boolean
default:false
Enable time selection

Form Validation

Using Zod Schema

import { z } from 'zod';
import { useForm } from '@/hooks/useForm';

const clientSchema = z.object({
  name: z.string().min(2, 'Name must be at least 2 characters'),
  email: z.string().email('Invalid email address'),
  phone: z.string().regex(/^\d{10}$/, 'Phone must be 10 digits'),
  installationDate: z.date().min(new Date(), 'Date must be in the future'),
  panelCount: z.number().min(1).max(100),
});

function ClientForm() {
  const { register, handleSubmit, errors } = useForm({
    schema: clientSchema,
  });

  return (
    <Form onSubmit={handleSubmit}>
      <Input
        {...register('name')}
        label="Client Name"
        error={errors.name?.message}
      />
      <Input
        {...register('email')}
        type="email"
        label="Email"
        error={errors.email?.message}
      />
      {/* Additional fields */}
    </Form>
  );
}

Custom Validation

const validatePhone = (value: string) => {
  if (!/^\d{10}$/.test(value)) {
    return 'Phone number must be 10 digits';
  }
  return true;
};

<Input
  name="phone"
  label="Phone Number"
  validate={validatePhone}
/>

Complete Form Example

import { Form, Input, Select, DatePicker, Textarea, Button } from '@/components';
import { z } from 'zod';

const schema = z.object({
  clientName: z.string().min(2),
  email: z.string().email(),
  phone: z.string().regex(/^\d{10}$/),
  serviceType: z.string(),
  installationDate: z.date(),
  panelCount: z.number().min(1).max(100),
  notes: z.string().optional(),
});

function NewClientForm() {
  const handleSubmit = async (data) => {
    try {
      await createClient(data);
      toast.success('Client created successfully');
    } catch (error) {
      toast.error('Failed to create client');
    }
  };

  return (
    <Form
      validationSchema={schema}
      onSubmit={handleSubmit}
      className="max-w-2xl mx-auto"
    >
      <div className="grid grid-cols-2 gap-4">
        <Input
          name="clientName"
          label="Client Name"
          placeholder="John Doe"
          required
        />
        <Input
          name="email"
          type="email"
          label="Email Address"
          placeholder="john@example.com"
          required
        />
        <Input
          name="phone"
          type="tel"
          label="Phone Number"
          placeholder="1234567890"
          required
        />
        <Select
          name="serviceType"
          label="Service Type"
          options={[
            { value: 'installation', label: 'Installation' },
            { value: 'maintenance', label: 'Maintenance' },
            { value: 'repair', label: 'Repair' },
          ]}
          required
        />
        <DatePicker
          name="installationDate"
          label="Installation Date"
          minDate={new Date()}
          required
        />
        <Input
          name="panelCount"
          type="number"
          label="Number of Panels"
          min={1}
          max={100}
          required
        />
      </div>
      <Textarea
        name="notes"
        label="Additional Notes"
        placeholder="Any special requirements or notes"
        rows={4}
      />
      <div className="flex gap-3 justify-end">
        <Button type="button" variant="secondary">
          Cancel
        </Button>
        <Button type="submit" variant="primary">
          Create Client
        </Button>
      </div>
    </Form>
  );
}

Best Practices

Validate Early

Use client-side validation to provide immediate feedback to users

Clear Error Messages

Write descriptive error messages that help users fix issues

Accessibility

Always include proper labels and ARIA attributes for screen readers

Loading States

Disable form inputs and show loading indicators during submission

Build docs developers (and LLMs) love