v1.0.0

<bmx-input>

A single-line text field with everything an enterprise form needs around it: a label, a description, one error message at a time, prefix and suffix content, a clear button, a character counter, input masking, and real form participation from inside a shadow root.

38 properties · 6 events · 7 methods · 11 parts

Example

Show markup
<div class="row">
  <bmx-input label="Email address" type="email" placeholder="you@example.com" description="We only use this to send your receipt." required="true" autocomplete="email"></bmx-input>
</div>
<div class="row">
  <bmx-input label="Date of birth" mask="##/##/####" placeholder="DD/MM/YYYY" description="The form receives 01011990, not 01/01/1990."></bmx-input>
</div>
<div class="row">
  <bmx-input label="Search" type="search" placeholder="Find an order" clearable="true" hide-label="true" appearance="filled">
    <svg slot="prefix" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true">
      <circle cx="7" cy="7" r="4.5" fill="none" stroke="currentColor" stroke-width="1.6" />
      <path d="M10.5 10.5L14 14" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" />
    </svg>
  </bmx-input>
</div>
<div class="row">
  <bmx-input label="Password" type="password" password-toggle="true" description="At least 12 characters." min-length="12"></bmx-input>
</div>
<div class="row">
  <bmx-input label="Display name" counter="true" max-length="24" description="Shown on your public profile."></bmx-input>
</div>

It is the first of the form family, so the conventions it sets are the ones bmx-textarea, bmx-select and the rest inherit: value is what the user sees, rawValue is what the value means, validity and visibility are two separate questions, and every decision that has an edge case lives in src/core where it can be tested without a browser.

MASKING

mask takes a pattern - # a digit, A a letter, * either, everything else a literal - or, for anything whose separators move as the value grows, maskFormat and maskParse take a pair of functions. Currency is the obvious case a pattern cannot express: 1,234 becomes 12,345 when a digit is typed at the end, and the comma moves.

The caret arithmetic is the hard part and it lives in core/mask.ts. What this component owns is the two things that need a DOM: not reformatting during an IME composition, and not destroying the browser's undo stack.

WHAT THE FORM RECEIVES

submitValue decides, and it defaults to raw: a masked telephone field submits digits and £1,234.50 submits 1234.5, because that is nearly always what the far end wants. Set it to display to submit the formatted text instead. An unmasked field is unaffected - the two are the same string.

WHY THE CHARACTER LIMIT IS NOT maxlength

The native attribute counts UTF-16 code units, so a limit of 100 cuts a user off after 50 emoji while a counter that counts characters still reads 50. Rather than ship two numbers that disagree, the limit is enforced here against the same count the counter displays. maxLength therefore behaves like a character limit in the sense a person means it.

ACCESSIBILITY

  • A real <input> inside the shadow root, labelled by a real <label>. The platform supplies the role, the keyboard behaviour and the announcement.
  • The description and the error are wired through aria-describedby, in reading order, with absent parts dropped rather than left as empty ids.
  • The error lives in a live region that is present from first render. A region created at the moment it gains text is frequently missed.
  • aria-invalid tracks the shown error, not the underlying validity, so a field the user has not reached yet is not announced as invalid.
  • The clear button is deliberately not a tab stop: clearing is reachable from the keyboard with select-all and Delete, so SC 2.1.1 is met without adding a second tab stop to every filled field in a long form. The password toggle is a tab stop, because there is no other way to reach it.

Properties

PropertyAttributeTypeDefaultDescription
appearance appearance BmxInputAppearance 'outline' Visual treatment.
autoFocus auto-focus boolean false Focus the field once it has rendered.
autocomplete autocomplete string Autocomplete hint. Worth setting: it is what makes a form fillable.
clearable clearable boolean false Show a clear button once the field has content.
counter counter boolean false Show a character counter. Pairs with maxLength.
description description string Help text below the field. Always visible, unlike a placeholder.
disabled disabled boolean false Disable the field.
enterkeyhint enterkeyhint 'enter' | 'done' | 'go' | 'next' | 'previous' | 'search' | 'send' What the on-screen keyboard's action key should say.
errorText error-text string An error supplied by the consumer - a server response, typically.
fullWidth full-width boolean false Stretch to the width of the container.
hideLabel hide-label boolean false Hide the label visually while keeping it for assistive technology. For a field whose purpose is obvious from context - a search box beside a search button. Not a licence to drop labels: the accessible name still has to exist, which is why this hides rather than removes.
inputmode inputmode 'none' | 'text' | 'decimal' | 'numeric' | 'tel' | 'search' | 'email' | 'url' On-screen keyboard hint.
label label string The field's label. Required unless the label slot is used.
mask mask string A mask pattern. # accepts a digit, A a letter, * either; every other character is a literal the mask supplies. Prefix a token with a backslash to use it as a literal. ##/##/####, +44 #### ######, \#### for a hash and three digits.
maskEager mask-eager boolean true Show the mask's separators as the user reaches them. On by default, so typing the second digit of a date shows 12/. Turn it off for a field whose partially-filled value is stored rather than only displayed.
maskFormat property only (raw: string) => string Render the raw value for display, in place of a pattern. For anything whose separators move as the value grows - currency, a locale-aware number. It may insert and remove characters freely but must not transform them: 1234 may become £1,234.00, and must not become ONE THOUSAND. A transforming formatter still produces the right text, but the caret can then only be placed at the end of it.
maskParse property only (display: string) => string The inverse of maskFormat.
max max string | number Maximum, for the numeric and date types.
maxLength max-length number Maximum length, in characters rather than UTF-16 code units. Enforced here rather than by the native attribute - see the note on the class. Also drives the counter's limit when counter is set.
messages property only BmxFieldMessages Replacements for the default wording, by reason. Accepts the JSON spelling of the object as well, for templates that can only write attributes. See src/core/markup.ts.
min min string | number Minimum, for the numeric and date types.
minLength min-length number Minimum length. Counted against rawValue when the field is masked.
name name string The field's name in the form it belongs to.
passwordToggle password-toggle boolean false Show a button that reveals the password. Only for type="password".
pattern pattern string A regular expression the value must match, as the native attribute takes it.
placeholder placeholder string Placeholder text. Never a substitute for a label.
readonly readonly boolean false Make the field read-only. It still submits and is still focusable.
required required boolean false Require a value.
shape shape BmxShape 'rounded' Corner treatment. circle is not meaningful here and behaves as pill.
size size BmxSize 'md' Size step.
spellcheck spellcheck boolean false Spellchecking. Off by default for the identifiers most fields hold.
step step string | number Granularity, for the numeric and date types.
submitValue submit-value BmxInputSubmitValue 'raw' Which value the form receives. See the note on the class.
tone tone BmxTone 'primary' Semantic colour role, used for the focus ring. An error overrides it.
type type BmxInputType 'text' The input type.
validateOn validate-on BmxValidateOn 'blur' When the field is willing to reveal a problem.
validator property only BmxInputValidator A consumer's own check, run once the value is structurally whole.
value value string '' What the field displays, mask and all. Assigning to it runs the mask, so setting 01011990 on a date-masked field leaves 01/01/1990 behind. Read rawValue for the significant characters.

Events

EventDetailDescription
bmxBlur void Fired when the field loses focus.
bmxChange BmxInputChangeDetail Fired when the field is committed - on blur, or on Enter.
bmxClear void Fired when the clear button is used, or clear() is called.
bmxFocus void Fired when the field gains focus.
bmxInput BmxInputChangeDetail Fired on every edit.
bmxValidityChange BmxInputValidityDetail Fired whenever the resolved validity changes.

Methods

MethodSignatureDescription
checkValidity checkValidity() => Promise<boolean> Validate now and return whether the field passed. Silent: it does not reveal a message the user has not earned yet. Use reportValidity to both check and show.
clear clear() => Promise<void> Empty the field.
getRawValue getRawValue() => Promise<string> The significant characters, with the mask's literals removed.
removeFocus removeFocus() => Promise<void> Remove focus from the field.
reportValidity reportValidity() => Promise<boolean> Validate, reveal any problem, and focus the field if it has one.
selectAll selectAll() => Promise<void> Select the field's contents.
setFocus setFocus(options?: FocusOptions) => Promise<void> Focus the field.

Slots

SlotDescription
description Rich help text, in place of the description property.
label Rich label content, in place of the label property.
prefix Content inside the field, before the input. An icon or a unit.
suffix Content inside the field, after the input.

CSS shadow parts

PartDescription
clear The clear button.
control The native input.
counter The character counter.
description The help text.
error The error message.
field The bordered box holding the prefix, input and suffix.
label The label element.
prefix The leading slot wrapper.
spinner
suffix The trailing slot wrapper.
toggle The password visibility toggle.

CSS custom properties

PropertyDescription
--bmx-input-background The field's background. Set by appearance; override for a one-off.
--bmx-input-border-color The field's border colour in its resting state.
--bmx-input-border-width Border width of the field.
--bmx-input-font-size The value's font size.
--bmx-input-gap Space between the prefix, the input and the suffix.
--bmx-input-height The control's height. Defaults to the size step's height times the density scale.
--bmx-input-icon-size Size of a slotted prefix or suffix icon, and of the clear and reveal buttons.
--bmx-input-label-font-size The label's font size.
--bmx-input-padding-inline Horizontal padding inside the field.
--bmx-input-placeholder-color Placeholder colour. Deliberately dimmer than the value, and still AA against the field.
--bmx-input-radius Corner radius of the field.
--bmx-input-stack-gap Space between the label, the field and the supporting text.
--bmx-input-support-font-size Font size of the description, error and counter.