Skip to content
Twentyfirst UIHalo

Form

Forms · Form, TextField, SelectMenu, Textarea, Checkbox, Button

View as Markdown

Validation for native forms. Give rules by field name; on submit the form checks them, shows each message under its field, marks the field aria-invalid and focuses the first one. After the first submit, fields re-check as they change.

  • Rules: required, email, minLength/maxLength, min/max, pattern, and validate for anything else. Messages can be set per rule.
  • onSubmit receives the values by name; errors shows messages from the server.
  • Works with TextField, Input, Select, Textarea, SelectMenu, Checkbox and Switch.

Props

Form

PropTypeNotes
rules?Record<string, FormRule>Rules by field `name`. Fields show their message under the input.
onSubmit?(values: FormValues) => voidCalled with the values (by `name`) when every rule passes.
onInvalid?(errors: Record<string, string>) => voidCalled with the messages when the form is submitted with errors.
errors?Record<string, string>Messages from the server, by field name (for example after a failed save).
children?ReactNode
className?stringExtra class on the root element.
style?CSSPropertiesInline style on the root element.

TextField

PropTypeNotes
type?stringInput type (`"text"` by default): `"email"`, `"number"`, `"tel"`, `"url"`, `"password"` …
icon?IconName
suffix?ReactNode
value?string
defaultValue?string
placeholder?string
disabled?boolean
readOnly?boolean
autoComplete?string
autoFocus?boolean
min?number | stringSmallest value for `type="number"`, `"date"` and the like (native `min`).
max?number | stringLargest value (native `max`).
step?number | stringStep between valid values (native `step`), e.g. `1` for whole numbers or `"any"`.
minLength?numberFewest characters (native `minlength`).
maxLength?numberMost characters (native `maxlength`).
pattern?stringPattern the value must match (native `pattern`).
inputMode?"none" | "text" | "tel" | "url" | "email" | "numeric" | "decimal" | "search"Virtual keyboard on touch devices (native `inputmode`), e.g. `"numeric"` or `"decimal"`.
onChange?(e: ChangeEvent<HTMLInputElement>) => void
onBlur?(e: ChangeEvent<HTMLInputElement>) => void
onKeyDown?(e: KeyboardEvent<HTMLInputElement>) => void
action?ReactNodeAn interactive control at the end of the field (an `IconButton`: clear, copy, locate …). Unlike `suffix` it can be clicked, and it stays when the field shows an error or success mark.
reveal?booleanFor `type="password"`: a button that shows and hides the password (default true).
label?string
hint?string
error?string

SelectMenu

PropTypeNotes
options(string | SelectMenuOption)[]Required
value?string
defaultValue?string
onChange?(value: string) => void
placeholder?string
disabled?boolean
size?"sm" | "md"`sm`: a compact trigger, e.g. a sort menu next to a heading.
label?string
hint?string
error?string
className?stringExtra class on the root element.
style?CSSPropertiesInline style on the root element.

Textarea

PropTypeNotes
placeholder?string
value?string
defaultValue?string
rows?number
disabled?boolean
onChange?(e: ChangeEvent<HTMLTextAreaElement>) => void
label?string
hint?string
error?string
className?stringExtra class on the root element.
style?CSSPropertiesInline style on the root element.

Checkbox

PropTypeNotes
name?string
value?string
required?boolean
checked?boolean
defaultChecked?boolean
onChange?(e: ChangeEvent<HTMLInputElement>) => void
children?ReactNode
disabled?boolean
label?string
className?stringExtra class on the root element.
style?CSSPropertiesInline style on the root element.

Button

PropTypeNotes
variant?"primary" | "secondary" | "soft" | "ghost" | "danger" | "danger-solid"
size?"md" | "sm"
icon?IconName
iconRight?IconName
disabled?boolean
type?"button" | "submit" | "reset"
onClick?(e: MouseEvent<HTMLButtonElement>) => void
children?ReactNode
asChild?booleanRender the single child element (a link, a router Link) with the button's look instead of a <button>.
id?string
name?stringForm field name and value, sent with the form when this button submits it.
value?string
form?stringThe id of the form this button belongs to, when it sits outside it.
title?string
tabIndex?number
autoFocus?boolean
aria-label?string
aria-labelledby?string
aria-describedby?string
aria-expanded?boolean | "true" | "false"For disclosure and menu triggers: whether what the button controls is open.
aria-controls?string
aria-haspopup?boolean | "true" | "false" | "menu" | "listbox" | "tree" | "grid" | "dialog"
aria-pressed?boolean | "true" | "false" | "mixed"For toggle buttons.
aria-current?boolean | "true" | "false" | "page" | "step" | "location" | "date" | "time"
className?stringExtra class on the root element.
style?CSSPropertiesInline style on the root element.