# Fieldset Forms UI Kit

> A browsable library of form controls and form structure on one token file: text, number, phone, masked and one-time-code inputs, selects, comboboxes, date, time, colour and file pickers, steppers, validation, error summaries and success states, plus five complete forms that open as working pages, light and dark.

Canonical: https://gsapvault.com/ui-elements/fieldset-forms-ui-kit
Live demo: https://gsapvault.com/demos/fieldset-forms-ui-kit/index.html

| Property | Value |
|----------|-------|
| Type | ui-kit |
| Tier | paid |
| Price | £25 |
| Difficulty | advanced |
| Plugins | Flip, Draggable |
| Techniques | token-theming, theme-switch, form-animation, form-validation, flip-layout, drag, keyboard-navigation, focus-management, dialog-animation, stagger, state-transition, micro-interaction, progress-bar, svg-line-draw, count-up |
| Uses Lenis | No |

## Overview

Fieldset is a component library for forms rather than a demo of one form. The page you see is the library itself: an index down the left, a search that filters it, and every control shown live at product density in the states a buyer checks, grouped into foundations, controls, text inputs, selection, pickers and uploads, form structure, validation and feedback, and five forms composed from the parts above.

Every component reads one token file, so a select, a date picker, a file upload and a submit button agree about surface, ink, line, radius, spacing and motion, and the light and dark themes are the same design at two sets of values. The register is a payments company's contact and checkout forms: a cool off-white ground, white fields with hairline borders, slate ink rather than black, one violet accent that means primary, selected or focused, and colour otherwise reserved for status.

Each component ships in its own folder with its markup, its stylesheet and its script, so you can take one control or link the two bundled files and take everything. Every control drives a real form field so a plain form submits it; every list, calendar and popover opens through one shared layer so Escape, focus and scroll behave once; and the motion is short, layered product motion with GSAP, with a reduced-motion state throughout.

The five forms are not screenshots. A contact form with artwork upload, a checkout, a sign-up with a one-time code, a four-step application and an account settings page each open as a full page (contact.html and its siblings) that validates, uploads, steps and submits to a success state. Each is composed from the components with include directives and a short glue script, so a form is also the worked example of how the parts fit together.

## Features

- Sixty-one components in eight families, each in its own folder with markup, styles and script
- A searchable catalogue page with an index rail, family groups and a theme toggle
- One token file driving light and dark; no component holds a colour of its own
- Text, textarea, password with strength, phone with dial codes, currency and unit numbers, masked card and bank fields, one-time code and inline edit
- Select, combobox, multi-select, tag input, address autocomplete, country and region, colour and time pickers on one shared menu style
- Date and date-range pickers, a file upload with per-file progress and retry, an image upload and a signature pad
- Form structure: field anatomy, fieldsets, sections, grids, inline forms, action bars, a multi-step stepper, collapsibles, conditional fields, a repeater with a running total and consent
- Validation with live timing rules, an error summary that links to fields, a submit button that morphs through loading and success, toasts, inline alerts, tooltips, popovers and dialogs
- Every control drives a real form field, so a plain form submits it without any script of yours
- Keyboard and ARIA contracts on every control, with live announcements for state changes
- Reduced-motion end states throughout; nothing animates while off screen
- Five forms that open as working pages: a project brief with artwork upload, a checkout, a sign-up with a one-time code, a four-step application and account settings
- Forms composed from the components with include directives, never redrawn, so each is a worked example of how the parts fit together

## Use Cases

- A contact, quote or enquiry form with file upload on a company site
- A checkout or booking flow that needs address, delivery and card fields that behave
- Sign-up, onboarding and account settings in a SaaS product
- A job application, survey or multi-step intake form
- A design system starting point where the form controls are the deliverable and the tokens prove them

## Questions about this component kit

### Can I take one control without the rest?

Yes. Each control has its own folder holding its markup, its stylesheet and, where it is scripted, its script. A project that only wants the date range picker or the file upload links tokens.css, base.css and base.js, then that one folder, and pastes the fieldset. The base files carry the field shell, label and hint positions and validation states every control shares. A project using the whole kit links the two bundled files instead. The catalogue page and its specimen rail are demo furniture.

### Do the fields actually submit, and how do I hook up my backend?

Every control drives a real form field: a native input, select or textarea, or a hidden input the script keeps in step. Wrap the markup in your own form and the browser submits the values as usual, or read them from the form on submit and post them yourself. The file upload exposes a documented hook for your upload request and reports progress per file; the simulated progress in the demo is the only thing you replace.

### What kind of site or app does this suit, and how do I rebrand it?

Anything with forms: a company site's contact and quote pages, a checkout, a sign-up, an application, a settings area. The worked example is a print studio, but nothing in the layout says so except the words. Rebranding is editing tokens.css: change the accent, the ground, the ink ramp, the face, the pill radius on buttons or the radius on fields, and every component follows in both themes.

### Which framework is it for?

None in particular. The controls are native form elements with classes and a few data attributes, styled by CSS custom properties and driven by plain JavaScript with GSAP, so they work in a static HTML form, a server-rendered page or a React, Vue, Svelte or Astro component. Because every control writes to a real input, select or textarea, a framework's own form handling reads the same values it would from an unstyled field. Render the markup, call the init after mount, and the validation and pickers attach themselves.

### What happens on a phone?

Side-by-side labels stack above their fields, grids collapse to one column, the date range shows one month, the time picker's columns fill the width, dialogs and pickers sit at the bottom of the screen, the signature pad and the sliders take touch, and every hover affordance also appears on focus and on tap. The catalogue's rail becomes an Index button opening a sheet.

### Is validation included, or do I bring my own?

Included. Fields validate on blur after first touch, re-validate as you type once invalid, and all validate on submit; the error summary at the top links to each field and focuses it. The rules are data attributes on the fields (required, email, minimum length, pattern, match another field), so you can add a rule without touching the script, and the hooks let a server-side error land in the same place.

## Vibe-Code Ready Setup

This component kit includes `START-HERE-AI.md`, a product-specific copy-paste setup prompt for Cursor, Claude Code, ChatGPT, GitHub Copilot, Windsurf, and other coding assistants. It tells the assistant to inspect the existing stack, integrate the supplied files, preserve the design, scope selectors, retain accessibility and responsive behaviour, add framework-appropriate GSAP cleanup, and report what it tested.

[How AI-assisted setup works](https://gsapvault.com/vibe-coding)

## How It Works

### The library is the page

The catalogue is generated from the component folders, so what you browse is exactly what you download. The rail lists every component by family, the search filters both the rail and the specimens, and each specimen is the control in every state a buyer would check, with product copy rather than placeholder text.

### One token file, two themes

Surfaces, ink, lines, accent, status colours, radii, spacing, control heights, durations and eases are role-named custom properties in one file. The dark theme re-values the same names, so a component never branches on the theme and a rebrand is one edit. Two of those tokens, the pill radius on buttons and the 6px radius on fields, are the register's signature and take one line each to change.

### Real form fields underneath

A custom select keeps a native select in the DOM, a masked card number writes its digits to a hidden input, a date picker carries an ISO date, a signature pad carries a data URL. Submit the form and the values are there, so the components work with any backend, any framework and no JavaScript of yours.

## Documentation

How this component kit works and how it goes into a page. The reference you use once you own the files (worked examples, events, the programmatic API, the class list) ships with the download.

### Quick Start

There are two ways in. Both need GSAP (core; Flip for the reflows and Draggable for the repeater and the banner image).

**Everything, two files.** In `<head>`:

_Code snippet omitted: it ships with the download._

At the top of `<body>`, paste the contents of `assets/icons.svg` once (it is an SVG sprite; the icons reference it with `<use href="#i-name">`). Before `</body>`:

_Code snippet omitted: it ships with the download._

Then copy any component's fragment from `components/<name>/specimen.html` into your form.

**One component.** Link `assets/tokens.css`, `assets/base.css` and the component's `components/<name>/style.css`; load GSAP, `assets/base.js` and the component's `components/<name>/script.js`; paste its `specimen.html`. `tokens.css`, `base.css` and `base.js` are required by everything; a component's own files are all it adds.

The scripts find every instance of their component by its `data-kit` attribute and initialise each once, so the same fragment can appear as many times as you need. If you render the markup from a framework, call the init after mount (each script is an IIFE that runs on `DOMContentLoaded` or immediately if the DOM is already parsed; reloading it, or dispatching a synthetic `DOMContentLoaded`, initialises anything new).

### What's Included

- `index.html`: the catalogue, every component assembled. Generated from `components/` and `kit.json`; the rail and search are demo furniture
- `contact.html`, `checkout.html`, `signup.html`, `application.html`, `settings.html`: the five forms as full pages
- `kit.json`: the manifest: families, components, their root selectors and keyboard contracts
- `components/<name>/`: one folder per component: `specimen.html` (the fragment), `style.css`, `script.js`
- `assets/tokens.css`: **the design system**: every surface, ink, line, accent and status colour, the type scale, spacing, radii, control heights, durations and eases, in two themes
- `assets/base.css`: reset, type ramp, the shared primitives (`.btn`, `.input`, `.label`, `.hint`, `.error`, `.field`, `.field--side`, `.kbd`, `.badge`, `.avatar`, `.icon`, `.card`, `.menu`, `.layer`) and layout utilities
- `assets/base.js`: `window.Kit`, the shared runtime: the overlay layer stack, positioning, focus helpers, motion tokens, the theme switch, a live region
- `assets/icons.svg`: the icon sprite
- `assets/style.css` and `assets/script.js`: the two bundles, generated from the files above
- `assets/catalogue.css` and `assets/catalogue.js`: the catalogue page chrome only; not needed in a product

### The five forms

Each form has two lives. In the catalogue it is a specimen in a fixed frame, so you can see the parts compose. As a page it fills the viewport and behaves like the product: fields validate, the upload runs, the stepper steps, the submit button morphs through loading and the success state replaces the form.

- **Contact** (`contact.html`) is the worked example: a project brief with contact details, a service select, a budget slider, a delivery date, the brief itself, artwork upload with per-file progress, consent, and a success state with a reference number.
- **Checkout** (`checkout.html`): address autocomplete, delivery options as choice cards, card details with masks and brand detection, a promo code and an order summary that updates.
- **Sign up** (`signup.html`): email and a password with a strength meter, a one-time code step, then company and role.
- **Application** (`application.html`): a four-step job application with the stepper, a CV upload, questions with conditional fields, and a review step.
- **Account settings** (`settings.html`): profile with avatar upload, notification switches, a password change, and a danger zone with a confirm dialog.

Every form is composed from the components with include directives in its `specimen.html` and a short glue `script.js`; nothing in a form is markup you cannot also find in a component folder.

### Components

<!-- kit:components -->

#### Foundations

The tokens every control reads, so a rebrand is one file.

| Component | Folder | Root | Keyboard |
|---|---|---|---|
| Colour roles | `components/colors/` | `assets/tokens.css` |  |
| Type ramp | `components/typography/` | `assets/tokens.css` |  |
| Icons | `components/icons/` | `assets/icons.svg` |  |
| Field anatomy and spacing | `components/layout/` | `assets/base.css` |  |

#### Controls

The things a hand rests on. Every one has a keyboard route and a disabled state.

| Component | Folder | Root | Keyboard |
|---|---|---|---|
| Button | `components/button/` | `.btn` | Enter, Space |
| Icon button | `components/icon-button/` | `.btn--icon` | Enter, Space |
| Switch | `components/switch/` | `[data-kit="switch"] .k-switch__control` | Space |
| Checkbox and radio | `components/checkbox-radio/` | `.k-checkbox-radio__item` | Space; arrows within a radio group |
| Choice cards | `components/choice-cards/` | `.k-choice-cards` | Space; arrows within the radio set |
| Segmented control | `components/segmented-control/` | `[data-kit="segmented-control"] [role="radiogroup"]` | Arrows, Home, End |
| Chip group | `components/chip-group/` | `.k-chip-group` | Space toggles; arrows move |
| Quantity stepper | `components/quantity-stepper/` | `[data-kit="quantity-stepper"] .k-quantity-stepper__field` | Arrows, typing, Home, End |
| Slider | `components/slider/` | `.k-slider` | Arrows, Home, End, PageUp, PageDown |
| Rating | `components/rating/` | `[data-kit="rating"] [role="radiogroup"]` | Arrows, numbers 1 to 5 |

#### Text inputs

Fields that take typing. Each shows its label, hint, error and disabled state.

| Component | Folder | Root | Keyboard |
|---|---|---|---|
| Text field | `components/text-field/` | `.k-text-field__item` | Native |
| Textarea | `components/textarea/` | `.k-textarea__item` | Native |
| Password field | `components/password-field/` | `.k-password-field__item` | Native; Enter on the reveal button |
| Phone field | `components/phone-field/` | `.k-phone-field__item` | Native; arrows in the country list |
| Number field | `components/number-field/` | `.k-number-field__item` | Arrows step; typing |
| Masked input | `components/masked-input/` | `.k-masked-input__item` | Native; the mask skips separators |
| Search field | `components/search-field/` | `.k-search-field` | / focuses, Escape clears |
| One-time code | `components/otp-field/` | `.k-otp-field` | Digits advance, Backspace retreats, paste fills |
| Inline edit | `components/inline-edit/` | `.k-inline-edit` | Enter edits and saves, Escape cancels |

#### Selection

Choosing from a list. Every list opens through the shared layer so Escape and focus behave once.

| Component | Folder | Root | Keyboard |
|---|---|---|---|
| Select | `components/select/` | `[data-kit="select"] .k-select__field` | Arrows, type-ahead, Enter, Escape |
| Combobox | `components/combobox/` | `[data-kit="combobox"] .k-combobox__field` | Arrows, Enter, Escape, typing filters |
| Multi-select | `components/multi-select/` | `[data-kit="multi-select"] .k-multi-select__field` | Arrows, Enter toggles, Backspace removes the last chip |
| Tag input | `components/tag-input/` | `.k-tag-input` | Enter or comma adds, Backspace removes |
| Address autocomplete | `components/address-autocomplete/` | `.k-address-autocomplete` | Arrows, Enter, Escape |
| Country select | `components/country-select/` | `[data-kit="country-select"] .k-country-select__field` | Arrows, type-ahead, Enter, Escape |
| Colour picker | `components/colour-picker/` | `.k-colour-picker` | Arrows on the swatches; typing a hex |
| Time picker | `components/time-picker/` | `[data-kit="time-picker"] .k-time-picker__field` | Arrows, typing, Enter, Escape |

#### Pickers and uploads

Dates, files and drawn input: the controls that take something other than typing.

| Component | Folder | Root | Keyboard |
|---|---|---|---|
| Date picker | `components/date-picker/` | `[data-kit="date-picker"] .k-date-picker__field` | Arrows move days, PageUp and PageDown months, Enter picks, Escape closes |
| Date range picker | `components/date-range-picker/` | `[data-kit="date-range-picker"] .k-date-range-picker__field` | Arrows, Enter twice, Escape |
| File upload | `components/file-upload/` | `.k-file-upload` | Enter on Choose files; Tab reaches each row's actions |
| Image upload | `components/image-upload/` | `.k-image-upload` | Enter opens the picker |
| Signature pad | `components/signature-pad/` | `.k-signature-pad` | Tab to the typed alternative; buttons for clear and undo |

#### Form structure

How fields sit together: anatomy, groups, sections, steps and the bits that appear conditionally.

| Component | Folder | Root | Keyboard |
|---|---|---|---|
| Form page | `components/form-page/` | `.k-form-page` | Native |
| Field | `components/field/` | `.k-field` | Native |
| Fieldset | `components/fieldset/` | `.k-fieldset` | Native |
| Form section | `components/form-section/` | `.k-form-section` | Native |
| Form grid | `components/form-grid/` | `.k-form-grid` | Native |
| Inline form | `components/inline-form/` | `.k-inline-form` | Enter submits |
| Form actions | `components/form-actions/` | `.k-form-actions` | Native |
| Form stepper | `components/form-stepper/` | `.k-form-stepper` | Enter continues; steps are links once visited |
| Collapsible | `components/collapsible/` | `.k-collapsible` | Enter or Space toggles |
| Conditional fields | `components/conditional-fields/` | `.k-conditional-fields` | Native |
| Repeater | `components/repeater/` | `.k-repeater` | Enter on Add; Tab through each row |
| Consent | `components/consent/` | `.k-consent` | Space |

#### Validation and feedback

What the form says back: errors, progress, confirmation and the overlays a form opens.

| Component | Folder | Root | Keyboard |
|---|---|---|---|
| Validation | `components/validation/` | `.k-validation` | Native |
| Error summary | `components/error-summary/` | `.k-error-summary` | Enter on an item moves focus to the field |
| Submit button | `components/submit-button/` | `.k-submit-button` | Enter, Space |
| Toast | `components/toast/` | `Kit.toast({ title, body, action })` | Escape dismisses the newest |
| Inline alert | `components/inline-alert/` | `.k-inline-alert` | Native |
| Tooltip | `components/tooltip/` | `[data-tooltip]` | Focus shows |
| Success state | `components/success-state/` | `.k-success-state` | Native |
| Dialog | `components/dialog/` | `[data-kit="dialog"] .k-dialog__layer` | Escape, Tab trapped, Cmd/Ctrl+Enter confirms |
| Popover | `components/popover/` | `[data-kit="popover"] .k-popover__panel` | Escape, outside press |

#### Forms

Five complete forms composed from the components above, each also a full page.

| Component | Folder | Root | Keyboard |
|---|---|---|---|
| Contact form | `components/contact-form/` and `contact.html` | `.k-contact-form` | Tab through; Enter submits |
| Checkout | `components/checkout-form/` and `checkout.html` | `.k-checkout-form` | Tab through; Enter submits |
| Sign up | `components/signup-form/` and `signup.html` | `.k-signup-form` | Tab through; Enter continues |
| Application | `components/application-form/` and `application.html` | `.k-application-form` | Tab through; Enter continues |
| Account settings | `components/settings-form/` and `settings.html` | `.k-settings-form` | Tab through; Cmd/Ctrl+S saves |

<!-- /kit:components -->

### Themes

The theme is one attribute on the root: `<html data-theme="light">` or `dark`. `assets/tokens.css` defines every value for both; no component has a theme branch, and the scripts never read the theme. `Kit.theme.set('dark')` switches it, remembers it in `localStorage` and dispatches `kit:theme` on the document for anything that reads a colour at runtime (the colour picker's pad re-renders on it).

To rebrand, edit `tokens.css`: `--accent` and its hover, active, ink and wash values; the `--bg*` surfaces; the `--ink*` ramp; `--font-ui`; and the two signature tokens, `--radius-btn` (pill buttons) and `--radius-field` (6px fields). Keep the contrast pairs the colour sheet in the catalogue reports at 4.5:1 or above in both themes.

### Motion and reduced motion

Durations and eases are tokens (`--dur-fast`, `--dur-base`, `--dur-slow`, `--ease-out`, `--ease-inout`, `--ease-spring`) read by CSS and by `Kit.dur()` / `Kit.ease()`. Under `prefers-reduced-motion: reduce`, `Kit.dur()` returns 0 and every component mounts and changes state in its final position; the progress bars, drawn checks and reveals complete at once. Nothing runs a ticker while it is off screen (`Kit.onVisible`).

### Keyboard contract

Every overlay in the kit (select, combobox, multi-select, country, colour and time pickers, the two calendars, popovers, dialogs, the recent-searches menu) opens through `Kit.layer.open()`, which owns Escape, the focus trap on modal layers, focus return to the trigger and the scroll lock. The per-component keys are in the table above; the patterns follow the WAI-ARIA Authoring Practices (combobox, listbox, grid for calendars, radiogroup for segmented controls and choice cards, switch, slider, tablist for nothing here, dialog).

### What is demo-only

`assets/catalogue.css` and `assets/catalogue.js` draw the catalogue page: the rail, the search, the specimen frames and the theme toggle. Buttons in a specimen marked "demo" in its comment (Simulate drop, Fail next, Replay, Fire five) exist so the catalogue can show a state that needs a server or a real file. The `upload(file, onProgress)` hook in the file upload and the simulated verification in the one-time code field are the two places you connect a request.

### Requirements

- GSAP 3.12+ (built against 3.15.0); Flip and Draggable from the same release
- Any modern browser; the components use `:has()`, `inset`, container-free layout and `IntersectionObserver`
- No build step, no framework, no dependency beyond GSAP and the Inter web font

## What You Get

- `index.html`: working demo page
- `assets/script.js`: commented, readable source
- `assets/style.css`: effect styles
- `README.md`: full documentation with examples and framework integration notes
- `START-HERE-AI.md`: product-specific copy-paste prompt for AI-assisted setup
- `LICENSE.txt`: standard license terms
- Lifetime updates: re-download anytime from your library

## Get the Code

This is a premium component kit. The standard license costs £25 one-time and covers unlimited personal and commercial projects with no attribution required. The only restrictions: no redistribution of the code itself and no competing effect libraries.

- [Buy Fieldset Forms UI Kit](https://gsapvault.com/ui-elements/fieldset-forms-ui-kit)
- [The Vault (£99 one-time, best value): everything in the catalogue, including future releases](https://gsapvault.com/effects)

---

From [GSAP Vault](https://gsapvault.com): production-ready GSAP animation effects. Full catalog for agents: https://gsapvault.com/llms-full.txt
