Form Fields

Schema-driven form system with 53 field types, built-in validation, conditional visibility, and automatic layout generation.

Last updated: 2025-02-18

Form Fields

Certexi's form system supports 53 field types with schema-driven validation and automatic layout. Forms are defined declaratively and rendered dynamically, enabling rapid prototyping of inspection checklists, data entry screens, and configuration panels.

Schema-Driven Forms

Forms are defined using a JSON schema that specifies fields, validation rules, layout, and conditional logic:

const formSchema = {
  fields: [
    {
      name: 'transportUnitId',
      type: 'text',
      label: 'Transport Unit ID',
      required: true,
      pattern: '^TU-\\d{4}-\\d{5}$',
      placeholder: 'TU-2024-00001',
    },
    {
      name: 'weight',
      type: 'number',
      label: 'Weight (kg)',
      min: 0,
      max: 100000,
      step: 0.1,
      required: true,
    },
    {
      name: 'inspectionResult',
      type: 'select',
      label: 'Inspection Result',
      options: ['Pass', 'Fail', 'Conditional'],
      required: true,
    },
  ],
};

Form Field Sandboxes

Live examples using the same primitives that back the schema-driven form system.

Text and textarea

Text inputs
<div className="space-y-4 max-w-sm">
  <div className="space-y-2">
    <Label htmlFor="tu-id">Transport Unit ID</Label>
    <Input id="tu-id" placeholder="TU-2024-00001" />
  </div>
  <div className="space-y-2">
    <Label htmlFor="notes">Notes</Label>
    <Textarea id="notes" placeholder="Inspection observations..." rows={3} />
  </div>
</div>

Number and select

Number and select
<div className="space-y-4 max-w-sm">
  <div className="space-y-2">
    <Label htmlFor="weight">Weight (kg)</Label>
    <Input id="weight" type="number" placeholder="0.00" />
  </div>
  <div className="space-y-2">
    <Label>Inspection Result</Label>
    <Select>
      <SelectTrigger className="w-full">
        <SelectValue placeholder="Select result" />
      </SelectTrigger>
      <SelectContent>
        <SelectItem value="pass">Pass</SelectItem>
        <SelectItem value="fail">Fail</SelectItem>
        <SelectItem value="conditional">Conditional</SelectItem>
      </SelectContent>
    </Select>
  </div>
</div>

Full inspection form

Inspection form
<Card className="max-w-md">
  <CardHeader>
    <CardTitle>Inspection entry</CardTitle>
    <CardDescription>Enter transport unit and result</CardDescription>
  </CardHeader>
  <CardContent className="space-y-4">
    <div className="space-y-2">
      <Label htmlFor="tid">Transport Unit ID</Label>
      <Input id="tid" placeholder="TU-2024-00001" />
    </div>
    <div className="space-y-2">
      <Label htmlFor="w">Weight (kg)</Label>
      <Input id="w" type="number" placeholder="0.00" />
    </div>
    <div className="space-y-2">
      <Label>Result</Label>
      <Select>
        <SelectTrigger className="w-full">
          <SelectValue placeholder="Select" />
        </SelectTrigger>
        <SelectContent>
          <SelectItem value="pass">Pass</SelectItem>
          <SelectItem value="fail">Fail</SelectItem>
        </SelectContent>
      </Select>
    </div>
    <div className="space-y-2">
      <Label htmlFor="n">Notes</Label>
      <Textarea id="n" placeholder="Observations..." rows={2} />
    </div>
    <Button className="w-full">Submit inspection</Button>
  </CardContent>
</Card>

Field Types

Text Fields

TypeDescription
textSingle-line text input
textareaMulti-line text area
emailEmail with validation
urlURL with validation
phonePhone number with format
passwordMasked password input
rich-textRich text editor (Markdown)

Number Fields

TypeDescription
numberNumeric input with min/max/step
integerWhole numbers only
currencyCurrency with prefix/suffix
percentagePercentage with 0-100 range
sliderRange slider
ratingStar rating (1-5)

Selection Fields

TypeDescription
selectSingle dropdown selection
multi-selectMultiple selection
radioRadio button group
checkboxSingle checkbox (boolean)
checkbox-groupMultiple checkbox options
toggleSwitch toggle
comboboxSearchable select with autocomplete

Date & Time

TypeDescription
dateDate picker
timeTime picker
datetimeCombined date and time
date-rangeDate range selector
monthMonth/year picker

Media & File

TypeDescription
fileSingle file upload
multi-fileMultiple file upload
imageImage upload with preview
photo-captureCamera capture
videoVideo upload
signatureDigital signature pad

Specialized

TypeDescription
barcode-scannerQR/barcode scanning
nfc-readerNFC tag reading
geolocationGPS coordinate capture
geofence-editorPolygon drawing tool
colorColor picker
jsonJSON editor
codeCode editor with syntax highlighting
markdownMarkdown editor with preview

Validation

Built-in Validators

{
  name: 'email',
  type: 'email',
  required: true,
  validation: {
    pattern: '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$',
    message: 'Please enter a valid email address'
  }
}

Zod Integration

Forms can use Zod schemas for complex validation:

import { z } from 'zod';

const schema = z.object({
  weight: z.number().min(0).max(100000),
  transportUnitId: z.string().regex(/^TU-\d{4}-\d{5}$/),
  photos: z.array(z.string().url()).min(1, 'At least one photo required'),
});

Conditional Validation

Fields can have validation rules that depend on other field values:

{
  name: 'rejectionReason',
  type: 'textarea',
  label: 'Rejection Reason',
  required: false,
  conditionalRequired: {
    field: 'inspectionResult',
    value: 'Fail'
  }
}

Conditional Visibility

Show or hide fields based on other values:

{
  name: 'hazmatDetails',
  type: 'textarea',
  label: 'Hazmat Classification',
  visible: {
    field: 'containsHazmat',
    value: true
  }
}

Layout

Auto Layout

By default, forms render fields in a single column. Use the layout property for multi-column layouts:

{
  layout: {
    columns: 2,
    gaps: { row: '1rem', column: '1.5rem' },
    sections: [
      { title: 'Transport Unit', fields: ['id', 'type', 'weight'] },
      { title: 'Inspection', fields: ['result', 'photos', 'notes'] }
    ]
  }
}

Responsive

Forms automatically collapse to single-column on mobile viewports.