Functional Weave
Code in Rust

Suites · forms-ui

Accessible React forms

GOV.UK-pattern form components for React (text, select, radios, checkboxes, dates, passwords, error summary) and the pure form state and checks behind them.

30 capabilities (9 core, 21 optional) and 8 gaps, in build order. Put each line in the file that calls it, then fune build.

The components are React 19 and TypeScript only; the helpers (form.*) and the validation they pair with are in every language.

1. Form state

Values, touched fields, errors and submit as a pure reducer, shared by browser and API.

form.state core
initialFormState, formReducer and visibleErrors, for useReducer.
A form's state as a pure reducer: values, touched fields, validator errors and the submit, for useReducer.
Not available in Rust: typescript only

2. Fields

Labelled, hinted inputs with their errors wired up for screen readers (React, TypeScript only).

react.form.form-field core
Wires a label, hint and error message to one control by id.
Wire a label, hint and error message to one form control by id, the accessible way (GOV.UK form group pattern).
Not available in Rust: typescript only
react.form.text-field core
Single-line text input with hint, error, autocomplete, prefix and suffix.
A labelled single-line text input with hint, error message, autocomplete, prefix and suffix (GOV.UK text input).
Not available in Rust: typescript only
react.form.button core
Primary, secondary or warning button that stays focusable while loading.
A form button in primary, secondary or warning style that stays focusable while loading (GOV.UK button).
Not available in Rust: typescript only
react.form.textarea optional
Multi-line box with an optional live character or word count.
A labelled multi-line text box with hint, error and an optional live character or word count (GOV.UK).
Not available in Rust: typescript only
form.character-count optional
The "You have 20 characters remaining" message, in any language.
The GOV.UK character count message for a text box: characters or words left or over a limit, with a threshold.
fune!(form.character-count@^1);  // then call character_count(…)
react.form.select optional
Drop-down list with hint, error and an optional empty first option.
A labelled drop-down list with a hint, error message and an optional empty first option (GOV.UK select).
Not available in Rust: typescript only
react.form.password-field optional
Password input with Show/Hide and a live policy checklist.
A password input with a Show/Hide button and an optional live checklist of a password policy (GOV.UK password input).
Not available in Rust: typescript only

3. Choices

Questions answered by picking.

react.form.radio-group optional
Choose one of several radios, with hints, an "or" divider and inline yes/no.
Choose exactly one of several radios, with item hints, an "or" divider and inline yes/no (GOV.UK radios).
Not available in Rust: typescript only
react.form.checkbox-group optional
Tick any of several checkboxes, with an exclusive "None".
A question answered by ticking any of several checkboxes, with item hints and an exclusive "None" (GOV.UK checkboxes).
Not available in Rust: typescript only
react.form.checkbox optional
One checkbox such as "I agree to the terms".
One checkbox with its label beside it, such as "I agree to the terms" (GOV.UK single checkbox).
Not available in Rust: typescript only
react.form.fieldset optional
Groups related inputs under a legend with a shared hint and error.
Group related inputs under a legend, with a hint and error message described to the whole group (GOV.UK fieldset).
Not available in Rust: typescript only

4. Dates

Dates typed as day, month and year.

react.form.date-input optional
Day, month and year boxes under one legend, marking the boxes in error.
Day, month and year boxes under one legend, with hint, error message and the boxes in error marked (GOV.UK date input).
Not available in Rust: typescript only
form.date-parts optional
Checks those three boxes with GOV.UK's error messages, in any language.
Check a date typed into day, month and year boxes, with GOV.UK's error messages and the boxes to mark in error.
fune!(form.date-parts@^1);  // then call validate_date_parts(…)

5. Errors

Tell people what to fix.

react.form.error-summary core
"There is a problem" box linking to each field in error, focused on arrival.
A "There is a problem" box linking to each field in error, focused on arrival, built from a validator's fields (GOV.UK).
Not available in Rust: typescript only

6. Styles

A default look you can theme.

react.form.styles optional
Optional stylesheet for the caps-* classes, themed by --caps-form-* properties.
An optional stylesheet for the react.form elements' caps-* classes, themed by --caps-form-* custom properties.
Not available in Rust: typescript only

7. Contact details from validation-basics

Check and normalise a person's contact details before storing them.

validation.email core
Is an email address plausible, by a documented subset of RFC 5322.
Is this a plausible email address? A documented, pragmatic subset of RFC 5322, not the full grammar.
fune!(validation.email@^1);  // then call is_email(…)
validation.phone-e164 core
Normalises a phone number to +44… E.164 for a default country.
Normalise a phone number to E.164 (+447700900123) using a default country's trunk and dialling prefixes.
fune!(validation.phone-e164@^2);  // then call validate_phone_e164(…)
validation.uk-postcode core
Validates a UK postcode and puts it in canonical form.
Validate a UK postcode and normalise it to canonical upper case with one space before the inward code.
fune!(validation.uk-postcode@^2);  // then call validate_uk_postcode(…)
text.normalise-name optional
Tidies a typed name: spacing and title case with Mc, O' and hyphen rules.
Tidy a personal name: trim, collapse whitespace and title-case, with Mc, Mac, O', hyphen and van/de rules.
fune!(text.normalise-name@^1);  // then call normalise_name(…)
auth.normalise-email optional
Lower-cases an email's domain for storage and lookup.
Trim an email address and lower-case its domain for storage and lookup, or null if it is not a plausible address.
fune!(auth.normalise-email@^1);  // then call normalise_email(…)

8. Bank details from validation-basics

Check payee and customer bank details before money moves.

validation.iban core
Checks an IBAN's mod-97 checksum and its country's length.
Check an IBAN against the ISO 13616 mod-97-10 checksum and the registered length for its country.
fune!(validation.iban@^1);  // then call is_iban(…)
validation.bic optional
Checks a SWIFT/BIC code's format and splits it.
Check the format of a SWIFT/BIC code (8 or 11 characters) and split it into its parts.
fune!(validation.bic@^1);  // then call validate_bic(…)
validation.uk-sort-code-account optional
Checks a UK sort code and account number by the Vocalink modulus rules, against a table you supply.
Check a UK sort code and account number with the Vocalink/Pay.UK modulus rules, against a table you supply.
fune!(validation.uk-sort-code-account@^3);  // then call validate_uk_sort_code_account(…)
validation.uk-modulus-table optional
Parses Vocalink's VALACDOS and SCSUBTAB files into that table.
Parse Vocalink's VALACDOS.txt and SCSUBTAB.txt into the table UK sort code modulus checking needs.
fune!(validation.uk-modulus-table@^1);  // then call parse_uk_modulus_table(…)

9. Identifiers and check digits from validation-basics

Catch mistyped reference numbers by their check digits.

validation.luhn optional
Luhn mod-10 check, for card numbers and many reference numbers.
Check a digit string against the Luhn mod-10 checksum used by payment cards and many identifiers.
fune!(validation.luhn@^1);  // then call is_luhn(…)
validation.uk-company-number optional
Checks a Companies House number's format and prefix.
Check a Companies House company number's format and prefix (SC, NI, OC, LP...) and zero-pad it to eight characters.
fune!(validation.uk-company-number@^2);  // then call validate_uk_company_number(…)
validation.lei optional
Checks a Legal Entity Identifier's check digits.
Check a 20-character Legal Entity Identifier against its ISO 17442 / ISO 7064 MOD 97-10 check digits.
fune!(validation.lei@^1);  // then call validate_lei(…)
validation.gtin optional
Checks an EAN/UPC/GTIN barcode number.
Check an EAN-8, UPC-A, EAN-13 or GTIN-14 barcode number against the GS1 mod-10 check digit.
fune!(validation.gtin@^1);  // then call validate_gtin(…)

10. Displaying sensitive values from validation-basics

Show stored identifiers without exposing them.

text.mask optional
Masks all but the last digits of a card, account or phone number.
Mask all but the last n characters of a card, account or phone number, optionally keeping separators.
fune!(text.mask@^1);  // then call mask(…)

Gaps

What this kind of app usually needs that Functional Weave does not have yet: write these yourself, or use a service.

  • other-frameworks Vue, Svelte, Angular or React Native components: only React is covered.
  • multi-step-flows Multi-page journeys: routing between steps, check-your-answers pages and saving progress.
  • file-upload File upload fields with progress, type and size checks.
  • autocomplete Autocomplete or combobox inputs (address finder, country picker).
  • submission Posting the form, CSRF protection and showing server errors back in the fields.
  • address-lookup Turning a postcode into a list of addresses (Royal Mail PAF or a lookup API) is network work and not in caps.
  • email-deliverability Whether a mailbox exists (MX lookups, a confirmation email): validation.email checks the syntax only.
  • vocalink-data The Vocalink modulus tables themselves: download them from Pay.UK under its terms; caps parses them but does not ship them.