Input
A text input. Input.Search adds a clear button and a search action;
Input.TextArea is the multi-line variant. Input.Number handles exact
numeric values with step controls.
import { Input } from '@jbpark/ui-kit';
<Input placeholder="Basic input" />
<Input.Search placeholder="Search..." onSearch={value => console.log(value)} />
<Input.TextArea placeholder="Text area" rows={3} />;
<Input.Number
label="Quantity"
min={0}
max={10}
defaultValue={2}
onChange={value => console.log(value)}
/>;
Input
A thin wrapper with no props beyond React.ComponentPropsWithRef<'input'>.
Input.Search
| Prop | Type | Default |
|---|---|---|
allowClear | boolean | true |
onChange | (e: ChangeEvent<HTMLInputElement> | { target: { value: string } }) => void | - |
onSearch | (value: string) => void | - |
onSearch fires on pressing Enter or clicking the search button. Also
accepts the rest of React.ComponentPropsWithRef<'input'>.
Input.TextArea
A thin wrapper with no props beyond
React.ComponentPropsWithRef<'textarea'>.
Input.Number
Input.Number uses Base UI Number Field for numeric parsing, keyboard steps,
validation, and form integration. Supply a visible label, an aria-label, or
an external <label htmlFor> paired with id.
| Prop | Type | Default |
|---|---|---|
label | string | - |
value | number | null | - |
defaultValue | number | - |
onChange | (value, eventDetails) => void | - |
min / max | number | - |
step | number | 'any' | 1 |
size | 'small' | 'middle' | 'large' | Config.componentSize or 'middle' |
placeholder | string | - |
disabled | boolean | false |
readOnly | boolean | false |
name | string | - |
required | boolean | false |
className | string | - |
classNames | { label?, group?, input?, decrement?, increment? } | - |
The callback receives null when the field is cleared. By default, direct
typing is clamped to min/max on blur while step buttons and keyboard
interactions clamp immediately. Use allowOutOfRange if form validation should
report an out-of-range typed value. step="any" disables step validation while
the buttons and arrows still step by 1. The component also passes through the
remaining Base UI Number Field root props, including format, locale, and
onValueCommitted.
Input.OTP
Segmented verification-code entry built on Base UI OTP Field. Values remain
strings, preserving leading zeroes. Provide label, aria-label, or an external
label paired with id. Each subsequent slot has its own accessible name;
getSlotLabel(index, length) can localize it. aria-describedby describes the
group once, rather than repeating the hint on every slot.
<Input.OTP
length={6}
label="Verification code"
name="code"
onChange={value => console.log(value)}
onComplete={value => console.log('Complete:', value)}
/>
| Prop | Type | Default |
|---|---|---|
length | positive safe integer | 6 |
value / defaultValue | string | - |
onChange / onComplete | (value, eventDetails) => void | - |
label | string | - |
size | 'small' | 'middle' | 'large' | Config size |
validationType | 'numeric' | 'alphanumeric' | 'none' | 'numeric' |
mask, disabled, readOnly, required | boolean | false |
name, form, inputMode, autoComplete | native input settings | autocomplete: 'one-time-code' |
inputRef | Ref<HTMLInputElement> | first slot |
ref | Ref<HTMLDivElement> | Base UI group |
placeholder | string | - |
classNames | { label?, group?, input? } | - |
Numeric mode filters non-digits; alphanumeric mode accepts ASCII letters and
numbers. Whitespace is removed, values are clamped to length, and normalizeValue
can apply an idempotent transformation. Full paste replaces the code, partial paste
starts at the focused slot. Typing advances focus; arrow keys navigate and Backspace
removes characters. Base UI handles native editing, autofill and validation.
Omitted or invalid lengths use six slots. Invalid lengths produce a development
warning instead of throwing during render. className, style, ref, data
attributes and event handlers all apply to the Base UI group root.
onComplete follows onChange when user entry completes the code. Pasting a full
code again can fire completion even if the value is unchanged. Initial or externally
controlled complete values do not represent user completion. Completion never
submits the form or sends/verifies a code. A named hidden input supplies the full
string to native forms. SMS delivery and retry timers belong to the application.
Form errors, reset, and focus
Wrap Input.OTP in Form.Field to display a caller-supplied error. Omit the OTP's
label when the field supplies it. The field's invalid state applies to every
editable slot; clearing the error also clears that state.
<Form.Field
name="code"
label="Verification code"
error="This code has expired. Request a new code."
>
<Input.OTP name="code" />
</Form.Field>
Base UI OTP Field does not reset its uncontrolled value on native form reset.
Use a controlled value and restore it in the form's onReset handler. inputRef
points to the first editable slot, so a button can return focus to code entry.
function VerificationForm() {
const [code, setCode] = useState('');
const inputRef = useRef<HTMLInputElement>(null);
return (
<form onReset={() => setCode('')}>
<Input.OTP
label="Verification code"
name="code"
value={code}
onChange={setCode}
inputRef={inputRef}
/>
<Button htmlType="reset">Reset</Button>
<Button onClick={() => inputRef.current?.focus()}>
Focus first slot
</Button>
</form>
);
}
Import useRef and useState from React and Button, Form, and Input from
@jbpark/ui-kit for these examples. Reset and focus actions do not complete,
submit, or verify a code.