Skip to content

FormField

The FormField component wraps individual form controls with a label, optional helper text, error messages, and a required indicator. It handles the association between the label and its input via htmlFor, ensuring proper accessibility.

Import

import { FormField } from '@nim-ui/components';

Usage

Basic FormField

View Code
<FormField label="Email address" name="email">
<Input type="email" placeholder="[email protected]" />
</FormField>

Required Field

Required FormField

View Code
<FormField label="Full name" name="fullName" required>
<Input placeholder="Enter your full name" />
</FormField>

With Helper Text

FormField with Helper Text

View Code
<FormField
label="Password"
name="password"
helperText="Must be at least 8 characters with one uppercase letter and one number."
>
<Input type="password" placeholder="Enter password" />
</FormField>

With Error Message

FormField with Error

View Code
<FormField
label="Email"
name="email"
error="Please enter a valid email address."
required
>
<Input type="email" placeholder="[email protected]" />
</FormField>

With Select

FormField with Select

View Code
<FormField label="Country" name="country" required>
<Select
options={[
{ value: 'us', label: 'United States' },
{ value: 'uk', label: 'United Kingdom' },
{ value: 'ca', label: 'Canada' },
{ value: 'au', label: 'Australia' },
]}
placeholder="Select your country"
/>
</FormField>

With Textarea

FormField with Textarea

View Code
<FormField
label="Bio"
name="bio"
helperText="Write a short description about yourself. Maximum 500 characters."
>
<Textarea placeholder="Tell us about yourself..." rows={4} />
</FormField>

Complete Form Example

Form with Multiple FormFields

View Code
<Form onSubmit={handleSubmit}>
<FormField label="First name" name="firstName" required>
<Input placeholder="Jane" />
</FormField>
<FormField label="Last name" name="lastName" required>
<Input placeholder="Doe" />
</FormField>
<FormField label="Email" name="email" required helperText="We will never share your email.">
<Input type="email" placeholder="[email protected]" />
</FormField>
<FormField label="Role" name="role">
<Select
options={[
{ value: 'dev', label: 'Developer' },
{ value: 'designer', label: 'Designer' },
{ value: 'pm', label: 'Product Manager' },
]}
placeholder="Select your role"
/>
</FormField>
<FormField label="Message" name="message">
<Textarea placeholder="Anything else you'd like to share?" rows={3} />
</FormField>
<Button type="submit" variant="primary">Submit</Button>
</Form>

Props

Name Type Default Description
label * string - Label text displayed above the form control
name * string - Used for the htmlFor attribute to associate the label with its form control
error string - Error message displayed in red below the form control
helperText string - Helper text displayed in gray below the form control. Hidden when an error is present.
required boolean false When true, displays a red asterisk (*) next to the label
children * ReactNode - The form control element (Input, Select, Textarea, etc.)
className string - Additional CSS classes to apply to the wrapper element

Usage Examples

Registration Form

import { useState } from 'react';
import { Form, FormField, Input, Select, Checkbox, Button } from '@nim-ui/components';
function RegistrationForm() {
const [errors, setErrors] = useState<Record<string, string>>({});
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
const formData = new FormData(e.currentTarget as HTMLFormElement);
const validationErrors = validateRegistration(formData);
if (Object.keys(validationErrors).length > 0) {
setErrors(validationErrors);
return;
}
createAccount(formData);
};
return (
<Form onSubmit={handleSubmit}>
<div className="flex gap-4">
<FormField label="First name" name="firstName" required error={errors.firstName}>
<Input name="firstName" placeholder="Jane" />
</FormField>
<FormField label="Last name" name="lastName" required error={errors.lastName}>
<Input name="lastName" placeholder="Doe" />
</FormField>
</div>
<FormField
label="Email"
name="email"
required
error={errors.email}
>
<Input name="email" type="email" placeholder="[email protected]" />
</FormField>
<FormField
label="Password"
name="password"
required
error={errors.password}
helperText="At least 8 characters with a mix of letters and numbers."
>
<Input name="password" type="password" placeholder="Create a password" />
</FormField>
<FormField label="Company" name="company">
<Input name="company" placeholder="Your company (optional)" />
</FormField>
<FormField label="Role" name="role" required error={errors.role}>
<Select
name="role"
placeholder="Select your role"
options={[
{ value: 'developer', label: 'Developer' },
{ value: 'designer', label: 'Designer' },
{ value: 'manager', label: 'Product Manager' },
{ value: 'other', label: 'Other' },
]}
/>
</FormField>
<Checkbox label="I agree to the terms of service" name="terms" />
<Button type="submit" variant="primary" fullWidth>
Create Account
</Button>
</Form>
);
}

Settings Form

function ProfileSettings() {
return (
<Form onSubmit={handleSave}>
<FormField label="Display name" name="displayName" required>
<Input name="displayName" defaultValue="Jane Doe" />
</FormField>
<FormField
label="Bio"
name="bio"
helperText="Brief description for your profile. Maximum 200 characters."
>
<Textarea
name="bio"
defaultValue="Frontend developer & design enthusiast"
rows={3}
/>
</FormField>
<FormField label="Website" name="website" helperText="Include the full URL with https://">
<Input name="website" type="url" placeholder="https://yoursite.com" />
</FormField>
<Button type="submit" variant="primary">
Save Changes
</Button>
</Form>
);
}

Accessibility

The FormField component ensures proper accessibility for form controls:

  • The label is rendered as an HTML <label> element associated with the input via htmlFor matching the name prop
  • Required fields include aria-required="true" in addition to the visual asterisk
  • Error messages are connected to the input via aria-describedby so screen readers announce them
  • Helper text is also connected via aria-describedby for screen reader users
  • When both error and helper text are provided, the error takes precedence to avoid confusion
  • The red asterisk on required fields includes aria-hidden="true" since the requirement is communicated programmatically