Skip to main content

Storybook

Form Control

A wrapper that provides consistent label, helper text, and error messaging for form fields. Use to ensure all form inputs meet layout and accessibility standards. Don't apply custom label or error patterns outside this component.

Figma Storybook Docs

Description

What it does

Form Control is the structural wrapper that every form field lives inside. It is not a field itself — it provides the consistent layout layer that surrounds inputs, dropdowns, text areas, checkboxes, and other controls.

Where it appears

Every form in Open Point and Social Point — consultation setup, stakeholder profiles, survey builders, settings screens, login and registration flows, and inline editing contexts.

Why it exists

Without Form Control, each team member who builds a form makes independent decisions about label positioning, error placement, spacing, and ARIA associations. Form Control eliminates that variation. Any field wrapped in it automatically gets the same layout, spacing, and accessibility wiring as every other field in the product.

Anatomy

PartRequired?Notes
Label Required Always visible above the field. Programmatically associated with the control via for/id or aria-labelledby. Never substitute placeholder text for a label.
Required indicator Conditional An asterisk (*) or "Required" text alongside the label when the field is mandatory. The visual indicator must have a text equivalent — not colour alone.
Field slot Required The interactive control. Can be any field component: Input, TextArea, Dropdown, RadioButton, Checkbox, Switch, etc.
Helper text Optional Below the field. Provides context that the label alone can't — format hints, length limits, examples. Associated with the field via aria-describedby.
Error message Conditional Replaces helper text when validation fails. Prefixed with an error icon. Associated via aria-describedby. Set aria-invalid="true" on the field element simultaneously.
Character count Optional Used with TextArea or constrained inputs. Updates live as the user types. Associated via aria-describedby.

States

State Behaviour
Default Label above, optional helper text below. Field in its resting state.
Error Error message replaces helper text. Red text and error icon. Field receives aria-invalid="true". Triggered on blur or form submission — not on every keystroke.
Disabled Label, field, and helper text all render at reduced opacity. The entire control is non-interactive. Communicate why the field is disabled nearby if the reason isn't obvious.

Usage guidelines

Required fields

Only mark fields as required when they genuinely are. In a form where most fields are required, consider marking the optional ones instead and noting the convention at the top of the form.

The required indicator (asterisk or "Required") must always be accompanied by a text explanation — either visible near the top of the form ("Fields marked with * are required") or included in the label itself ("Full name (required)"). Never rely on the asterisk or red colour alone.

When to use

  • Every form field — no exceptions. Input, TextArea, Dropdown, RadioButton, Checkbox, Switch, and all other form controls should live inside a Form Control wrapper.
  • Even fields with unconventional layouts (inline forms, filter bars, search) should use Form Control where possible to preserve the accessibility wiring.

When not to use

  • Standalone icon buttons or controls that aren't part of a form — these don't need a label/helper structure.
  • Groups of related fields (e.g. a date with separate day/month/year inputs) — use a <fieldset> and <legend> to wrap the group, with individual Form Controls inside for each field.

Do / Don't

Do

Always use a visible label. Every field must have one — even if the design shows a clean, label-free layout, the label must exist in the DOM and be associated with the field.

Don't

Don't use placeholder text as a substitute for a label. Placeholder text disappears the moment the user starts typing, leaving them with no reminder of what the field is for.

Do

Write error messages that tell users exactly what to do: "Enter a valid email address (e.g. name@example.com)" rather than "Invalid input".

Don't

Don't show error messages before the user has interacted with the field. Trigger validation on blur (when leaving the field) or on form submission — not on page load.

Do

Use helper text to set expectations before the user types — format, length, examples. "Must be at least 8 characters" is more useful than waiting for an error.

Don't

Don't use helper text to restate the label. It should add context the label doesn't already provide.

Was this page helpful?

Updated 9 September 2026