Example#
Usage#
Use Form around any set of fields that is sent somewhere. It is a native form that takes over validation, timed so it helps without nagging: a field is checked when the form is sent and when someone leaves a field they typed in; an error clears the moment it is fixed.
- On a failed send every failed field gets its message, focus moves to the first one, and with two or more errors an
ErrorSummarylists them above the send key, each linked to its field. - Server results.
errorsandformErrorprint what the server said; the send key goes intoloadingwhile the form is pending. - Without JavaScript the form posts natively and the page prints the server's result.
- Default messages are literal (D-I2): "Add your name.", "That email looks incomplete."
Anatomy#
- FormNative form, validated by the kit.
.mk-form - FieldEach control in its Field.
.mk-field - Send keyThe action key, the form's one action.
.mk-button
Volume#
Reading layer: identical at every volume.
Quiet
Studio
Press
Rave
Content#
- Ask only for what you will use; every field is a reason to leave.
- The send key says what happens: "Send", "Get a quote".
- After sending, say what happens next and when: "Sent. I reply within one working day."
Do and don't#
Do
Don't
A form that shows every error in red the moment the page loads.
Accessibility#
- A field is checked on submit and on blur when it holds something; an error clears the moment it is fixed.
- A failed submit focuses and centres the first failed field; two or more failures print a summary linking to each.
- With JavaScript off the form posts natively.
| Keys | What happens |
|---|---|
| Enter in a field | Submits; a failed submit moves focus to the first failed field |
| Tab out of a field | Checks it when it holds something or is already marked |
| Enter on a summary link | Moves focus to that field |
The colour pairs it prints, with their contrast on both papers:
| Text | Surface | Role | Bone | Night |
|---|---|---|---|---|
--mk-text | --mk-surface | ui | not in this look | not in this look |
Props#
| Prop | Type | Default | Description |
|---|---|---|---|
action | string | ((formData: FormData) => void | Promise<void>) | none | A URL (native post, works without JavaScript) or a function action (React 19 form actions). |
errors | Readonly<Record<string, string>> | none | Server messages by field name. |
formError | string | none | A server message for the whole form (shown by `ErrorSummary`). |
copy | Partial<FormCopy> | none | |
onInvalidSubmit | ((problems: readonly FormProblem[]) => void) | none | Called with the problems after a submit that failed validation. |
children required | ReactNode | none |
Tokens#
Changelog#
Arrived in 0.1.0.
- The reading layer's controls, overlays, forms and visitor prefs (P2-T1 to P2-T5): every Button is the comic hit key, with IconButton, Link and Tooltip; Input, Textarea, Select, Checkbox and CheckboxGroup, Radio and RadioGroup, Switch, Slider with the ruler, RulerReadout and SegmentedControl; Dialog, Drawer, NavSheet, Tabs, Disclosure, Faq and faqJsonLd on Base UI 1.9 where the platform falls short; Field, Fieldset, Form with the site's inline validation, ErrorSummary, Callout, Honeypot, FormTimestamp and QuoteForm; PrefsScript under 1 KB, usePref and setPref with cross-tab sync, ThemeToggle and the visitor VolumeDial; VisuallyHidden.