figma guide
Designing forms in Figma: inputs, validation states, and handoff that engineers trust
Design accessible form UI in Figma: field anatomy, error/focus/disabled states, component variants, auto layout, and spec tables so devs ship the right behavior.
- Published
- Updated
- May 28, 2026
- Read time
- 6 min
- Level
- Intermediate
Quick answer
Form UI in Figma should be one component set per field type (text, select, checkbox, radio, switch) with variants for state (default, focus, error, disabled, read-only) and size (sm/md/lg)—not separate frames per screen. Build fields with auto layout, bind labels and hints with predictable spacing, and document validation timing (on blur vs submit) in descriptions Dev Mode can read. Pair components with interactive component states for hover/press where prototypes need them, and link accessibility checks to best Figma accessibility plugins. Start from Figma guides if you are new to libraries.
Who this is for
- Product designers shipping signup, checkout, and settings flows.
- Design system contributors publishing input primitives once for many squads.
- Teams tired of redlined forms that omit error text and focus rings.
Field anatomy: what every input includes
| Part | Purpose | Spec tip |
|---|---|---|
| Label | Identifies the control | Visible; do not rely on placeholder alone |
| Control | Value entry | Min height 40–44px for touch |
| Placeholder | Format hint | Not a substitute for label |
| Helper text | Guidance | Persistent below field |
| Error message | Validation failure | Distinct color + icon optional |
| Optional indicator | “Optional” fields | Reduces required-marker noise |
Verdict: if a screen lacks helper or error slots in the component, designers will draw ad hoc red text that breaks alignment in Dev Mode.
Component structure (recommended)
Input / Text
├── Variant: size=md | sm | lg
├── Variant: state=default | focus | error | disabled | read-only
├── Layer: Label (text style text/label)
├── Layer: Field container (auto layout horizontal)
│ ├── Prefix icon (optional)
│ ├── Value text (text/body)
│ └── Suffix icon (optional)
├── Layer: Helper (text/body-sm)
└── Layer: Error (text/body-sm, semantic color)
Publish from your library file and consume instances on feature pages—see organize Figma files at scale.
States you must ship in v1
| State | Visual signal | Prototype note |
|---|---|---|
| Default | Neutral border | Starting point |
| Focus | Strong border / ring | Document ring width for a11y |
| Error | Border + message | Show with sample message text |
| Disabled | Reduced contrast, no pointer | Do not hide label |
| Read-only | Muted fill, copy-friendly | Common in admin tools |
Hover and pressed matter for buttons inside forms (Submit, Add row)—use component property interactions or nested button components from your button set.
Avoid a separate “empty vs filled” variant unless marketing needs it; engineering cares about validation, not filler text styling.
Layout patterns with auto layout
Vertical form stack
- Parent frame: vertical auto layout, gap 16–24px between fields.
- Each field component: vertical label → control → helper/error.
- Section headings: full-width
text/h2with top padding token.
Horizontal pairs
Use two columns only above ~768px; stack on mobile per responsive design in Figma.
Button row
Footer actions: horizontal auto layout, primary on the inline end (right in LTR), destructive separated with gap—not adjacent without margin.
Comparison: native Figma vs plugins for forms
| Approach | Best for | Limitation |
|---|---|---|
| Native components + variants | Production design systems | You build the logic |
| UI kit instances | Speed in early sprints | May not match your tokens |
| Content Reel / data plugins | Realistic stress tests | Not a11y validation |
| A11y plugins (contrast, labels) | CI-style checks | Does not replace structure |
Verdict: own a thin native input set aligned to your code library (React, iOS, etc.); import kits only as reference, not source of truth. Template starters: best Figma UI kits.
Accessibility checklist
- Label tap target: label and field grouped; hit area ≥ 44px where touch applies.
- Contrast: border, text, and error meet WCAG for your background—run accessibility plugins.
- Focus visible: never prototype “invisible focus” that engineers copy.
- Error identification: color + text; do not use color alone.
- Required fields: mark in label; explain in form intro for long flows.
Keyboard order is not simulated in Figma—add a numbered tab order note in Dev Mode description for complex wizards.
Complex controls
Select / combobox
Show closed and open menu as variants or separate frames linked in prototype. Document max height, scroll, and empty state in specs.
Checkbox vs switch
| Control | Use when |
|---|---|
| Checkbox | Multi-select lists, legal consent |
| Switch | Immediate settings (on/off) |
| Radio | Single choice among few options |
Keep each as its own component set—do not mash into one “boolean” component with confusing icons.
Date / password / search
Specialized icons and masking rules belong in description fields (password: toggle visibility; search: submit on Enter).
Validation and copy
Document in the component description (visible in Dev Mode):
- When validation runs (blur, change, submit).
- Max length and allowed characters.
- Error message templates (
{field} is required).
Design at least three error examples (empty, format, server) so QA does not invent copy.
Handoff to engineering
| Deliverable | Where it lives |
|---|---|
| Component props | Variant names = code props |
| Spacing tokens | Auto layout gap = spacing token |
| Colors | Semantic variables, not hex on instance |
| Behavior | Description + linked Notion only if needed |
Use dev handoff plugins when token export exceeds native Dev Mode. Avoid duplicating full field specs in Notion—see Notion × Figma workflow.
Typography for labels and errors should use published text styles—not local 13.5px experiments.
Prototyping flows without fooling yourself
- Wire happy path with real component instances.
- Add error screen using error variant on the same instance—proves spacing holds.
- Link submit to success overlay; keep loading state as a variant on the button.
For multi-step wizards, use prototype basics with clear frame names (checkout / step-2 / payment).
Common mistakes
| Mistake | Consequence | Fix |
|---|---|---|
| Placeholder as label | Fails a11y; vanishes on type | Always visible label |
| One-off red border | Token drift | Error variant on library component |
| Giant form screenshot only | Devs miss edge states | Ship variant matrix artboard |
| Detached inputs per screen | Unmaintainable | Swap instances from library |
| Ignoring mobile keyboard | Fields hidden under keyboard | Safe area + scroll spec on mobile frames (mobile UI frames) |
FAQ
How many variants before it is too many?
If size × state explodes past ~30 combinations, split size into separate component sets or use nested instances for icons only.
Should error text be part of the component?
Yes—include the error text layer, hidden in default variant, visible in error variant. Engineers hide/show in code; designers see layout impact.
Can I use Auto Layout for the input control only?
Yes. Typical pattern: outer vertical stack; inner horizontal stack for icon + text with padding tokens and min height on the control frame.
Do forms belong in the same library as buttons?
Same library file, different component sets, shared tokens and text styles.
Bottom line
Treat each field type as a small design system: variants for state and size, auto layout for rhythm, and descriptions for validation behavior. Review focus, error, and disabled before any handoff review, and keep instances linked so form screens stay maintainable. Continue with interactive states, typography standards, and the tutorials hub.
§ Keep reading