Web & UI pack
Claude Skill
Form Builder
Generates accessible HTML forms (signup, contact, multi-step) with validation and error states.
What it does
Given form fields and submission target, produces accessible HTML+Tailwind forms with proper labels, ARIA, native validation, error states, and keyboard support. Handles single-page and multi-step flows. Outputs HTML for vanilla apps OR a controlled React component if requested.
When to use
- ✓You need a signup, contact, lead-capture, or onboarding form
- ✓Existing form fails accessibility audits or has clunky error UX
- ✓Building a multi-step wizard (3-7 steps) with progress + back navigation
When not to use
- ✗Hosted form builder (Typeform, Tally, Formspark) is fine — use them
- ✗Highly dynamic form with conditional logic across 30+ fields — use a form library (React Hook Form, Formik, Tanstack Form)
- ✗Survey with branching logic — use a survey tool
Install
Download the .zip, then unzip into your Claude skills folder.
mkdir -p ~/.claude/skills
unzip ~/Downloads/form-builder.zip -d ~/.claude/skills/
# Restart Claude Code session.
# Skill is now available — Claude will use it when relevant.SKILL.md
SKILL.md
---
name: form-builder
description: Use when generating an accessible HTML form (signup, contact, multi-step). Triggers on "build a form", "signup form", "contact form", "multi-step form", "form with validation".
---
# Form Builder
Generate accessible forms with real validation and error states. Most forms break accessibility because labels are placeholder-only, errors aren't announced, and keyboard users can't navigate. Build it right.
## Required inputs
1. **Form purpose** — signup / contact / onboarding / payment / etc.
2. **Fields** — for each: label, type (text/email/tel/select/textarea/checkbox/radio), required y/n, validation rules, helper text
3. **Submission target** — endpoint URL + method, or "client-side handler"
4. **Success/error UX** — redirect, inline message, toast?
5. **Framework** — vanilla HTML, React (controlled), or progressive-enhancement (works without JS)
If a field is required but unclear why ("phone number" for a newsletter signup), push back. Every required field is friction.
## Output format
**Default**: HTML+Tailwind with native validation (`required`, `type="email"`, `pattern`, `minlength`). Progressive enhancement — works without JS, better with.
**React**: controlled inputs with `useState` or React Hook Form. Output a single `.tsx` component.
**Multi-step**: state machine (`useReducer` or XState lite) tracking step + per-step validation.
## Field structure (the canonical pattern)
```
<div class="space-y-1">
<label for="email" class="block text-sm font-medium text-gray-900">
Work email
<span class="text-red-600" aria-hidden="true">*</span>
</label>
<input
id="email"
name="email"
type="email"
required
autocomplete="email"
aria-describedby="email-help email-error"
aria-invalid="false"
class="block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
/>
<p id="email-help" class="text-sm text-gray-500">We'll never share your email.</p>
<p id="email-error" class="text-sm text-red-600 hidden" role="alert"></p>
</div>
```
Every field gets:
- `<label for="...">` — never placeholder-only
- Real `type` (`email`, `tel`, `url`, `number`) — drives mobile keyboards
- `autocomplete` — `email`, `name`, `organization`, `tel`, `street-address`, `new-password`, etc.
- `aria-describedby` linking to help text and error
- `aria-invalid` flipped to `true` on validation failure
## Validation strategy
**Native first**: `required`, `type`, `pattern`, `min/max`, `minlength/maxlength`. The browser validates for free.
**On submit**: validate all, focus the first invalid field, set `aria-invalid="true"`, show inline error, scroll into view if off-screen.
**On blur**: validate that field only. Don't validate as user types — frustrating.
**Server errors**: announce with `role="alert"` so screen readers catch them. Don't just style red and hope.
## Error UX
- Inline below the field, never as a tooltip
- `role="alert"` on the error element so it's announced
- Tie via `aria-describedby` so the error reads when the field is focused
- Don't disable the submit button preemptively — let the user submit and see ALL errors at once
- After server error, refocus the offending field
## Multi-step flows
For 3+ steps:
1. **Progress indicator** — `<ol aria-label="Progress">` with `<li aria-current="step">` on the active one. Numbered, not just dots.
2. **Step routing** — query param (`?step=2`) or hash so back-button works
3. **Per-step validation** — block "Next" until current step passes
4. **Back button** — preserves entered data; never lose user input
5. **Review step** — final step shows all data with Edit links per section
6. **Save progress** — for 5+ step flows, save to localStorage so refresh doesn't wipe
## Accessibility
- `<form>` with `<fieldset>` + `<legend>` for grouped fields (e.g., billing address)
- Required fields: visible `*` AND `aria-required="true"` (or HTML `required`)
- Error summary at top for long forms: "There were 2 errors. [Email] is invalid. [Phone] is required." — each link focuses the field
- Submit button: not disabled until network in flight. Use `aria-busy="true"` during submit.
- Focus management: after submit success, focus the success message (`tabindex="-1"` + `focus()`)
- Honor `prefers-reduced-motion` for any transitions
## Anti-patterns
- **Placeholder as label**: invisible when typing, fails screen readers
- **Floating labels with poor contrast**: cute, often inaccessible
- **Real-time validation as user types**: shows errors before they finish typing
- **Disabled submit until valid**: user can't tell what's wrong
- **Generic "Something went wrong"**: be specific. "We couldn't reach the email server. Try again?"
- **Required asterisks without explanation**: include "* indicates required field" once at top
- **Stripping autocomplete**: Chrome's autofill is your friend; let it work
- **Captcha on every form**: rate-limit instead. If you must, use invisible reCAPTCHA or hCaptcha.
## Output
Return the form HTML/JSX file. Top comment lists:
- Fields and their types
- Validation rules
- Submit handler approach
- A11y checklist (labels present, errors announced, focus management, autocomplete)
Example prompts
Once installed, try these prompts in Claude:
- Build a contact form: name, work email, company, message. Required fields, email validation, success/error states, Tailwind styling.
- Build a 3-step signup wizard: account info → company details → plan selection. Progress bar, back button, validation per step.