Registration form example
This is a simple registration form example. It showcases our highly accessible client-side validation with error summary for easy screen-reader navigation.
Create an account
registration-form.tsx
'use client';
import {
RiEarthLine,
RiHeart2Line,
RiLockPasswordLine,
RiPhoneLine,
} from '@remixicon/react';
import Link from 'next/link';
import { Button } from '@/ui/components/button/button';
import { Checkbox } from '@/ui/components/forms/checkbox';
import {
Combobox,
ComboboxItem,
ComboboxListBox,
ComboboxSearchField,
} from '@/ui/components/forms/combobox';
import { Form, FormRoot } from '@/ui/components/forms/form';
import { useForm } from '@/ui/components/forms/hooks/use-form';
import { Radio, RadioGroup } from '@/ui/components/forms/radio';
import { Select, SelectItem } from '@/ui/components/forms/select';
import { TextField } from '@/ui/components/forms/text-field';
import {
FieldErrorSummary,
FormErrors,
FormServerError,
validators,
} from '@/ui/components/forms/validation';
import { registerAction } from './action';
import { RegistrationFormValues } from './types';
export const RegistrationForm = () => {
const form = useForm<RegistrationFormValues>({
onSubmit: async ({ values, reset }) => {
await registerAction(values);
reset();
},
});
return (
<FormRoot context={form}>
<h2 id="registration-form-heading" className="mb-4 text-3xl font-bold">
Create an account
</h2>
<FormStatus>
<FormServerError
errorMessage={form.serverError}
title="Could not register"
/>
<FieldErrorSummary
title="Something went wrong!"
subtitle="The form could not be submitted because some of the fields are invalid. Please correct your input in the following fields:"
fieldLabels={{
name: 'Name',
email: 'Email Address',
phone: 'Phone Number',
password: 'Password',
favoriteAnimal: 'Favorite Animal',
contactMethod: 'Preferred Contact Method',
country: 'Country',
'terms-and-conditions': 'Terms and Conditions',
}}
/>
</FormStatus>
<Form
className="flex flex-col gap-4 rounded-lg border-2 border-gray-200 p-6 shadow-xl"
aria-labelledby="registration-form-heading"
>
<TextField
id="name"
name="name"
label="Name"
type="text"
description="Please enter your full name without any middle names"
autoComplete="name"
isRequired
validate={(value) => {
if (!value) {
return 'Please enter your name';
}
}}
/>
<TextField
id="email"
name="email"
label="Email Address"
type="email"
description="Please enter a valid email address. Example: test@test.com"
autoComplete="email"
validate={(value) => {
if (!validators.email(value)) {
return 'Invalid email address';
}
}}
isRequired
/>
<TextField
id="phone"
name="phone"
label="Phone Number"
type="tel"
icon={<RiPhoneLine size={20} />}
description="Please enter your phone number with the country code. Example: +43"
autoComplete="tel"
/>
<TextField
id="password"
name="password"
label="Password"
type="password"
description="Password must be at least 8 characters long and contain at least one
uppercase letter, one lowercase letter, and one number."
autoComplete="new-password"
icon={<RiLockPasswordLine size={18} />}
isRequired
validate={(value) => {
if (value.length < 8) {
return 'Password must be at least 8 characters long';
}
if (!/[A-Z]/.test(value)) {
return 'Password must contain at least one uppercase letter';
}
if (!/[a-z]/.test(value)) {
return 'Password must contain at least one lowercase letter';
}
if (!/[0-9]/.test(value)) {
return 'Password must contain at least one number';
}
}}
/>
<Select
id="favoriteAnimal"
name="favoriteAnimal"
label="Favorite Animal"
icon={<RiHeart2Line size={18} />}
isRequired
validate={(value) => {
if (!value) {
return 'Please select an animal';
}
if (value === 'snake') {
return 'Please select a non-snake as your favorite animal';
}
}}
>
<SelectItem id="cat">Cat</SelectItem>
<SelectItem id="dog">Dog</SelectItem>
<SelectItem id="kangaroo">Kangaroo</SelectItem>
<SelectItem id="panda">Panda</SelectItem>
<SelectItem id="snake">Snake</SelectItem>
<SelectItem id="lion">Lion</SelectItem>
<SelectItem id="tiger">Tiger</SelectItem>
<SelectItem id="elephant">Elephant</SelectItem>
<SelectItem id="giraffe">Giraffe</SelectItem>
<SelectItem id="zebra">Zebra</SelectItem>
<SelectItem id="hippo">Hippo</SelectItem>
<SelectItem id="rhino">Rhino</SelectItem>
<SelectItem id="leopard">Leopard</SelectItem>
<SelectItem id="cheetah">Cheetah</SelectItem>
<SelectItem id="monkey">Monkey</SelectItem>
<SelectItem id="fox">Fox</SelectItem>
<SelectItem id="wolf">Wolf</SelectItem>
</Select>
<Combobox
id="country"
name="country"
label="Country"
isRequired
icon={<RiEarthLine size={18} />}
validate={(value) => {
if (!value) {
return 'Please select a country';
}
}}
>
<ComboboxSearchField placeholder="Search country..." />
<ComboboxListBox>
<ComboboxItem id="austria">Austria</ComboboxItem>
<ComboboxItem id="ireland">Ireland</ComboboxItem>
<ComboboxItem id="poland">Poland</ComboboxItem>
<ComboboxItem id="uk">United Kingdom</ComboboxItem>
<ComboboxItem id="hungary">Hungary</ComboboxItem>
<ComboboxItem id="spain">Spain</ComboboxItem>
<ComboboxItem id="portugal">Portugal</ComboboxItem>
<ComboboxItem id="kangaroo">Australia</ComboboxItem>
<ComboboxItem id="in">India</ComboboxItem>
<ComboboxItem id="br">Brazil</ComboboxItem>
<ComboboxItem id="mx">Mexico</ComboboxItem>
<ComboboxItem id="it">Italy</ComboboxItem>
<ComboboxItem id="es">Spain</ComboboxItem>
<ComboboxItem id="se">Sweden</ComboboxItem>
<ComboboxItem id="no">Norway</ComboboxItem>
<ComboboxItem id="fi">Finland</ComboboxItem>
</ComboboxListBox>
</Combobox>
<RadioGroup
id="contactMethod"
name="contactMethod"
label="Preferred Contact Method"
description="We will contact you via the method you select"
isRequired
validate={(value) => {
if (!value) {
return 'Please select a contact method';
}
if (value === 'pigeon') {
return 'Please select a modern contact method';
}
}}
orientation="vertical"
>
<Radio value="email">Email</Radio>
<Radio value="phone">Phone</Radio>
<Radio value="pigeon">Carrier Pigeon</Radio>
</RadioGroup>
<Checkbox
id="terms-and-conditions"
name="terms-and-conditions"
value="terms-and-conditions"
label="I agree to the terms and conditions"
description={
<>
Read our full{' '}
<Link
href="/terms-and-conditions"
className="text-primary-500 hover:underline"
>
Terms and Conditions
</Link>
</>
}
isRequired
validate={(value) => {
if (!value) {
return 'Please agree to the terms and conditions';
}
}}
className="pt-2"
/>
<div>
<Button
type="submit"
disabled={form.isPending}
loading={form.isPending}
>
Create your account
</Button>
</div>
</Form>
</FormRoot>
);
};