<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-invalidtracks 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
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
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
| Event | Detail | Description |
|---|---|---|
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
| Method | Signature | Description |
|---|---|---|
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
| Slot | Description |
|---|---|
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
| Part | Description |
|---|---|
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
| Property | Description |
|---|---|
--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. |