Kanzo UI
Forms

Controls

Every form control in the library, grouped by what it captures. A table index — start here to find the right one.

Every control goes inside a Field the same way, so there is no per-control API to learn. This page is the index: find the control you need by what it captures, then follow the link for its own page.

The naming rule that explains half of these. A kebab-case file is the vendored primitive — the compound with all its parts exposed. A PascalCase one is our pre-assembled convenience, built on it: FacetFilter imports listbox and popover, FieldArray imports field. They are not competitors; one is made of the other. Default to the PascalCase one, and drop to the primitive when you need to rearrange the parts. The rule in full is on Philosophy.

Text

ControlWhat it isReach for it when
InputA single-line text input.The everyday field.
Input type="number"The same input, numeric, with a decimal keypad on mobile. No steppers — see NumberInput for those.A number typed straight in: a price, an amount.
TextareaMulti-line text.A description, a note, free text.
InputGroupAn input flanked by addons — a prefix, a unit, a button.The value needs an affix or an inline action.
EditableEdit-in-place: a preview that swaps for an input on click.The value is normally read, and editing it is the exception.

Choice

ControlWhat it isManyReach for it when
NativeSelectThe browser's own <select> element, styled to the input scale.no — it is the OS pickerFew options and plain text: it costs no JavaScript, and on mobile it opens the platform picker.
SelectA listbox in a popover, driven by a collection.multipleThe options need to look like more than plain text: icons, descriptions, groups.
ListboxThat same listbox with no popover of its own — you place it.selectionModeThe list must live somewhere Select cannot put it: inline in a panel, or in a popover you own.
ComboboxA text input plus that same listbox — typing filters the collection.multipleThe list is long enough that typing beats scrolling.
FacetFilterA Listbox in a popover behind a trigger that counts what is picked.multipleNarrowing a table or a dashboard, where the options are data and carry counts.
TagsInputA list of removable tokens with no option collection — the user invents the values.alwaysThe values do not exist beforehand: free-form tags, keywords, addresses.
RadioGroupA few options, all visible at once.noOne of a few, no popover.
RadioGroupCardThat same item styled as a card, with room for an icon, a description or a preview.noOne of a few, where the options need explaining.
SegmentGroup2–4 options as a compact inline switch. Radio semantics, segmented look.noSwitching a view in place.

Rule of thumb: under ~7 options, NativeSelect; over ~15, Combobox, because that is where scrolling starts costing more than typing; Select in between, when the options need to look like more than plain text. Multiple selection is not the deciding axisSelect and Combobox both take multiple, and TagsInput is multiple by nature. Typing is.

Autocomplete is not a control here. It is the presentation of a Combobox with no trigger button — showTrigger={false} — so it opens on type rather than on click. Same machine, same props, one page: Combobox. A further face of that same machine, Command, is not a form control at all: what it captures is an action, so it is filed under actions.

A menu is a command; a listbox is a value

Half the "which control?" questions here are one question wearing several hats, and the answer is an ARIA role, not a look. Two surfaces open a popover over a list, and they are not interchangeable. role="menu" (Menu, MenuItem, MenuCheckboxItem) is a list of commands: you press one, something happens, the surface closes. It is not anybody's data. role="listbox" (inside Select and Combobox) is a value: it lives in state, and the popover is only its editor.

The test, in one line: if closing the surface leaves state, it is a listbox; if it leaves only an effect, it is a menu.

That is the only axis that matters. The rest of the Choice table is two orthogonal questions on top of it — can you type to filter? and how many can you pick? — which is why these controls look alike and are not.

Command is the honest exception, and reading it clarifies the rule rather than breaking it: a palette runs commands yet is built on a combobox, because the role follows the interaction, not the payload. Type to filter, arrow to highlight, enter to run is combobox behaviour, and a menu cannot filter at all. So: a value needs a listbox; a command needs a menu unless it needs to be searched.

The rule bites hardest on filters, because a filter is a value while the popover-with-checkboxes idiom looks like a menu. Getting the role wrong costs more than purity: a menuitemcheckbox list cannot announce "2 of 5 selected", and a menu has nowhere to grow a search field the day the list has 200 values.

Boolean

ControlWhat it isReach for it when
SwitchReads as on/off.A setting that takes effect immediately.
CheckboxReads as included/excluded, with a third indeterminate state.A value submitted with the form.
CheckboxGroupOne value array across several checkboxes.Related checkboxes you submit together.

Value

ControlWhat it isReach for it when
NumberInputA spinbutton: stepper triggers, arrow keys, drag-to-scrub.A bounded quantity the user nudges — a count, a page size.
SliderA value or range on a track.A bounded number where the range matters more than the digit.
RatingA row of stars on a fixed scale.A score out of five.
DatePickerA date input with a calendar popover. Takes Ark's DateValue; the ISO-string adapter is two functions at your seam.Picking a date in a form.
CalendarThe same machine inline, so the month grid is always visible.A calendar that is furniture, not a form value.
ColorPickerArea, hue and hex, with preset swatches.Picking a colour.

A row of colours the user is not editing is not a control at all: when the colour merely pictures a value that has a name, reach for Swatch, which is aria-hidden and never focusable.

Files

ControlWhat it isReach for it when
FileUploadA dropzone plus the list of what was picked, with previews.The value is a file, not text.

Credentials

ControlWhat it isReach for it when
PasswordInputA password input with a reveal toggle.Entering a password — sign-in, sign-up.
PasswordInput + hasStoredValueThe same input in stored-credential mode: renders empty when a secret exists, and submitting empty means "keep it".Editing a credential that already lives server-side.
PinInputOne cell per character; a pasted code spreads across them.A one-time password or verification code.

Repeating

ControlWhat it isReach for it when
FieldArrayN rows with add and remove, stateless — the caller owns the values.A field the user can have several of.

FieldArray's rowKey must be stable across a commit. If a row's key changes when its value is first saved, React remounts the input and the user loses focus mid-typing — do not "simplify" it to the array index.

AI-assisted

These take suggestions from a model, and the library never calls one — you pass a stream. See AI-assisted fields for the shared contract.

ControlWhat it isReach for it when
SuggestRoot + SuggestMark + SuggestListA ✨ inside a field that streams candidates into a strip underneath it.The user is choosing a value and needs options they did not think of.
CompleteRoot + CompleteGhostA field that completes inline as you type, Tab to accept.The user is writing prose and a streamed continuation helps.

Every one of these sets its state on the Field, never on the control — see Building a form, then Validation for how errors are shown.

RadioGroupProps is exported, so a wrapper can take the same props without restating them.

On this page