Skip to content

Input ​

An enhanced base input built on the native <input> element.

Basic Usage ​

Basic usage

Accessible Name (label) ​

label (accessible name)

label serves as the accessible name (aria-label) source for the input, announced by screen readers. When label is not set, it falls back to placeholder → built-in text "Input"; once set (e.g. "Login email"), it overrides the fallback chain.

Native Form & Label Association ​

form-associated: label for / FormData / reset

Read FormDataform.reset()

The component is a form-associated custom element (formAssociated: true): <label for> works natively (clicking the label focuses the real input inside the shadow root, and screen readers announce the label text); inside a native <form> the value is collected via standard FormData (submitted only when name is set), form.reset() restores the initial value, and a parent fieldset[disabled] disables it. Works in parallel with oas-form's collectFields mechanism.

Reading/writing the current value is done via the public value property (matching native input.value): el.value reads the parser/mask-aware submitted-value semantics (same as oas-input/oas-change/FormData); el.value = x writes the controlled value attribute and immediately syncs the inner control, dispatching no events. Controlled assignment is immediate: even a same-value assignment force-writes the inner control; frameworks like Vue re-write an element's :value binding unconditionally on every patch, so under a controlled binding sync external state via events (oas-input/oas-change) to avoid an unrelated re-render wiping uncommitted input.

Types ​

type

type is passed through to the native input type, supporting text / password / number / email, etc.

Password Visibility Toggle ​

show-password

With show-password and type="password", an eye button is rendered on the right side of the input; clicking toggles between plaintext and masked text. The button has an aria-label (locale text), aria-pressed, and a focus ring when focused.

Clearable ​

clearable

When there is content and clearable is set, a clear button is shown; clicking clears the value, refocuses, and dispatches oas-clear.

Loading ​

loading (input stays editable)

Toggle loading

With loading set, a spinner shows at the end of the field and aria-busy="true" is mirrored: the input is not disabled (users can keep typing — useful for remote validation / suggestion requests). Together with clearable, the spinner takes precedence and the clear button yields; exiting loading restores it.

Disabled & Readonly ​

disabled / readonly

Addons ​

addon-before / addon-after

addon-before / addon-after render external addon text blocks (e.g. units, domains) outside the input, going through dedicated ::part(prepend) / ::part(append) parts; addons are greyed out when disabled.

Icons ​

prefix-icon / suffix-icon

prefix-icon / suffix-icon accept icon names (from @oas-ui/icons built-in icon set) and inline-render decorative SVG icons.

Inline Affixes & Clear Together ​

prefix / suffix + clearable

prefix-text / suffix-text are inline text inside the input and can coexist with clearable, icons, and addons without conflicts. prefix / suffix are compatibility aliases (writable through both the attribute and property channels, including React / Vue bindings) — the canonical names are prefix-text / suffix-text.

Custom Clear Icon (clear-icon slot) ​

clear-icon slot

The clear button of clearable renders a built-in close icon by default; distribute a custom icon via slot="clear-icon" to personalize it (the slot natively replaces the built-in fallback when it has content; the icon size is defined by the distributed content).

Character Count ​

show-count + maxlength

show-count displays a character counter at the bottom-right of the input: with maxlength it shows current/maxlength, without it just the current length; maxlength is also passed through to the native input to limit input length. When the limit is exceeded, the counter number turns danger-colored.

Hint Text (hint) ​

hint static hint (independent of validation errors)

Toggle validation error

hint renders a persistent static hint below the input (font size --oas-font-size-sm, secondary color) and is associated with the inner input via aria-describedby (screen readers announce it). It is independent of validation errors (status / aria-invalid): the hint stays visible when an error appears. Click the button to toggle status="error" and see the error border coexist with the hint text.

Enter Submit Event ​

oas-enter

Pressing Enter while typing (not an IME composition commit) dispatches oas-enter with detail: { value }.

Events ​

Input and clear events

Listen to oas-input (while typing) and oas-clear (on clear):

Complex Affixes (slot distribution) ​

slot=prefix / slot=suffix

📱

Use the prefix-text / suffix-text attributes for simple text; for complex content (icons/buttons/badges etc.) distribute via the same-named slot="prefix" / slot="suffix" slots — distributed content natively replaces the attribute text. prefix / suffix are compatibility aliases (canonical: prefix-text / suffix-text), usable through both the attribute and property channels (React / Vue bindings included).

Sizes ​

size

size supports small / medium (default) / large, with heights aligned to the global size tokens (--oas-control-height-sm/md/lg, 24/32/40px). Font size, inline affixes, addons, and the clear/eye buttons scale together. When not set, it inherits the size injected by the nearest oas-config-provider (global form density).

Variants ​

variant

variant supports outlined (default) / filled (filled background, border appears on focus) / borderless (no border or background, for plain-text embedding scenarios).

Validation Status ​

status

status supports error / warning / success: the border and focus ring switch to the semantic color. error also syncs aria-invalid="true" onto the inner input (announced as invalid by screen readers); warning / success are visual-only without invalid semantics. The existing channel where form validation (oas-form) writes host-level aria-invalid still works and composes with status (error takes priority).

Native Attribute Passthrough ​

Native attribute passthrough

The following native attributes are mirrored onto the inner native input (and removed in sync when the host attribute is removed): name / autocomplete / autofocus / inputmode / minlength / min / max / step / required / spellcheck / enterkeyhint / pattern. Useful for native form semantics, autofill, and mobile keyboard hints (inputmode / enterkeyhint); min / max / step are for type="number" (natively ignored by other types). autofocus is forwarded by the component as a one-time focus after mount (native autofocus does not pierce the shadow DOM).

Focus & Commit Events ​

oas-focus / oas-blur / oas-change + select()

Select all
  • oas-focus / oas-blur: dispatched when the inner input gains/loses focus, detail: { value } carries the current value.
  • oas-change: commit semantics — dispatched on blur or Enter only when the value changed since the last commit (not on every keystroke, unlike oas-input).
  • select() method: selects all content (delegates to the native input.select); blur() delegates likewise.

Complex Addons (slot distribution) ​

slot=prepend / slot=append (text / icons / buttons)

http://.comSearch

The addon-before / addon-after attributes accept text only; for complex content distribute via slot="prepend" / slot="append". Plain text and icons render on the gray addon surface (radius merging / border dedup work the same as with the addon attributes, and distributed content natively replaces the attribute fallback across the two coexisting channels). When a self-contained control (oas-button / oas-button-group / oas-compact) is distributed, the addon degrades into a flush container: it drops the text addon's gray fill, border and horizontal padding, aligns its height with the input, overlaps the shared edge by -1px into a single line, and forwards the radius merging protocol (--oas-button-group-radius) to the control so its outer corner joins the input frame into one continuous radius. Bordered compound controls such as selectors are still not recommended in addon slots: the host cannot safely strip their internal styles across the Shadow boundary (their dropdown shares color tokens with the trigger — making them transparent would also transparentize the dropdown). To compose a selector with an input, use the oas-compact container:

select + input composition (oas-compact)

Go

Block Addons (block-start / block-end) ​

slot=block-start / slot=block-end (full-width block above/below the field)

📦 Ship to: Haidian, BeijingClear address

slot="block-start" / slot="block-end" render a full-width block row above / below the field — a different dimension from prepend / append (which join horizontally at either side). Block rows occupy their own line and never participate in border joining; they can host hint text, action buttons, links, or any other content. The row container uses --oas-font-size-sm in secondary text color (grayed out when disabled), and is deep-customizable via ::part(block-start) / ::part(block-end). When combined with show-count (the outside counter also lives below the field), the counter automatically moves into the block-end row, aligned to the end edge — no overlap.

Count Position & Grapheme Counting ​

count-position + emoji grapheme counting

show-count counts by grapheme clusters (built-in Intl.Segmenter, falling back to code points when unavailable) — emoji and ZWJ sequences (like the family emoji) count as 1, avoiding the JS length behavior that counts one emoji as multiple. count-position="inside" moves the counter to the right inside the input (default outside, bottom-right). Note: native maxlength truncation still uses the UTF-16 code-unit metric — counting and truncation are separate concerns (see allow-over-max below for over-limit scenarios).

Allow Over Max ​

allow-over-max + oas-validate

By default maxlength is passed through to the native hard truncation; with allow-over-max, input beyond the limit is no longer truncated — the counter turns danger-red and oas-validate is dispatched whenever the over-limit state flips (detail.error is exceed-maximum, or null when back within the limit), so hosts can warn without interrupting typing.

Display Formatting (formatter / parser) ​

formatter / parser (thousand separator, property channel)

formatter / parser are JS property-channel only (el.formatter = fn) — Web Components attributes cannot carry functions, so there is no corresponding HTML attribute. Display = formatter(rawValue); detail.value of oas-input / oas-change carries the parsed raw value (parser(display)). Removing them (set to null) restores the raw display. While typing, the cursor is approximately preserved by shifting with the length delta of the format change (sufficient for card-number grouping and similar cases).

Input Mask (mask) ​

mask input mask (###-####) and mask-raw raw value

mask defines an input mask template: # digit, A letter, * alphanumeric; any other character is a literal (like the - in ###-####). Typing skips literals automatically, invalid characters are filtered, pasting accepts only the fitting positions, and backspace stops at literals (literals are managed by the template and can never be deleted through); the caret always stays at the correct position. By default events and the form submit value carry the display value (including literals); with mask-raw set they carry the de-formatted raw character sequence instead (FormData submits the same). mask is mutually exclusive with formatter/parser — when both are set, mask wins with a warning; maxlength is not passed through in mask mode (native truncation would break the mask). (The show-count counter follows the submission channel: the display value with literals by default, the raw sequence with mask-raw.)

Clear Button Visibility ​

show-clear-on

show-clear-on controls the clear-button visibility strategy: default always (shown whenever there is a value, unchanged behavior); focus shows only while focused; hover shows while hovering or focused (reduces visual noise in dense forms).

Auto Width ​

auto-width

With auto-width, the input width follows its content (mirror measurement: a hidden element sharing the input's font and paddings; empty value falls back to the placeholder width). auto-width-min / auto-width-max (px numbers) clamp the range — min defaults to 72px and max to 100%. Common in inline editing and tag-input scenarios.

Range Input (Composition) ​

Two inputs + separator (range input)

~

A range input is just two oas-input elements plus a separator layout (the component does not provide a pair API): each input commits its own oas-change, and the host combines them into a range. Wrap in an oas-compact container when you need tight radius-merged composition.

API ​

oas-input ​

Attributes ​

AttributeDescriptionTypeDefault
addon-afterAddon text block after the input——
addon-beforeAddon text block before the input——
allow-over-maxOver-limit without truncation: maxlength is no longer passed native (typing continues), count turns red and oas-validate firesboolean—
auto-widthAuto width following content (mirror measurement; empty value falls back to placeholder width), usually with auto-width-min/maxboolean—
auto-width-maxMaximum width for auto-width, px or percentage (default 100%)——
auto-width-minMinimum width in px for auto-width (default 72)——
autocompletePasses the autocomplete hint through to the inner native input (password managers / autofill)——
autofocusAuto-focus the inner input after mount (native autofocus does not cross shadow DOM, so the component forwards it)boolean—
clearableClearableboolean—
count-positionCharacter count position: outside (default) / inside (right side within the field)string—
disabledDisabledboolean—
enterkeyhintPasses the mobile virtual keyboard enter-key appearance through (e.g. search/send/go)——
hintPersistent static hint below the input (aria-describedby, independent of validation errors)string—
inputmodePasses the mobile virtual keyboard type through to the inner input——
labelAccessible name (aria-label source; falls back to placeholder → built-in "Input" when unset)——
loadingLoading state: trailing spinner with aria-busy (input stays editable); takes precedence over the clear buttonboolean—
maskInput mask template: # digit, A letter, * alphanumeric; other characters are literals (e.g. ###-####); typing skips literals, pasting accepts only fitting positions, backspace stops at literals; mutually exclusive with formatter/parser (mask wins)string—
mask-rawEvents and form submit value carry the de-formatted raw character sequence; by default the display value is submittedboolean—
maxNative max mirrored to the inner input——
maxlengthMaximum input length (passed through to native maxlength)string—
minNative min mirrored to the inner input (number type)——
minlengthPasses the native minimum length constraint through——
nameNative form field name (form-associated: the FormData submission key)——
patternPasses the native regex validation pattern through——
placeholderPlaceholder textstring—
prefix-iconIcon name for the leading iconstring—
prefix-textInline text before the input value; prefix is a compatibility alias (usable via attribute and property channels)string—
readonlyReadonlyboolean—
requiredRequired marker (native passthrough to the inner input; drives the valueMissing validation chain)boolean—
show-clear-onClear button visibility: always (default) / hover / focusstring—
show-countShow character count (bottom-right; danger when over limit)boolean—
show-passwordPassword visibility toggle (renders an eye button when type="password")boolean—
sizeSize preset small / medium (default) / large: height and font scalestringmedium
spellcheckPasses the native spellcheck toggle through——
statusValidation status: error / warning / success; error mirrors aria-invalid on the inner inputstring—
stepNative step mirrored to the inner input——
suffix-iconIcon name for the trailing iconstring—
suffix-textInline text after the input value; suffix is a compatibility alias (usable via attribute and property channels)string—
typeNative input typestringtext
valueValue (controlled)string—
variantVariant: outlined (default) / filled / borderlessstring—

Property (JS property; see each row for attribute reflection) ​

PropertyDescriptionTypeDefault
valueCurrent value: parser/mask-aware submitted-value semantics (el.value reads; el.value = x writes the controlled value and syncs the inner control, no event)string—

Events ​

EventDescription
oas-blurFires on blur, detail: { value }
oas-changeCommit semantics: fires on blur/Enter when the value differs from the last commit, detail: { value }
oas-clearCleared by click, detail: { originalEvent }
oas-enterEnter pressed (not IME composition), detail: { value }
oas-focusFires on focus, detail: { value }
oas-inputWhile typing, detail: { value }
oas-validateFires when the over-limit state flips (allow-over-max), detail: { error: "exceed-maximum" | null }

Slots ​

NameDescription
appendAppend addon area (may contain select/button or any content)
block-endFull-width block addon below the field (action/counter row, any content; the outside character counter moves into this row when both are present)
block-startFull-width block addon above the field (hint/note row, any content)
clear-iconCustom clear-button icon (replaces the built-in when present)
prefixInline leading content (icons/buttons etc.; distributed content takes precedence over the prefix attribute text). For simple text use the prefix attribute
prependPrepend addon area (may contain select/button or any content)
suffixInline trailing content (icons/buttons etc.; distributed content takes precedence over the suffix attribute text). For simple text use the suffix attribute

CSS Variables ​

CSS VariableDefault
--oas-button-group-radiusvar(--oas-radius-md)
--oas-input-auto-max100%
--oas-input-auto-min72px
--oas-input-measured100%

Released under the MIT OR Apache-2.0 License.