Input
A text field, with clear button and groups.
Example
We send the invite here.
Installation
pnpm dlx shadcn@latest add superzero11/uiset/inputIt lands in components/ui/input.tsx, with UISet’s root (uiset). Wrap your app in <UISet> once, and every component takes its skin.
What UISet adds
The component is UI SDK’s own, with its parts, props and names, so everything below works as UI SDK documents it. UISet adds the look and checks it:
- Styles in five skins, each in light and dark, from CSS variables you can override.
- Text at 4.5:1 contrast and control edges and focus rings at 3:1, in every skin and theme, checked with axe in tests.
- Haptic cues on phones, and sound cues when you set
soundon<UISet>. - Examples that name every control, so agents can find it (see Agents below).
The API reference and accessibility notes below are UI SDK’s, from its docs for @ui-sdk/react (Apache-2.0). Input on ui-sdk.dev has more usage examples. Your coding agent can read the same page at node_modules/@ui-sdk/react/docs/components/input.md.
API Reference
Props are the same as below, as React props, plus every native input prop.
Input
-
value?(string): The value, for a controlled field. -
defaultValue?(string): The value it starts with. A form reset returns here. -
onValueChange?(((value: string, details: ChangeDetails<InputValueChangeReason>) => void)): Called when the user changes the value: typing ("input-change"), a Clear part ("clear-press"), a form reset ("reset") or a controller ("imperative").details.cancel()keeps the value as it was. -
controller?(object): Reads and writes the field from anywhere. Create one withcreateInputController(). -
debug?(boolean): Logs every state change with its reason to the console, in development builds. -
disabled?(boolean): Disables the field. -
readOnly?(boolean): Makes the field read-only. -
required?(boolean): Makes the field required.
InputGroup
debug?(boolean): Logs every state change with its reason to the console, in development builds.
InputClear
A <button> that empties the input in its group and focuses it. It renders only while there's text to clear.
State
filled(boolean): Whether the field holds any text.disabled(boolean): Whether the field is disabled.readOnly(boolean): Whether the field is read-only.required(boolean): Whether the field is required.
InputGroup and InputClear receive the state of the input inside the group.
filled(boolean): Whether the field in the group holds any text.disabled(boolean): Whether the field in the group is disabled, by itself or by a<fieldset>.readOnly(boolean): Whether the field in the group is read-only.
Reasons
input-change(Event): Typing, pasting or dropping changed a text field's value; in a combobox it can also open or close it, or Enter keeps the typed text as the value.clear-press(MouseEvent | KeyboardEvent): A Clear part was pressed, like on an input, a select or a combobox.reset(none): A form reset.imperative(none): A controller orapicall, or a property set on a web component.
Controller
Create one with createInputController() and pass it as controller.
getValue()(() => string): The current value.setValue(value, options?)((value: string, options?: ChangeOptions<InputValueChangeReason> | undefined) => boolean): Sets the value as if the user typed it, soinputfires. Returns false when the change was canceled or nothing changed.clear(options?)((options?: ChangeOptions<InputValueChangeReason> | undefined) => boolean): Empties the field, as if the user deleted the text, soinputfires. Returns false when the change was canceled or nothing changed.focus()(() => void): Moves focus to the field.
Accessibility
Give the input a visible field label or an aria-label, and give the clear button an accessible name. The native input keeps standard text editing, selection, autocomplete and form behavior.
- The label names the input and the description describes it.
- Clicking the label focuses the input.
- An invalid input is marked once the form tries to submit.
- Data-filled follows the text.
- An input group's clear button shows only while there's text.
- 's value property writes the field quietly, and its api reports. Web components only.
Enhancements
- Changes report their reason: typing, then a reset.
- A canceled change keeps the text as it was.
- A canceled change keeps a controlled input's text as it was.
- A canceled change waits for an IME to finish before the text goes back.
- A controlled input keeps every keystroke.
- A required input marks its label required.
Input group
- The clear button empties the field, reports why, and returns focus.
- Pressing the group's text focuses its field.
- The clear button hides while its field is disabled.
Runs in React, Vue and web components.
Agents
UI SDK’s agent bridge finds this component by its accessible name: give it a visible label or an aria-label, and an agent can read its state and call its actions without screenshots. Building with AI agents shows how to connect one.
This is agent.snapshot() for the example above, read live from this page. Change something in the example, then read it again: the values follow.
[
{
"ref": "c8",
"component": "input",
"actions": [
"setValue",
"clear"
],
"label": "Work email",
"value": ""
}
]