Form Control

Build accessible and styled form controls with proper labeling and validation states.

Overview

FormControl provides a consistent way to build form fields with proper accessibility, labeling, help text, and error states. It automatically manages ARIA attributes and ensures screen readers can understand the form structure.

AccessibleARIA SupportValidation ReadyTypeScript

Basic Usage

Simple Form Control

The most basic form control with label and helper text.

import { FormControl, Input, Button } from '@akitectio/aki-ui'

function BasicForm() {
  return (
    <form className="space-y-4">
      <FormControl>
        <FormControl.Label>Email Address</FormControl.Label>
        <Input 
          type="email" 
          placeholder="Enter your email"
          required
        />
        <FormControl.HelperText>
          We'll never share your email with anyone else.
        </FormControl.HelperText>
      </FormControl>
      
      <FormControl>
        <FormControl.Label>Password</FormControl.Label>
        <Input 
          type="password" 
          placeholder="Enter password"
          required
        />
      </FormControl>
      
      <Button type="submit">Submit</Button>
    </form>
  )
}

Validation States

Form Validation

Handle validation states with error messages and visual feedback.

import { FormControl, Input, Button } from '@akitectio/aki-ui'
import { useState } from 'react'

function ValidatedForm() {
  const [errors, setErrors] = useState<Record<string, string>>({})
  
  const validateField = (name: string, value: string) => {
    switch (name) {
      case 'email':
        return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) 
          ? '' : 'Please enter a valid email address'
      case 'password':
        return value.length >= 8 
          ? '' : 'Password must be at least 8 characters'
      default:
        return ''
    }
  }

  return (
    <form className="space-y-4">
      <FormControl isInvalid={!!errors.email}>
        <FormControl.Label>Email Address</FormControl.Label>
        <Input 
          type="email" 
          name="email"
          onChange={(e) => {
            const error = validateField('email', e.target.value)
            setErrors(prev => ({ ...prev, email: error }))
          }}
        />
        {errors.email && (
          <FormControl.ErrorMessage>
            {errors.email}
          </FormControl.ErrorMessage>
        )}
      </FormControl>
      
      <FormControl isInvalid={!!errors.password}>
        <FormControl.Label>Password</FormControl.Label>
        <Input 
          type="password" 
          name="password"
          onChange={(e) => {
            const error = validateField('password', e.target.value)
            setErrors(prev => ({ ...prev, password: error }))
          }}
        />
        {errors.password && (
          <FormControl.ErrorMessage>
            {errors.password}
          </FormControl.ErrorMessage>
        )}
      </FormControl>
    </form>
  )
}

API Reference

FormControl Props

PropTypeDefaultDescription
isRequiredbooleanfalseWhether the field is required
isInvalidbooleanfalseWhether the field has validation errors
isDisabledbooleanfalseWhether the field is disabled

Subcomponents

FormControl.Label

Accessible label for the form control. Automatically links to the input field.

FormControl.HelperText

Additional help text to guide users. Appears below the input field.

FormControl.ErrorMessage

Error message displayed when validation fails. Automatically styled with error colors.

Best Practices

Do

  • • Always provide clear, descriptive labels
  • • Use helper text for additional context
  • • Implement real-time validation feedback
  • • Group related fields logically
  • • Test with screen readers

Don't

  • • Use placeholder text as labels
  • • Hide important validation messages
  • • Make error messages too technical
  • • Disable form submission unnecessarily
  • • Forget to handle loading states