Reference · UX pattern catalogueForm patterns

36 patterns in this category — each with its illustration, what it is, and the fields that matter when you build or review one. Part of the UX pattern catalogue; the raw, agent-readable version is ux-pattern-catalogue/form-patterns.json.

Components

Submit Cancel Outline

Button form-001

A clickable element that triggers an action. Use for primary actions, form submissions, and confirmations.

Implementation

shadcn: button. Primary for main action, secondary/ghost for alternatives. One primary per viewport.

Accessibility

Must be focusable and respond to Enter/Space. Use <button> not <div>.

Dark mode Notifications Auto-save

Checkbox form-002

A box you tick to turn an option on or off. Use for multiple selections from a list or boolean toggles.

Implementation

shadcn: checkbox. Group with fieldset/legend for related options.

Accessibility

Linked <label>. aria-checked state. Group with role="group" and aria-labelledby.

Austr Australia Austria

Combobox form-003

A search box that filters and suggests options as you type. Use for selecting from large lists (10+ items) like countries or tags.

Implementation

shadcn: command + popover. Debounce input (300ms). Show loading state for async options.

Accessibility

aria-expanded, aria-activedescendant for selection. Full keyboard navigation (arrows, Enter, Escape).

March 2026 Mo Tu We Th Fr Sa Su 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

Date Picker form-004

A calendar popup for picking dates. Use for date selection, date ranges, and scheduling.

Implementation

shadcn: calendar + popover. Allow manual typing alongside calendar selection. Locale-aware formatting.

Accessibility

Keyboard navigation within calendar grid. aria-label on day cells. Support manual date entry.

Name Email Submit

Form form-005

A group of fields the user fills in and submits. The foundation for any structured data collection.

Implementation

shadcn: form. Single-column layout. Validate on blur. Autocomplete attributes on all standard fields.

Accessibility

Every input needs a <label>. Error messages via aria-describedby. Focus first error on submit failure.

Email address you@example.com We'll never share your email.

Input form-006

A text field where users type short text like names, emails, or search queries.

Implementation

shadcn: input. Set inputmode (numeric, email, tel). Set autocomplete attribute.

Accessibility

Linked <label for>. aria-describedby for helper text. aria-invalid on error.

Enter verification code 4 8 2 Didn't receive it? Resend

Input OTP form-007

Separate boxes for entering a verification code. Auto-advances on digit entry and supports paste.

Implementation

shadcn: input-otp. autocomplete="one-time-code", inputmode="numeric". Auto-advance on digit entry.

Accessibility

Single logical input with aria-label. Support full-code paste. Focus management between boxes.

Full Name * Jane Doe Bio (optional)

Label form-008

Text that describes what a form field is for. Every input must have one.

Implementation

shadcn: label. Always use <label for="id"> linking to the input. Show required/optional marking.

Accessibility

Programmatic association via for/id. Never use placeholder as a label substitute.

Select plan Free Basic features Pro — $10/mo Team — $25/mo

Radio Group form-009

A set of options where you pick exactly one. Use for mutually exclusive choices with 2–5 visible options.

Implementation

shadcn: radio-group. Use radio over select when options ≤5 — all options are visible without interaction.

Accessibility

Wrap in fieldset/legend. Arrow keys move selection. Role="radiogroup".

Country United States United States United Kingdom

Select form-010

A dropdown list for picking one option from 3–10 choices where space is limited.

Implementation

shadcn: select. Use for 3-10 options. For 10+ options, prefer Combobox with search.

Accessibility

aria-expanded on trigger. Keyboard: arrows to navigate, Enter to select, Escape to close.

Price range $75 $0 $100 Volume

Slider form-011

A draggable handle for picking a value within a range, like price or volume.

Implementation

shadcn: slider. Show current value label. Snap to meaningful increments.

Accessibility

role="slider" with aria-valuenow/min/max/valuetext. Arrow keys for fine control.

Dark mode On Notifications Off

Switch form-012

An on/off toggle that takes effect immediately. Use for settings like dark mode or notifications.

Implementation

shadcn: switch. Applies instantly (no save button needed). Show on/off label alongside.

Accessibility

role="switch" with aria-checked. Linked label. Space toggles state.

Description This product is designed for teams who need a fast and reliable… 128 / 500 characters

Textarea form-013

A larger text box for writing longer content like descriptions, comments, or messages.

Implementation

shadcn: textarea. Pair with Character Counter for length limits. Resizable handle optional.

Accessibility

Linked <label>. aria-describedby for character count. Never silently truncate input.

B I U S Stays pressed until toggled off

Toggle form-014

A button that stays pressed or released. Use for formatting tools like bold/italic or view mode switching.

Implementation

shadcn: toggle. Visual pressed state via aria-pressed. Not for binary settings (use Switch instead).

Accessibility

aria-pressed indicates state. Keyboard-operable via Enter/Space.

Grid List Table Pick one or multiple from a segmented set

Toggle Group form-015

A row of buttons where you pick one (or multiple). Use for view switchers or filter groups.

Implementation

shadcn: toggle-group. Single-select by default. Multi-select when choices are independent.

Accessibility

role="group" with aria-label. Roving tabindex for arrow key navigation within group.

Drag files here or click to browse PNG, JPG up to 10 MB photo.png

File Upload form-016

A button or drop zone for uploading files. Always provide a button alternative alongside drag-and-drop.

Implementation

Drag-and-drop zone with click fallback. Show file type/size limits. Progress indicator during upload.

Accessibility

Button fallback is essential — drag-and-drop alone excludes keyboard users. aria-describedby for limits.

Validation

john@example.com bad-email Enter a valid email address

Inline Validation form-017

Validate on blur (not on keystroke). Show success checkmarks for valid fields and error messages inline below the field. Never clear the field on error.

Implementation

Attach onBlur handler to each field. Show error via aria-describedby. Use aria-invalid="true" on the field. Success: green checkmark icon.

Accessibility

Error messages linked via aria-describedby. aria-invalid="true" on the field. Never color-only indicators.

Please fix 2 errors: → Email is required → Password too short

Error Summary form-018

Show a summary box at the top of the form listing all errors on failed submission. Each error links to the corresponding field.

Implementation

role="alert" container. Focus the summary on submit failure. Each item is an anchor to the field ID.

Accessibility

role="alert" or aria-live="polite". Focus management on submit failure.

Email ← focus here

Focus on First Error form-019

On submission failure, automatically focus the first invalid field and scroll it into view. Never focus the submit button on error.

Implementation

After validation, find first invalid field, call .focus() and .scrollIntoView({ behavior: "smooth", block: "center" }).

Accessibility

Ensures keyboard users are positioned at the first problem without manual searching.

Email john@com ! Enter a valid email (e.g. name@example.com) john@com Invalid

Error Message Clarity form-032

Error messages must say what went wrong AND how to fix it. Use specific language, not generic. Red color + icon, not color alone.

Implementation

Template: "Enter a valid [field] (e.g., [example])". Always pair color with an icon. Link via aria-describedby.

Accessibility

8% of men are colorblind — never use color alone. Icon + color + text triple redundancy.

Autocomplete

John Doe autofill john@example.com autofill +1 555-123-4567 autofill

Autocomplete Tokens form-020

Set the autocomplete attribute on every standard form field (name, email, tel, address, cc-number). Browsers auto-fill known values, reducing effort by 30-50%.

Implementation

Add autocomplete="name|email|tel|address-line1|postal-code|country|cc-number|cc-exp|cc-csc" to inputs.

Accessibility

Autocomplete helps motor-impaired users avoid retyping. Never disable autocomplete on standard fields.

123 Main St 123 Main St, New York, NY 123 Main St, Boston, MA

Address Autocomplete form-021

Integrate address lookup (Google Places API or similar) to auto-fill city, state, and zip from partial address input. Pre-select country from locale.

Implementation

Attach Places Autocomplete to the first address field. On selection, populate all address fields. Fallback to standard fields with autocomplete tokens.

Accessibility

Autocomplete dropdown must be keyboard-navigable. aria-expanded on the input. aria-activedescendant for selection.

Country United States auto Currency USD ($) Timezone America/New_York

Smart Defaults form-031

Pre-fill fields with the most common or contextually relevant values. Use browser autofill attributes. Default to the most popular option in select fields.

Implementation

Auto-detect country from IP or locale. Pre-select currency. Use autocomplete attributes. Set default <option selected> on selects.

Accessibility

Pre-filled values must be screen-reader-accessible. Users must be able to override defaults.

Enhancement

•••••••••• ✓ 8+ characters ✓ One uppercase ✗ One number

Password Strength form-022

Entropy-based strength meter for password creation. Show as a colored bar (red → yellow → green) with a specific requirements checklist.

Implementation

Calculate entropy from character set diversity and length. Show requirements as checkmarks. aria-live="polite" for strength changes.

Accessibility

Strength meter uses aria-valuenow/min/max. Requirements list uses aria-live="polite" for updates.

•••••••• MyP@ss123

Password Reveal form-023

Eye icon toggle that switches between type="password" and type="text". Essential on mobile where autocorrect can corrupt hidden passwords.

Implementation

Button with aria-label="Show password" / "Hide password". Toggles input type attribute. Preserves cursor position.

Accessibility

aria-label updates on toggle. Button is focusable and keyboard-operable.

This is my bio text with multiple lines 42/280

Character Counter form-024

Show remaining or used characters as "42/280" below the field. Warn when approaching the limit. Never silently truncate input.

Implementation

Live counter tied to input event. aria-describedby links the counter to the field. Warn at 90% of limit.

Accessibility

Counter announced via aria-describedby. Warning state via aria-live="polite".

User types: 5551234567 On blur: (555) 123-4567

Input Masking form-025

Format inputs like phone numbers and credit cards on blur, not during typing. Accept flexible user input and normalize server-side.

Implementation

Format on blur event. Store raw value internally. Display formatted value. Never prevent free typing.

Accessibility

Formatted value must remain readable by screen readers. aria-label describes the expected format.

Structure

1 2 3 Next →

Multi-Step Form form-026

Break forms with 7+ fields into 3-5 logical steps. Show progress indicator. Validate per step. Persist progress. Allow back navigation.

Implementation

Step indicator at top. Validate current step on "Next". Save to localStorage on every step. Enable back without losing data.

Accessibility

Progress indicator has aria-label. Current step announced. Focus moves to first field of new step.

Ship to different address Street address City, State, ZIP ↳ shown when checkbox is checked

Conditional Fields form-027

Show or hide fields based on previous answers. Use the collapse/expand animation pattern. Clear hidden field values on parent change.

Implementation

aria-expanded on the controlling field. Animate with grid-template-rows: 0fr/1fr. Remove hidden fields from form data on submit.

Accessibility

aria-expanded indicates state. Conditional fields are removed from tab order when hidden.

Personal Info Address

Fieldset Grouping form-028

Wrap related field groups (address, payment, personal info) in <fieldset> with <legend>. Provides context for screen readers.

Implementation

<fieldset> with <legend>. Never use <div> for groups that have a shared label.

Accessibility

Screen readers announce the legend when entering the fieldset, providing group context.

Email * Name * Company (optional)

Required/Optional Marking form-029

Mark the minority: if most fields are required, mark optional ones as "(optional)". If most are optional, mark required ones with an asterisk.

Implementation

required attribute or aria-required="true" on required fields. Visual indicator matches the minority pattern.

Accessibility

required attribute is the primary mechanism. Visual indicators supplement, never replace.

Name Email Message

Single-Column Layout form-030

Stack all fields in a single column. Left-align labels above fields. Never use multi-column form layouts — they cause 28% more errors.

Implementation

Use a single <form> with max-width constraint. Labels above fields with display: block. No CSS grid/flex row layouts for form fields.

Accessibility

Single-column layout creates a clear tab order. Labels above fields improve screen reader flow.

+34% conversions Submit

Field Count Optimization form-033

Audit every field — remove any not strictly required. If a field can be derived later, skip it. Target 3-5 fields for signup forms.

Implementation

Review each field: can it be derived? deferred? removed? Reducing 11 → 4 fields increased conversions 120% (Unbounce).

Accessibility

Fewer fields reduce cognitive load for all users, especially those using assistive technology.

Checkout Guest Checkout No account needed or Sign in to your account

Guest Checkout form-034

Never require account creation to complete a purchase. Offer guest checkout as the default, with optional account creation after payment.

Implementation

Guest checkout button as primary CTA. "Sign in" as secondary. Offer account creation post-payment with pre-filled data.

Accessibility

Guest checkout path must be fully keyboard-navigable and clearly labeled.

Resilience

✓ Saved

Auto-Save Draft form-035

Save form state to localStorage on debounce (2-5 seconds). Show a "Saved" indicator. Restore on page reload. Essential for long forms.

Implementation

Debounce form change events (2s). Save serialized form data to localStorage. Show "Saved" via aria-live="polite" region.

Accessibility

Save status announced via aria-live="polite". Recovery banner on reload is focusable.

Draft recovered. Continue or discard? john@example.com My project description...

Form Recovery form-036

Persist form state to localStorage on every change. Restore on page reload. Show a "Recovered draft" banner with option to discard.

Implementation

Listen to beforeunload to save. On load, check for saved state. Show banner: "We recovered your draft. Continue or discard?"

Accessibility

Recovery banner uses role="alert". Discard button is keyboard-accessible.