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 fromcomponents/andkit.json; the rail and search are demo furniturecontact.html,checkout.html,signup.html,application.html,settings.html: the five forms as full pageskit.json: the manifest: families, components, their root selectors and keyboard contractscomponents/<name>/: one folder per component:specimen.html(the fragment),style.css,script.jsassets/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 themesassets/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 utilitiesassets/base.js:window.Kit, the shared runtime: the overlay layer stack, positioning, focus helpers, motion tokens, the theme switch, a live regionassets/icons.svg: the icon spriteassets/style.cssandassets/script.js: the two bundles, generated from the files aboveassets/catalogue.cssandassets/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
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 |
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 andIntersectionObserver - No build step, no framework, no dependency beyond GSAP and the Inter web font
Worked examples, the events and programmatic API, and the class reference ship with the download, alongside the full source.