HyTextInput
Usage examples on this page are written for Lit / plain HTML (
<hy-text-input>). The same component ships asHyTextInputin@whitespaceux/harmony-react(native React 19), with typed wrappers for Angular, Solid, Svelte, and Vue. The API reference below applies to all frameworks.
A versatile single-line text input component with enhanced styling and functionality. Supports multiple input types, validation states, icons, and comprehensive accessibility features. Provides a consistent interface for various text input scenarios with built-in error handling. Offers both block (default) and inline layout options — in inline, label sits on the left of the row, input on the right, and helper/error under the control (col 2–end).
A field or a settings row?
A field has its label above it, or beside it with layout="inline" (its helper and messages then sit under the control). A settings row — a setting's name with a line of description at the start and the control at the row's end, as on a preferences page — is a row of your own: a flex row with justify-content: space-between, the name and description as your own text, and the control named with aria-labelledby pointing at the name, with no label, helper-text or layout. Rebuilding a drawn settings page, keep the control at the row's end.
When to use
- A single line of free text: a name, an email address, a title, a search.
- A value with a known format people type, with the matching
type: email, URL, phone.
Do
- Size a field to its expected length with
charswhen the content has one: a postal code, a year. - Say the expected format in
helper-text, before people type.
When not to use
- Text that runs over several lines:
hy-text-area. - One of a few known options:
hy-select. A long list:hy-combobox, so people can type to filter. - A quantity with bounds or steps:
hy-number-input, nottype="number". - A yes or no answer:
hy-checkboxorhy-switch.
Accessibility: your part
- Never use
placeholderas the label or for guidance. It disappears as people type. - Set
autocompleteon a field that asks for the person's own data, such as name, email or phone.
Examples
<hy-text-input label="Name" placeholder="Enter your name"></hy-text-input><hy-text-input
type="email"
label="Email Address"
placeholder="user@example.com"
helper-text="We'll never share your email with anyone"
required
>
</hy-text-input>Search with a clear button
The × shows while there is a value; Escape clears too. The search icon goes at the start, so the end of the field is the ×'s.
<hy-text-input
type="search"
aria-label="Search"
clearable
clear-label="Clear search"
></hy-text-input>Password with a show / hide button
The host keeps type="password"; only the inner input switches, so forms and password managers still see a password field. The button re-hides the password when the form is submitted or reset.
<hy-text-input
type="password"
label="Password"
autocomplete="current-password"
password-toggle
></hy-text-input>Inline layout (dense parameter panels)
Label on the left, input on the right, helper/error below the row. Set --hy-text-input-label-column-width on a wrapping container so stacked inputs align on the left edge.
<style>
.form {
--hy-text-input-label-column-width: 8rem;
}
</style>
<div class="form">
<hy-text-input layout="inline" label="Name" placeholder="Jane Doe"></hy-text-input>
<hy-text-input layout="inline" label="Email" placeholder="jane@example.com"></hy-text-input>
</div>API
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
focused | focused | boolean | false | Whether the input is currently focused. |
disabled | disabled | boolean | false | Disables the input, preventing user interaction. |
required | required | boolean | false | Marks the input as required for form validation. |
readonly | readonly | boolean | false | Makes the input read-only, preventing user editing. |
error | error | boolean | false | Whether the input is in an error state. |
warning | warning | boolean | false | Warning state: the value is accepted but worth a second look. Paints the warning color and shows warning-message; never sets aria-invalid and never blocks submission. error wins when both are set. |
leadingIcon | leading-icon | string | '' | Icon name from HyIcon component library to display before the input field, drawn in the field's icon ink. Lit resolves the name (its icon registry); React's leadingIcon takes the icon node instead. A type="search" field draws its own magnifier (the design system picks its side), so it names none here. |
trailingIcon | trailing-icon | string | '' | Icon name from HyIcon component library to display after the input field, as leading-icon. |
size | size | 'small' | 'medium' | 'large' | 'medium' | The size of the input: 'small', 'medium', or 'large'. |
layout | layout | 'block' | 'inline' | 'block' | Row layout: block (default) stacks label above the input; inline puts label on the left and input on the right. Helper/error always sit under the control (col 2–end), never under the label. |
chars | chars | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | 12 | 16 | 20 | 24 | 32 | 48 | undefined | How many characters the field holds — the way to make a field narrower than its container. One of 1–8, 10, 12, 16, 20, 24, 32, 48; the width is that many 0 glyphs in the input's own font, plus its padding and icons, so it follows every design system. Never wider than the container. A value outside the set is ignored (dev warning). width wins when both are set. |
width | width | string | undefined | undefined | A fixed width for the input container, as any CSS width value (e.g. '300px', '20rem', '50%') — for a size the layout dictates rather than the content. Never wider than the container. To size a field to its content, use chars. |
label | label | string | '' | The label text displayed above the input (block layout) or to the left (inline layout). |
value | value | string | '' | The current value of the input. |
placeholder | placeholder | string | '' | Placeholder text displayed when the input is empty. |
helperText | helper-text | string | '' | Helper text displayed below the input to provide additional context. |
type | type | 'text' | 'email' | 'password' | 'tel' | 'url' | 'search' | 'number' | 'text' | The input type: 'text', 'email', 'password', 'tel', 'url', 'search', or 'number'. |
name | name | string | '' | The name attribute for form submission. |
autocomplete | autocomplete | string | '' | The autocomplete attribute for browser auto-completion. |
autofocus | autofocus | boolean | false | Marks this input as the auto-focus target. Read by hy-dialog (and other overlay containers) on show to choose which slotted control receives initial focus. Also focuses on first connect when used outside an overlay, matching the native HTML autofocus attribute — but routed through JS so SSR'd HTML doesn't pull focus during hydration. |
autoselect | autoselect | boolean | false | After auto-focus lands, selects the current value so the user can type-to-replace. Pairs with autofocus for rename-style dialogs where the existing name is shown for context but is meant to be overwritten. |
errorMessage | error-message | string | '' | Error message displayed when the input is in an invalid state. |
warningMessage | warning-message | string | '' | Warning message shown under the input (replaces the helper text). Setting it raises warning. |
maxlength | maxlength | number | undefined | — | Maximum number of characters allowed in the input. |
minlength | minlength | number | undefined | — | Minimum number of characters required in the input. |
pattern | pattern | string | '' | Regular expression pattern for input validation. |
inputmode | inputmode | string | '' | Virtual-keyboard hint forwarded to the inner input (inputmode), e.g. numeric for one-time codes so mobile users get the number pad while the type stays text (leading zeros, no spinner). |
clearable | clearable | boolean | false | Adds a clear (×) button at the end of the field while it has a value (not when disabled or read-only). A press empties the field, keeps focus in it, and sends input then change with an empty value. The × is not in the tab order: Escape clears from the keyboard — and while the field is empty, Escape passes through, so an enclosing dialog still closes on the next one. Opt-in on every type, type="search" included; the browser's own search × is always hidden. |
clearLabel | clear-label | string | 'Clear' | The clear button's accessible name. Name what it clears ("Clear search"). |
passwordToggle | password-toggle | boolean | false | Adds a show / hide button at the end of a type="password" field. The host keeps type="password" throughout — only the inner input switches to text — so form semantics, autocomplete and password managers never see a type change. Ignored on any other type (dev warning). |
passwordVisible | password-visible | boolean | false | Whether the password is shown as plain text (type="password" only). Set it to reveal or hide from code; the show / hide button and a form submit or reset change it too. A submit or reset always hides it, so the browser never records the credential from a text field. |
showPasswordLabel | show-password-label | string | 'Show password' | The show / hide button's accessible name while the password is hidden. The name swaps with the state (GOV.UK, Web Awesome, Carbon), so the button says what a press does. Set it to localize. |
hidePasswordLabel | hide-password-label | string | 'Hide password' | The show / hide button's accessible name while the password is shown. |
form | — | HTMLFormElement | null | — | — |
validity | — | ValidityState | — | — |
validationMessage | — | string | — | — |
Events
| Event | Detail | Description |
|---|---|---|
input | — | Fired when the input value changes. Detail: |
change | — | Fired when the input loses focus after a value change. Detail: |
focus | — | Fired when the input receives focus. Detail: none |
blur | — | Fired when the input loses focus. Detail: none |
password-visibility-change | — | Fired when the show / hide button reveals or hides the password, and when a form submit or reset hides it again; not when password-visible is set. Detail: TextInputPasswordVisibilityDetail |
CSS Parts
| Part | Description |
|---|---|
base | The text input's base wrapper element |
label | The label element |
container | The input container element |
input | The native input element |
leading-icon | The leading icon container |
search-icon | The magnifier box of a search field |
trailing-icon | The trailing icon container |
clear-button | The clear (×) button |
password-toggle | The show / hide password button |
helper-text | The helper text element |
error-message | The error message element |
warning-message | The warning message element |
message-icon | The icon starting the error or warning message |
CSS Custom Properties
The documented hooks. Every override hook the component reads — one per token it paints — is listed in @whitespaceux/harmony/theme-api.json, and @whitespaceux/harmony/component-bindings.json (the Harmony MCP get-bindings tool) says which part and state each one paints.
| Property | Default | Description |
|---|---|---|
--hy-text-input-background-surface-base | var(--hy-background-surface-base) | Background color at rest |
--hy-text-input-border-subtle-rest | var(--hy-border-subtle-rest) | Border color at rest |
--hy-text-input-border-brand-rest | var(--hy-border-brand-rest) | Focused edge color, any focus method. |
--hy-text-input-border-default-hover | var(--hy-border-default-hover) | Border color on hover |
--hy-text-input-border-danger-rest | var(--hy-border-danger-rest) | Border color for error state |
--hy-text-input-border-warning-rest | var(--hy-border-warning-rest) | Border color for warning state |
--hy-text-input-border-default-disabled | var(--hy-border-default-disabled) | Border color when disabled — the same disabled edge as every other field (binding rules C7 / F1) |
--hy-text-input-foreground-warning-rest | var(--hy-foreground-warning-rest) | Warning message text and icon color |
--hy-text-input-gap-layout-2xs | var(--hy-gap-layout-2xs) | Gap between the message icon and its text |
--hy-text-input-stroke-sm | var(--hy-stroke-sm) | Border width |
--hy-text-input-radius-form-md | var(--hy-radius-form-md) | Border radius |
--hy-text-input-padding-layout-lg | var(--hy-padding-layout-lg) | Horizontal padding |
--hy-text-input-padding-form-sm | var(--hy-padding-form-sm) | Vertical padding for small size |
--hy-text-input-padding-form-md | var(--hy-padding-form-md) | Vertical padding for medium size |
--hy-text-input-padding-form-lg | var(--hy-padding-form-lg) | Vertical padding for large size |
--hy-text-input-gap-form-sm | var(--hy-gap-form-sm) | Gap between input elements |
--hy-text-input-gap-form-md | var(--hy-gap-form-md) | Gap between container sections |
--hy-text-input-clear-button-foreground-subtle-rest | var(--hy-foreground-subtle-rest) | Clear button glyph color |
--hy-text-input-clear-button-foreground-default-rest | var(--hy-foreground-default-rest) | Clear button glyph color on hover |
--hy-text-input-clear-button-radius-form-sm | var(--hy-radius-form-sm) | Clear button corner |
--hy-text-input-password-toggle-foreground-subtle-rest | var(--hy-foreground-subtle-rest) | Show / hide button glyph color |
--hy-text-input-password-toggle-foreground-default-rest | var(--hy-foreground-default-rest) | Show / hide button glyph color on hover |
--hy-text-input-password-toggle-foreground-default-disabled | var(--hy-foreground-default-disabled) | Show / hide button glyph color when the input is disabled |
--hy-text-input-foreground-icon-default-disabled | var(--hy-foreground-icon-default-disabled) | The leading / trailing icon's color when the input is disabled |
--hy-text-input-password-toggle-radius-form-sm | var(--hy-radius-form-sm) | Show / hide button corner (its focus ring follows it) |
--hy-text-input-label-column-width | — | Width of the label column in layout="inline" mode. No default — set on a wrapping container so stacked inputs align. |
--hy-text-input-search-icon-placement | start | The side a type="search" field draws its magnifier on: start (the default) or end, after the clear and reveal buttons. A design system's setting; the instance names no glyph. |
--hy-text-input-control-height-sm | var(--hy-control-height-sm) | Outer height for small size variant. Per-component override in the form-control height contract. |
--hy-text-input-control-height-md | var(--hy-control-height-md) | Outer height for medium size variant. |
--hy-text-input-control-height-lg | var(--hy-control-height-lg) | Outer height for large size variant. |
Methods
focus()
Sets focus on the input.
blur()
Removes focus from the input.
select()
Selects all text in the input.