A single-line text input component that integrates with Reef's container system for consistent border radius math and status coloring. Supports input masks, validation with Effect schemas, and various presets.
<TextInput placeholder="Enter text..." />
<TextInput label="Username" placeholder="Enter username" />
Current value: ""
const [value, setValue] = createSignal("");
<TextInput
label="Controlled"
value={value}
onValue={setValue}
placeholder="Type something..."
/><TextInput label="Disabled" placeholder="Cannot edit" disabled />
Fixed non-editable text at the start. Smart paste: if pasted content contains the prefix, it's automatically stripped.
<TextInput label="Username" prefix="@" placeholder="username" />
<TextInput label="Email" suffix="@company.com" placeholder="username" />
Slots allow custom content at the start or end of the input. Must be passed as functions to avoid hydration issues.
<TextInput
label="Search"
slotStart={() => <Icon icon="search" />}
placeholder="Search..."
/>When an error message is provided, the input automatically switches to danger status.
<TextInput label="Email" placeholder="Enter email..." errorMessage="Please enter a valid email address" />
Labels can be positioned above, below, before, or after the input.
<TextInput label="Above" labelPosition="above" /> <TextInput label="Below" labelPosition="below" /> <TextInput label="Before" labelPosition="before" /> <TextInput label="After" labelPosition="after" />
Use a validate function for validation and transformation. When allowInvalid is false (default), invalid keystrokes are prevented. When true, invalid input is allowed but shows an error.
const positiveIntValidator: ValidateFn<number> = (value) => {
const num = Number(value);
if (Number.isNaN(num)) return { valid: false, error: "Must be a number" };
if (!Number.isInteger(num)) return { valid: false, error: "Must be an integer" };
if (num <= 0) return { valid: false, error: "Must be positive" };
return { valid: true, value: num };
};
<TextInput
label="Age"
validate={positiveIntValidator}
allowInvalid
/>TextInput provides preset variants for common use cases.
Password input with visibility toggle button.
<TextInput.Password label="Password" placeholder="Enter password..." />
Search input with a search icon.
<TextInput.Search label="Search" placeholder="Search..." />
Email input with appropriate autocomplete.
<TextInput.Email label="Email" placeholder="you@example.com" />
URL input with optional protocol prefix.
<TextInput.URL label="Website" protocol="https://" placeholder="example.com" />
Number input with increment/decrement controls. Supports min, max, step, and scale (decimal places). Use arrow keys to increment/decrement.
Current value: 0
<TextInput.Number label="Quantity" min={0} max={100} step={1} />Currency input with currency symbol prefix and 2 decimal places.
<TextInput.Currency label="Price" currency="USD" />
Phone number input with pattern mask.
<TextInput.Phone label="Phone" placeholder="(555) 123-4567" />
US Social Security Number with automatic formatting (###-##-####).
<TextInput.SSN label="SSN" />
TextInput supports three types of masks for formatting input:
For fixed-length structured inputs. DSL: # = digit, A = letter, * = any.
// Phone number
mask={{ type: "pattern", pattern: "(###) ###-####" }}
// SSN
mask={{ type: "pattern", pattern: "###-##-####" }}For numeric inputs with locale-aware formatting. Supports min, max, scale (decimal places), and step.
mask={{ type: "number", min: 0, max: 100, scale: 2 }}For variable-length inputs with validation. Supports pattern (regex), minLength, maxLength, and redact.
mask={{ type: "text", maxLength: 50, pattern: /^[a-z]+$/ }}| Name | Type | Default | Description |
|---|---|---|---|
value | Accessor<string> | undefined | Controlled value accessor for the input |
onValue | (value: string) => void | undefined | Callback when the input value changes |
onRawValue | (value: string) => void | undefined | Callback when the raw (unmasked) value changes |
onTypedValue | (value: T) => void | undefined | Callback when schema-transformed value changes |
placeholder | string | undefined | Placeholder text shown when the input is empty |
disabled | boolean | false | Disables the input when true |
label | string | undefined | Label text displayed above the input |
prefix | string | undefined | Fixed non-editable prefix (e.g., 'user_') |
suffix | string | undefined | Fixed non-editable suffix (e.g., '@company.com') |
slotStart | () => JSX.Element | undefined | Function returning content for the start of the input |
slotEnd | () => JSX.Element | undefined | Function returning content for the end of the input |
labelPosition | "above" | "below" | "before" | "after" | "above" | Label placement relative to input |
errorMessage | string | undefined | Error message displayed next to label (auto-switches status to danger) |
validate | ValidateFn<T> | undefined | Validation function for input validation and transformation |
allowInvalid | boolean | false | If true, allows invalid input and shows error; if false, prevents invalid keystrokes |
mask | PatternMask | NumberMask | TextMask | undefined | Input mask for formatting |
autocomplete | string | undefined | HTML autocomplete attribute for browser autofill |
type | "text" | "password" | "email" | "url" | "tel" | "search" | "text" | HTML input type |
status | Status | from ContainerContext or 'neutral' | Status for color theming |
styles | StyleXStyles | undefined | Additional StyleX styles to apply |