AppInput
The single-line text field — name, email, amount — with label, hint, error, and optional icon, unit, and password reveal.
<app-input label="Email" name="email" type="email" /><app-input> is the shared single-line field, and the one you'll reach for most. It handles any short text or numeric value — a name, an email, an amount, a reference — with a consistent label, hint, and error treatment, so every field in a form reads the same.
Its look comes entirely from the shared @webority/theme, so the Razor <app-input> and the React <AppInput> render identically — a field is a field on every Webority surface.
Playground
Every meaningful attribute, live. Each change re-renders the real tag helper on the server, so the markup underneath is the exact call that produced the field above it.
Trailing action
A control beside the field, outside its border — a labelled button (verify, apply, send code), or a confirmation once the value resolves. The field flexes to fill the row; the action keeps its natural width. Compose it with an <app-input-action> child; it pairs with a leading icon and is exclusive with the in-field shells.
Show code
<app-input label="PAN" name="pan" placeholder="Enter PAN"> <app-input-action><app-button variant="secondary">Verify</app-button></app-input-action> </app-input> <app-input label="PAN" name="pan" value="ABCDE1234F"> <app-input-action><app-button variant="success" static="true" left-icon="check-circle">Verified</app-button></app-input-action> </app-input>
Types
The type sets the on-screen keyboard and native validation — email, number, tel, and more. The field looks the same; the input behaviour follows the type.
Show code
<app-input label="Email" name="email" type="email" placeholder="you@company.com" /> <app-input label="Area" name="area" type="number" placeholder="0" /> <app-input label="Phone" name="phone" type="tel" placeholder="+91 98765 43210" />
Without a label
The label is optional — omit it for a compact, placeholder-only field like a toolbar search or a filter. Give it an aria-label so it still has an accessible name.
Show code
<app-input name="q" aria-label="Search" left-icon="search" placeholder="Search projects…" />
aria-label so screen readers still announce the field's purpose.Floating label
An animated variant: the label starts inside as the placeholder, then slides up and shrinks on focus or once the field is filled. Set floating-label — it's standalone (no icon/unit/affix in the same field).
Show code
<app-input label="Email address" name="email" type="email" floating-label="true" />
Sizes
Three sizes. Default (md) suits almost everything; use sm inside dense toolbars and filter bars, lg for a marketing-scale field.
Show code
<app-input label="Small" name="s" size="sm" placeholder="sm" /> <app-input label="Medium" name="m" placeholder="md (default)" /> <app-input label="Large" name="l" size="lg" placeholder="lg" />
Leading icon
A leading icon drops a glyph inside the start of the field — a mail icon on an email, a person on a name — to make the field's purpose scannable at a glance.
Show code
<app-input label="Email" name="email" type="email" left-icon="mail" placeholder="you@company.com" />
Unit suffix
A unit suffix prints a fixed label inside the field — a measurement, a currency, a percentage — without it becoming part of the typed value.
Show code
<app-input label="Area" name="area" type="number" unit="m²" placeholder="0" />
Prefix & suffix
A bordered box attached before or after the input — a currency mark, a URL scheme, a domain suffix. Use it when the affix is a fixed, non-editable part of the value's shape.
Show code
<app-input label="Amount" name="amt" type="number" prefix="₹" suffix=".00" /> <app-input label="Site" name="site" prefix="https://" suffix=".com" />
Clearable
Set clearable and an ✕ appears once the field has a value — one click empties it and refocuses. Useful on any editable field: a coupon, a tag, a filter value. (For an actual search box, reach for AppSearch.) The ✕ fades in as you type.
Show code
<app-input label="Coupon code" name="coupon" clearable="true" placeholder="Enter a code" />
Character count
Set show-count for a live count under the field; add max-length to cap the input and show the denominator. The count turns red at the limit.
Show code
<app-input label="Headline" name="headline" show-count="true" max-length="60" placeholder="Up to 60 characters" />
Password
A password field can show a reveal toggle — an eye button the user taps to check what they typed before submitting.
Show code
<app-input label="Password" name="password" type="password" placeholder="••••••••" />
Show code
<app-input label="Password" name="password" type="password" left-icon="lock" placeholder="••••••••" />
password-requirements to show a checklist on focus that ticks each rule green as the user types — client-side, before any server round-trip. requirements-placement (auto | top | bottom | start | end) chooses the side. Focus the field to try it.Show code
<app-input label="New password" name="new-password" type="password" password-requirements requirements-placement="auto" placeholder="••••••••" />
Show code
<app-input label="New password" name="pw-policy" type="password" password-requirements password-min-length="10" password-unique-chars="4" requirements-title="Choose a strong password" requirements-placement="end" placeholder="••••••••" />
@webority/ui-elements so both surfaces validate identically.Validation
Show a hint for guidance and an error when validation fails. They share one slot below the field — the error replaces the hint and turns the field red. Mark required fields on the label.
Show code
<app-input label="GSTIN" name="gstin" hint="15-character GST identification number." /> <app-input label="Email" name="email" required error="Enter a valid email address." />
hint and error occupy the same line, so a set error hides the hint. Write the error as an instruction — "Enter a valid email address" — not just "Invalid".Disabled
Set disabled when a field can't be edited yet — it depends on an earlier choice, or the value is fixed. The control greys out, stops taking focus, and is skipped on submit.
Show code
<app-input label="Workspace" name="workspace" value="Acme Inc." disabled="true" /> <app-input label="Plan" name="plan" value="Enterprise" left-icon="briefcase" disabled="true" />
disabled greys the field and drops it from the form submission. If the value should still submit but not be editable, use a read-only control instead.Custom class
Hook your own styling onto a field: input-class lands on the input element, a plain class on the .field wrapper. Both append after the design-system classes, so yours win on equal specificity.
Show code
<app-input label="Email" name="email" input-class="js-track" class="grid-col-span-2" />
When to use
Use it when
- The user enters a single line of text or a number — name, email, amount, reference.
- You want the shared field treatment: label, hint, error, and required marking.
- A specific type (email, number, tel) should drive the keyboard and native validation.
Reach for something else when
- The value runs to multiple lines — a note or description. → AppTextarea
- The user picks from a fixed set of options. → AppSelect
- It is a search box that filters a list. → AppSearch
- The value is a calendar date. → AppDatePicker
Best practices
Every option
The whole surface of the component, one cell per value — every input type, every shell, and the combinations that behave specially.
type — all seven
type="text"
type="email"
type="number"
type="tel"
type="url"
type="search"
type="password"
size — every size
size="sm"
size="md"
size="lg"
state
(default)requireddisablederror="…"hint="…"required + erroricon slots
left-icon="mail"right-icon (no click handler in Razor — always disabled)right-icon-label="Run search"left-icon + clearableright-icon has no server-side click handler — the trailing-icon button is always rendered disabled, unlike React where passing onRightIconClick enables it.unit & affixes
unit="m²"prefix="₹"suffix=".com"prefix + suffixfloating-label
floating-label (empty)floating-label + valuefloating-label + requiredvariant
variant="bare"clearable
clearable, empty (✕ hidden)clearable + value (✕ visible)clearable + disabled (✕ never shown)show-count
show-count, no max-lengthshow-count + max-length (under limit)show-count + max-length (at limit, red)password
type="password"type="password" + left-iconpassword-requirements (focus me)edge cases
long content overflows the fixed-width fieldno label, aria-label onlyAttributes
| Attribute | Type | Default | Description |
|---|---|---|---|
| asp-for | ModelExpression | — | Razor-only; no React equivalent. Binds to a Razor Pages model property — derives name, id, value, [Display] label and [Required], and emits unobtrusive validation attributes plus the validation message in place of a manual error. |
| label | string | — | The field label. Always set one — never rely on the placeholder. |
| name | string | — | Field name; also used as the id. |
| type | string | text | Native input type — text, email, number, tel, password, etc. |
| prefix | string | — | A bordered box before the input (e.g. https://). |
| suffix | string | — | A bordered box after the input (e.g. .00). |
| floating-label | bool | — | Label sits inside as a placeholder, then slides up once the field has focus or a value. |
| clearable | bool | — | Show an ✕ button while the field has a value. |
| show-count | bool | — | Show a live count / max-length under the field. |
| max-length | int | — | Character cap; the count turns red as it is approached. |
| size | sm | lg | md | Control size. Omit for the default (md). |
| placeholder | string | — | Placeholder text shown while the field is empty. |
| value | string | — | Pre-filled value of the field. |
| required | bool | false | Appends a required mark to the label. |
| hint | string | — | Helper text below the field. Hidden while an error is shown. |
| error | string | — | Error message. Turns the field red and replaces the hint. |
| left-icon | string | — | Bootstrap Icons glyph shown inside the start of the field. |
| unit | string | — | Fixed suffix printed inside the field (e.g. m², %). |
| right-icon | string | — | Bootstrap Icons glyph for a trailing icon (React rightIcon). |
| right-icon-label | string | — | Accessible name for the right-icon button. Defaults to the icon name, which is a poor label but not an absent one. |
| disabled | bool | — | Disable the control. |
| help | string | — | Info-tip content shown beside the label (React help). |
| help-label | string | More information | aria-label for the info-tip button (React helpLabel). |
| id | string | — | Explicit control id. Defaults to name (React id). |
| input-class | string | — | Extra classes on the input element (React className). |
| class | string | — | Extra classes on the .field wrapper (React fieldClassName). |
| variant | bare | — | Borderless variant — no border/background, inherits the container's chrome (inline-rename, ⌘K). Matches React variant. |
| password-requirements | bool | false | Only honoured on type="password". Shows a live requirements checklist popover on focus that ticks each rule green as the user types — client-side, before server validation. The rule set is shared with React via @webority/ui-elements. Maps to React passwordRequirements. |
| password-min-length | int | 8 | Minimum-length rule. Set 0 to drop the length rule. |
| password-uppercase | bool | true | Require at least one uppercase letter. |
| password-lowercase | bool | true | Require at least one lowercase letter. |
| password-digit | bool | true | Require at least one digit. |
| password-special | bool | true | Require at least one special (non-alphanumeric) character. |
| password-unique-chars | int | 0 | Require at least N distinct characters. 0 omits the rule. |
| requirements-title | string | Password Requirements | Heading shown at the top of the requirements popover. Maps to React passwordRequirements.title. |
| requirements-placement | auto | top | bottom | start | end | auto | Which side the requirements popover opens; auto flips to stay in view. Matches React requirementsPlacement. |