md-text-field spec card
Identity · when to use / when NOT · decision cues · behavioural contract · do/don't · anti-patterns · full API. Paste into your agent when you're implementing with this component.
The library’s single text-entry primitive. Filled and outlined, single-line
or auto-growing, with built-in clear / password-toggle / speech affordances,
input masking via formatter / parser, debounced search, and the full
constraint-validation API — form-associated via ElementInternals.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-text-field variant="filled" label="Email" type="email" supporting-text="We'll never share it" style="min-width: 240px;"></md-text-field>
<md-text-field variant="outlined" label="Email" type="email" supporting-text="We'll never share it" style="min-width: 240px;"></md-text-field>import { MdTextField } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdTextField variant="filled" label="Email" type="email" supportingText="We'll never share it" style={{ minWidth: '240px' }}></MdTextField>
<MdTextField variant="outlined" label="Email" type="email" supportingText="We'll never share it" style={{ minWidth: '240px' }}></MdTextField>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-text-field variant="filled" label="Email" type="email" supporting-text="We'll never share it" style="min-width: 240px;"></md-text-field>
<md-text-field variant="outlined" label="Email" type="email" supporting-text="We'll never share it" style="min-width: 240px;"></md-text-field><script setup>
import '@awc-ui/core/define';
</script>
<template>
<md-text-field variant="filled" label="Email" type="email" supporting-text="We'll never share it" style="min-width: 240px;"></md-text-field>
<md-text-field variant="outlined" label="Email" type="email" supporting-text="We'll never share it" style="min-width: 240px;"></md-text-field>
</template><script>
import '@awc-ui/core/define';
</script>
<md-text-field variant="filled" label="Email" type="email" supporting-text="We'll never share it" style="min-width: 240px;"></md-text-field>
<md-text-field variant="outlined" label="Email" type="email" supporting-text="We'll never share it" style="min-width: 240px;"></md-text-field>
Already installed? See the
Installation guide for one-time package setup
(core + tokens, fonts). Each tab below shows two patterns for using
md-text-field in your project: Option A registers every AWC UI
component at once (simplest), Option B imports only this component for
tree-shake-friendly bundles.
<!-- ─── Option A: global registration (all components) ─── -->
<script type="module">
import '@awc-ui/core/define';
</script>
<!-- ─── Option B: single import (tree-shake only md-text-field) ─── -->
<script type="module">
import '@awc-ui/core/components/md-text-field';
</script>
<md-text-field></md-text-field>// ─── Option A: typed React wrapper (registers all components) ───
// Importing from '@awc-ui/react' calls defineCustomElements() as a
// side effect, so every md-* element becomes available in the browser.
import { MdTextField } from '@awc-ui/react';
export function Example() {
return <MdTextField></MdTextField>;
}
// ─── Option B: single import (tree-shake to only md-text-field) ───
// Skip the wrapper and use the raw custom element. Smallest bundle,
// but you lose typed props/events on JSX.
import '@awc-ui/core/components/md-text-field';
export function ExampleTreeShaken() {
return <md-text-field></md-text-field>;
}// ─── Option A: schema module (any md-* element accepted) ───
// Pair with `defineCustomElements(window)` in main.ts.
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@Component({
standalone: true,
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `<md-text-field></md-text-field>`,
})
export class ExampleComponent {}
// ─── Option B: typed directive (tree-shake friendly) ───
// Pair with `import '@awc-ui/core/components/md-text-field'` in main.ts.
import { Component } from '@angular/core';
import { MdTextField } from '@awc-ui/angular';
@Component({
standalone: true,
imports: [MdTextField],
template: `<md-text-field></md-text-field>`,
})
export class ExampleTreeShakenComponent {}<!-- ─── Option A: typed Vue wrapper (registers all components) ─── -->
<script setup lang="ts">
import { MdTextField } from '@awc-ui/vue';
</script>
<template>
<MdTextField></MdTextField>
</template>
<!-- ─── Option B: single import (tree-shake to only md-text-field) ─── -->
<script setup lang="ts">
import '@awc-ui/core/components/md-text-field';
</script>
<template>
<md-text-field></md-text-field>
</template><!-- ─── Option A: global registration (done once in main entry) ─── -->
<!-- main.ts: -->
<!-- import { defineCustomElements } from '@awc-ui/svelte'; -->
<!-- defineCustomElements(window); -->
<md-text-field></md-text-field>
<!-- ─── Option B: single import (tree-shake to only md-text-field) ─── -->
<script lang="ts">
import '@awc-ui/core/components/md-text-field';
</script>
<md-text-field></md-text-field>multiline="auto-grow" or "fixed").| Situation | Use instead |
|---|---|
| Entry with a suggestion list | md-autocomplete |
| App-wide search with a results surface | md-search |
| Choosing from a fixed set | md-select / md-multi-select |
| A date or a time | md-date-picker / md-time-picker |
| A bounded numeric range the user should feel | md-slider |
| A colour | md-color-picker |
| Rich text | Not in this library — integrate a third-party editor |
| A yes / no | md-checkbox / md-switch |
| Variant | Container | Use for |
|---|---|---|
filled | Tonal fill + bottom active indicator | Default. Dense forms, surfaces that need the field to read as a distinct target |
outlined | Transparent, notched outline | Sparse layouts, forms over patterned or coloured surfaces |
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-text-field variant="filled" label="Filled" value="Jane Doe" style="min-width: 240px;"></md-text-field>
<md-text-field variant="outlined" label="Outlined" value="Jane Doe" style="min-width: 240px;"></md-text-field>import { MdTextField } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdTextField variant="filled" label="Filled" value="Jane Doe" style={{ minWidth: '240px' }}></MdTextField>
<MdTextField variant="outlined" label="Outlined" value="Jane Doe" style={{ minWidth: '240px' }}></MdTextField>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-text-field variant="filled" label="Filled" value="Jane Doe" style="min-width: 240px;"></md-text-field>
<md-text-field variant="outlined" label="Outlined" value="Jane Doe" style="min-width: 240px;"></md-text-field><script setup>
import '@awc-ui/core/define';
</script>
<template>
<md-text-field variant="filled" label="Filled" value="Jane Doe" style="min-width: 240px;"></md-text-field>
<md-text-field variant="outlined" label="Outlined" value="Jane Doe" style="min-width: 240px;"></md-text-field>
</template><script>
import '@awc-ui/core/define';
</script>
<md-text-field variant="filled" label="Filled" value="Jane Doe" style="min-width: 240px;"></md-text-field>
<md-text-field variant="outlined" label="Outlined" value="Jane Doe" style="min-width: 240px;"></md-text-field>Icons are slots, not props: leading-icon and trailing-icon take any
glyph — a Material Symbol, an SVG, an emoji.
<!-- index.html <head> — the icon font the components draw from -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=swap">
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-text-field variant="filled" label="Search" style="min-width: 240px;">
<span slot="leading-icon" class="material-symbols-outlined">search</span>
</md-text-field>
<md-text-field variant="outlined" label="Email" style="min-width: 240px;">
<span slot="leading-icon" class="material-symbols-outlined">mail</span>
<span slot="trailing-icon" class="material-symbols-outlined">cancel</span>
</md-text-field>// Icons need the Material Symbols stylesheet in index.html — see Installation.
import { MdTextField } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdTextField variant="filled" label="Search" style={{ minWidth: '240px' }}>
<span slot="leading-icon" className="material-symbols-outlined">search</span>
</MdTextField>
<MdTextField variant="outlined" label="Email" style={{ minWidth: '240px' }}>
<span slot="leading-icon" className="material-symbols-outlined">mail</span>
<span slot="trailing-icon" className="material-symbols-outlined">cancel</span>
</MdTextField>
</>
);
}// Icons need the Material Symbols stylesheet in index.html — see Installation.
// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-text-field variant="filled" label="Search" style="min-width: 240px;">
<span slot="leading-icon" class="material-symbols-outlined">search</span>
</md-text-field>
<md-text-field variant="outlined" label="Email" style="min-width: 240px;">
<span slot="leading-icon" class="material-symbols-outlined">mail</span>
<span slot="trailing-icon" class="material-symbols-outlined">cancel</span>
</md-text-field><script setup>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import '@awc-ui/core/define';
</script>
<template>
<md-text-field variant="filled" label="Search" style="min-width: 240px;">
<span slot="leading-icon" class="material-symbols-outlined">search</span>
</md-text-field>
<md-text-field variant="outlined" label="Email" style="min-width: 240px;">
<span slot="leading-icon" class="material-symbols-outlined">mail</span>
<span slot="trailing-icon" class="material-symbols-outlined">cancel</span>
</md-text-field>
</template><script>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import '@awc-ui/core/define';
</script>
<md-text-field variant="filled" label="Search" style="min-width: 240px;">
<span slot="leading-icon" class="material-symbols-outlined">search</span>
</md-text-field>
<md-text-field variant="outlined" label="Email" style="min-width: 240px;">
<span slot="leading-icon" class="material-symbols-outlined">mail</span>
<span slot="trailing-icon" class="material-symbols-outlined">cancel</span>
</md-text-field>prefix-text and suffix-text sit inside the field; max-length renders a
counter.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-text-field variant="outlined" label="Amount" prefix-text="$" inputmode="decimal" style="min-width: 200px;"></md-text-field>
<md-text-field variant="outlined" label="Weight" suffix-text="kg" type="number" style="min-width: 200px;"></md-text-field>
<md-text-field variant="filled" label="Headline" max-length="60" value="Shipping update" style="min-width: 240px;"></md-text-field>import { MdTextField } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdTextField variant="outlined" label="Amount" prefixText="$" inputmode="decimal" style={{ minWidth: '200px' }}></MdTextField>
<MdTextField variant="outlined" label="Weight" suffixText="kg" type="number" style={{ minWidth: '200px' }}></MdTextField>
<MdTextField variant="filled" label="Headline" maxLength="60" value="Shipping update" style={{ minWidth: '240px' }}></MdTextField>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-text-field variant="outlined" label="Amount" prefix-text="$" inputmode="decimal" style="min-width: 200px;"></md-text-field>
<md-text-field variant="outlined" label="Weight" suffix-text="kg" type="number" style="min-width: 200px;"></md-text-field>
<md-text-field variant="filled" label="Headline" max-length="60" value="Shipping update" style="min-width: 240px;"></md-text-field><script setup>
import '@awc-ui/core/define';
</script>
<template>
<md-text-field variant="outlined" label="Amount" prefix-text="$" inputmode="decimal" style="min-width: 200px;"></md-text-field>
<md-text-field variant="outlined" label="Weight" suffix-text="kg" type="number" style="min-width: 200px;"></md-text-field>
<md-text-field variant="filled" label="Headline" max-length="60" value="Shipping update" style="min-width: 240px;"></md-text-field>
</template><script>
import '@awc-ui/core/define';
</script>
<md-text-field variant="outlined" label="Amount" prefix-text="$" inputmode="decimal" style="min-width: 200px;"></md-text-field>
<md-text-field variant="outlined" label="Weight" suffix-text="kg" type="number" style="min-width: 200px;"></md-text-field>
<md-text-field variant="filled" label="Headline" max-length="60" value="Shipping update" style="min-width: 240px;"></md-text-field>| State | Focusable | Use when |
|---|---|---|
| Default | Yes | Normal entry |
error + error-text | Yes | The value failed validation — set both |
readonly | Yes | The value is shown for reading and copying, not editing |
disabled | No | The control is unavailable in this context |
Without reserve-supporting-space the message line only exists when there’s a
message, so content below shifts when an error appears. Turn it on in dense
forms.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-text-field variant="outlined" label="Email" supporting-text="We'll never share it" style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Email" value="not-an-email" error error-text="Enter a valid email address" style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Read only" value="Locked value" readonly style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Disabled" value="Unavailable" disabled style="min-width: 220px;"></md-text-field>import { MdTextField } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdTextField variant="outlined" label="Email" supportingText="We'll never share it" style={{ minWidth: '220px' }}></MdTextField>
<MdTextField variant="outlined" label="Email" value="not-an-email" error errorText="Enter a valid email address" style={{ minWidth: '220px' }}></MdTextField>
<MdTextField variant="outlined" label="Read only" value="Locked value" readonly style={{ minWidth: '220px' }}></MdTextField>
<MdTextField variant="outlined" label="Disabled" value="Unavailable" disabled style={{ minWidth: '220px' }}></MdTextField>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-text-field variant="outlined" label="Email" supporting-text="We'll never share it" style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Email" value="not-an-email" error error-text="Enter a valid email address" style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Read only" value="Locked value" readonly style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Disabled" value="Unavailable" disabled style="min-width: 220px;"></md-text-field><script setup>
import '@awc-ui/core/define';
</script>
<template>
<md-text-field variant="outlined" label="Email" supporting-text="We'll never share it" style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Email" value="not-an-email" error error-text="Enter a valid email address" style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Read only" value="Locked value" readonly style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Disabled" value="Unavailable" disabled style="min-width: 220px;"></md-text-field>
</template><script>
import '@awc-ui/core/define';
</script>
<md-text-field variant="outlined" label="Email" supporting-text="We'll never share it" style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Email" value="not-an-email" error error-text="Enter a valid email address" style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Read only" value="Locked value" readonly style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Disabled" value="Unavailable" disabled style="min-width: 220px;"></md-text-field>readonly stays focusable and readable; disabled does not.
| Prop | Values | Use for |
|---|---|---|
clearable | "internal" / "external" / false | A clear icon button. internal empties value itself; external only emits mdClear and leaves the value to you |
password-toggle | "internal" / "external" / false | A visibility toggle. internal flips the input type itself; external only emits mdPasswordToggle and leaves the type to you |
speech-to-text | "internal" / "external" / false | A mic button. internal drives the browser’s SpeechRecognition and appends the transcript; external only emits mdSpeechResult, so you can run your own engine |
Writing the bare attribute — clearable, password-toggle or speech-to-text
with no value — is normalised to "internal" on load, so it is a supported
shorthand rather than a silent off.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-text-field variant="outlined" label="Search" type="search" clearable="internal" value="query" style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Password" type="password" password-toggle="internal" value="hunter2" style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Notes" speech-to-text="internal" speech-lang="en-US" style="min-width: 220px;"></md-text-field>import { MdTextField } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdTextField variant="outlined" label="Search" type="search" clearable="internal" value="query" style={{ minWidth: '220px' }}></MdTextField>
<MdTextField variant="outlined" label="Password" type="password" passwordToggle="internal" value="hunter2" style={{ minWidth: '220px' }}></MdTextField>
<MdTextField variant="outlined" label="Notes" speechToText="internal" speechLang="en-US" style={{ minWidth: '220px' }}></MdTextField>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-text-field variant="outlined" label="Search" type="search" clearable="internal" value="query" style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Password" type="password" password-toggle="internal" value="hunter2" style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Notes" speech-to-text="internal" speech-lang="en-US" style="min-width: 220px;"></md-text-field><script setup>
import '@awc-ui/core/define';
</script>
<template>
<md-text-field variant="outlined" label="Search" type="search" clearable="internal" value="query" style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Password" type="password" password-toggle="internal" value="hunter2" style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Notes" speech-to-text="internal" speech-lang="en-US" style="min-width: 220px;"></md-text-field>
</template><script>
import '@awc-ui/core/define';
</script>
<md-text-field variant="outlined" label="Search" type="search" clearable="internal" value="query" style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Password" type="password" password-toggle="internal" value="hunter2" style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Notes" speech-to-text="internal" speech-lang="en-US" style="min-width: 220px;"></md-text-field>Speech-to-text depends on the browser’s SpeechRecognition API — feature-detect before advertising it.
Every built-in glyph is a slot, and slotting your own replaces the default:
<!-- index.html <head> — the icon font the components draw from -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=swap">
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-text-field variant="outlined" label="Custom clear glyph" clearable="internal" value="query" style="min-width: 220px;">
<span slot="clear-icon" class="material-symbols-outlined">backspace</span>
</md-text-field>
<md-text-field variant="outlined" label="Custom toggle glyph" type="password" password-toggle="internal" value="hunter2" style="min-width: 220px;">
<span slot="password-toggle-icon" class="material-symbols-outlined">key</span>
</md-text-field>
<md-text-field variant="outlined" label="Custom error glyph" value="not-an-email" error error-text="Enter a valid email address" style="min-width: 220px;">
<span slot="error-icon" class="material-symbols-outlined">report</span>
</md-text-field>// Icons need the Material Symbols stylesheet in index.html — see Installation.
import { MdTextField } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdTextField variant="outlined" label="Custom clear glyph" clearable="internal" value="query" style={{ minWidth: '220px' }}>
<span slot="clear-icon" className="material-symbols-outlined">backspace</span>
</MdTextField>
<MdTextField variant="outlined" label="Custom toggle glyph" type="password" passwordToggle="internal" value="hunter2" style={{ minWidth: '220px' }}>
<span slot="password-toggle-icon" className="material-symbols-outlined">key</span>
</MdTextField>
<MdTextField variant="outlined" label="Custom error glyph" value="not-an-email" error errorText="Enter a valid email address" style={{ minWidth: '220px' }}>
<span slot="error-icon" className="material-symbols-outlined">report</span>
</MdTextField>
</>
);
}// Icons need the Material Symbols stylesheet in index.html — see Installation.
// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-text-field variant="outlined" label="Custom clear glyph" clearable="internal" value="query" style="min-width: 220px;">
<span slot="clear-icon" class="material-symbols-outlined">backspace</span>
</md-text-field>
<md-text-field variant="outlined" label="Custom toggle glyph" type="password" password-toggle="internal" value="hunter2" style="min-width: 220px;">
<span slot="password-toggle-icon" class="material-symbols-outlined">key</span>
</md-text-field>
<md-text-field variant="outlined" label="Custom error glyph" value="not-an-email" error error-text="Enter a valid email address" style="min-width: 220px;">
<span slot="error-icon" class="material-symbols-outlined">report</span>
</md-text-field><script setup>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import '@awc-ui/core/define';
</script>
<template>
<md-text-field variant="outlined" label="Custom clear glyph" clearable="internal" value="query" style="min-width: 220px;">
<span slot="clear-icon" class="material-symbols-outlined">backspace</span>
</md-text-field>
<md-text-field variant="outlined" label="Custom toggle glyph" type="password" password-toggle="internal" value="hunter2" style="min-width: 220px;">
<span slot="password-toggle-icon" class="material-symbols-outlined">key</span>
</md-text-field>
<md-text-field variant="outlined" label="Custom error glyph" value="not-an-email" error error-text="Enter a valid email address" style="min-width: 220px;">
<span slot="error-icon" class="material-symbols-outlined">report</span>
</md-text-field>
</template><script>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import '@awc-ui/core/define';
</script>
<md-text-field variant="outlined" label="Custom clear glyph" clearable="internal" value="query" style="min-width: 220px;">
<span slot="clear-icon" class="material-symbols-outlined">backspace</span>
</md-text-field>
<md-text-field variant="outlined" label="Custom toggle glyph" type="password" password-toggle="internal" value="hunter2" style="min-width: 220px;">
<span slot="password-toggle-icon" class="material-symbols-outlined">key</span>
</md-text-field>
<md-text-field variant="outlined" label="Custom error glyph" value="not-an-email" error error-text="Enter a valid email address" style="min-width: 220px;">
<span slot="error-icon" class="material-symbols-outlined">report</span>
</md-text-field>The speech-icon slot works the same way. chips is composite-owned — see the
Internal props note under the API Reference.
multiline="auto-grow" expands as the user types; "fixed" keeps a fixed
rows height.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-text-field variant="outlined" label="Notes" multiline="auto-grow" rows="2" max-length="500" style="min-width: 280px;"></md-text-field>
<md-text-field variant="filled" label="Comment" multiline="fixed" rows="4" style="min-width: 280px;"></md-text-field>import { MdTextField } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdTextField variant="outlined" label="Notes" multiline="auto-grow" rows="2" maxLength="500" style={{ minWidth: '280px' }}></MdTextField>
<MdTextField variant="filled" label="Comment" multiline="fixed" rows="4" style={{ minWidth: '280px' }}></MdTextField>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-text-field variant="outlined" label="Notes" multiline="auto-grow" rows="2" max-length="500" style="min-width: 280px;"></md-text-field>
<md-text-field variant="filled" label="Comment" multiline="fixed" rows="4" style="min-width: 280px;"></md-text-field><script setup>
import '@awc-ui/core/define';
</script>
<template>
<md-text-field variant="outlined" label="Notes" multiline="auto-grow" rows="2" max-length="500" style="min-width: 280px;"></md-text-field>
<md-text-field variant="filled" label="Comment" multiline="fixed" rows="4" style="min-width: 280px;"></md-text-field>
</template><script>
import '@awc-ui/core/define';
</script>
<md-text-field variant="outlined" label="Notes" multiline="auto-grow" rows="2" max-length="500" style="min-width: 280px;"></md-text-field>
<md-text-field variant="filled" label="Comment" multiline="fixed" rows="4" style="min-width: 280px;"></md-text-field>Use type, inputmode and autocomplete accurately — type="text" for an
email address is a real accessibility and UX cost.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-text-field variant="outlined" label="Email" type="email" inputmode="email" autocomplete="email" style="min-width: 200px;"></md-text-field>
<md-text-field variant="outlined" label="Phone" type="tel" inputmode="tel" autocomplete="tel" style="min-width: 200px;"></md-text-field>
<md-text-field variant="outlined" label="Quantity" type="number" min="1" max="99" step="1" style="min-width: 200px;"></md-text-field>
<md-text-field variant="outlined" label="Website" type="url" inputmode="url" style="min-width: 200px;"></md-text-field>import { MdTextField } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdTextField variant="outlined" label="Email" type="email" inputmode="email" autoComplete="email" style={{ minWidth: '200px' }}></MdTextField>
<MdTextField variant="outlined" label="Phone" type="tel" inputmode="tel" autoComplete="tel" style={{ minWidth: '200px' }}></MdTextField>
<MdTextField variant="outlined" label="Quantity" type="number" min="1" max="99" step="1" style={{ minWidth: '200px' }}></MdTextField>
<MdTextField variant="outlined" label="Website" type="url" inputmode="url" style={{ minWidth: '200px' }}></MdTextField>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-text-field variant="outlined" label="Email" type="email" inputmode="email" autocomplete="email" style="min-width: 200px;"></md-text-field>
<md-text-field variant="outlined" label="Phone" type="tel" inputmode="tel" autocomplete="tel" style="min-width: 200px;"></md-text-field>
<md-text-field variant="outlined" label="Quantity" type="number" min="1" max="99" step="1" style="min-width: 200px;"></md-text-field>
<md-text-field variant="outlined" label="Website" type="url" inputmode="url" style="min-width: 200px;"></md-text-field><script setup>
import '@awc-ui/core/define';
</script>
<template>
<md-text-field variant="outlined" label="Email" type="email" inputmode="email" autocomplete="email" style="min-width: 200px;"></md-text-field>
<md-text-field variant="outlined" label="Phone" type="tel" inputmode="tel" autocomplete="tel" style="min-width: 200px;"></md-text-field>
<md-text-field variant="outlined" label="Quantity" type="number" min="1" max="99" step="1" style="min-width: 200px;"></md-text-field>
<md-text-field variant="outlined" label="Website" type="url" inputmode="url" style="min-width: 200px;"></md-text-field>
</template><script>
import '@awc-ui/core/define';
</script>
<md-text-field variant="outlined" label="Email" type="email" inputmode="email" autocomplete="email" style="min-width: 200px;"></md-text-field>
<md-text-field variant="outlined" label="Phone" type="tel" inputmode="tel" autocomplete="tel" style="min-width: 200px;"></md-text-field>
<md-text-field variant="outlined" label="Quantity" type="number" min="1" max="99" step="1" style="min-width: 200px;"></md-text-field>
<md-text-field variant="outlined" label="Website" type="url" inputmode="url" style="min-width: 200px;"></md-text-field>Use type="tel" with inputmode="tel" for phone numbers — type="number"
brings spinners and locale parsing that get in the way.
formatter / parserformatter and parser are function props — assign them in JS, they can’t
cross the attribute boundary. They are a pair: formatter renders the display
value, parser converts it back.
field.formatter = (raw) => new Intl.NumberFormat('en-US').format(Number(raw));field.parser = (shown) => shown.replace(/,/g, '');<md-text-field id="amount" variant="outlined" label="Amount"
prefix-text="$" inputmode="decimal" value="1234567"></md-text-field>
<script type="module">
const field = document.getElementById('amount');
field.formatter = (raw) => (raw ? new Intl.NumberFormat('en-US').format(Number(raw)) : '');
field.parser = (shown) => shown.replace(/,/g, '');
field.addEventListener('mdChange', (e) => save(Number(e.detail)));
</script>import { MdTextField } from '@awc-ui/react';
const format = (raw: string) => (raw ? new Intl.NumberFormat('en-US').format(Number(raw)) : '');
const parse = (shown: string) => shown.replace(/,/g, '');
export function AmountField() {
return (
<MdTextField
variant="outlined"
label="Amount"
prefixText="$"
inputMode="decimal"
value="1234567"
formatter={format}
parser={parse}
onMdChange={(e) => save(Number(e.detail))}
/>
);
}import { Component } from '@angular/core';
@Component({
selector: 'app-amount-field',
template: `
<md-text-field
variant="outlined"
label="Amount"
prefix-text="$"
inputmode="decimal"
value="1234567"
[formatter]="format"
[parser]="parse"
(mdChange)="onChange($event)"
></md-text-field>
`,
})
export class AmountFieldComponent {
format = (raw: string) => (raw ? new Intl.NumberFormat('en-US').format(Number(raw)) : '');
parse = (shown: string) => shown.replace(/,/g, '');
onChange(e: CustomEvent<string>) {
save(Number(e.detail));
}
}<script setup lang="ts">
const format = (raw: string) => (raw ? new Intl.NumberFormat('en-US').format(Number(raw)) : '');
const parse = (shown: string) => shown.replace(/,/g, '');
function onChange(e: CustomEvent<string>) {
save(Number(e.detail));
}
</script>
<template>
<md-text-field
variant="outlined"
label="Amount"
prefix-text="$"
inputmode="decimal"
value="1234567"
:formatter.prop="format"
:parser.prop="parse"
@mdChange="onChange"
/>
</template><script lang="ts">
const format = (raw: string) => (raw ? new Intl.NumberFormat('en-US').format(Number(raw)) : '');
const parse = (shown: string) => shown.replace(/,/g, '');
function onChange(e: CustomEvent<string>) {
save(Number(e.detail));
}
</script>
<md-text-field
variant="outlined"
label="Amount"
prefix-text="$"
inputmode="decimal"
value="1234567"
formatter={format}
parser={parse}
on:mdChange={onChange}
></md-text-field>restrict blocks disallowed characters as they are typed. It takes a regex
character class ("[0-9]", "[0-9+() -]") or one of five named presets —
numeric, integer, decimal, alpha, alphanumeric.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-text-field variant="outlined" label="Digits only" restrict="[0-9]" inputmode="numeric" style="min-width: 180px;"></md-text-field>
<md-text-field variant="outlined" label="numeric" restrict="numeric" inputmode="numeric" style="min-width: 180px;"></md-text-field>
<md-text-field variant="outlined" label="decimal" restrict="decimal" inputmode="decimal" style="min-width: 180px;"></md-text-field>
<md-text-field variant="outlined" label="alphanumeric" restrict="alphanumeric" style="min-width: 180px;"></md-text-field>import { MdTextField } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdTextField variant="outlined" label="Digits only" restrict="[0-9]" inputmode="numeric" style={{ minWidth: '180px' }}></MdTextField>
<MdTextField variant="outlined" label="numeric" restrict="numeric" inputmode="numeric" style={{ minWidth: '180px' }}></MdTextField>
<MdTextField variant="outlined" label="decimal" restrict="decimal" inputmode="decimal" style={{ minWidth: '180px' }}></MdTextField>
<MdTextField variant="outlined" label="alphanumeric" restrict="alphanumeric" style={{ minWidth: '180px' }}></MdTextField>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-text-field variant="outlined" label="Digits only" restrict="[0-9]" inputmode="numeric" style="min-width: 180px;"></md-text-field>
<md-text-field variant="outlined" label="numeric" restrict="numeric" inputmode="numeric" style="min-width: 180px;"></md-text-field>
<md-text-field variant="outlined" label="decimal" restrict="decimal" inputmode="decimal" style="min-width: 180px;"></md-text-field>
<md-text-field variant="outlined" label="alphanumeric" restrict="alphanumeric" style="min-width: 180px;"></md-text-field><script setup>
import '@awc-ui/core/define';
</script>
<template>
<md-text-field variant="outlined" label="Digits only" restrict="[0-9]" inputmode="numeric" style="min-width: 180px;"></md-text-field>
<md-text-field variant="outlined" label="numeric" restrict="numeric" inputmode="numeric" style="min-width: 180px;"></md-text-field>
<md-text-field variant="outlined" label="decimal" restrict="decimal" inputmode="decimal" style="min-width: 180px;"></md-text-field>
<md-text-field variant="outlined" label="alphanumeric" restrict="alphanumeric" style="min-width: 180px;"></md-text-field>
</template><script>
import '@awc-ui/core/define';
</script>
<md-text-field variant="outlined" label="Digits only" restrict="[0-9]" inputmode="numeric" style="min-width: 180px;"></md-text-field>
<md-text-field variant="outlined" label="numeric" restrict="numeric" inputmode="numeric" style="min-width: 180px;"></md-text-field>
<md-text-field variant="outlined" label="decimal" restrict="decimal" inputmode="decimal" style="min-width: 180px;"></md-text-field>
<md-text-field variant="outlined" label="alphanumeric" restrict="alphanumeric" style="min-width: 180px;"></md-text-field>debounce and throttle gate mdSearch — not mdInput. mdInput always
fires on every keystroke; mdSearch is the rate-limited twin you point at an
API call. The usual search-as-you-type setup is debounce="300". Clearing the
field re-emits mdSearch with an empty string, so stale results get dropped.
<!-- index.html <head> — the icon font the components draw from -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=swap">
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-text-field variant="outlined" label="Search" type="search" clearable="internal" debounce="300" style="min-width: 260px;">
<span slot="leading-icon" class="material-symbols-outlined">search</span>
</md-text-field>// Icons need the Material Symbols stylesheet in index.html — see Installation.
import { MdTextField } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdTextField variant="outlined" label="Search" type="search" clearable="internal" debounce="300" style={{ minWidth: '260px' }}>
<span slot="leading-icon" className="material-symbols-outlined">search</span>
</MdTextField>
</>
);
}// Icons need the Material Symbols stylesheet in index.html — see Installation.
// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-text-field variant="outlined" label="Search" type="search" clearable="internal" debounce="300" style="min-width: 260px;">
<span slot="leading-icon" class="material-symbols-outlined">search</span>
</md-text-field><script setup>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import '@awc-ui/core/define';
</script>
<template>
<md-text-field variant="outlined" label="Search" type="search" clearable="internal" debounce="300" style="min-width: 260px;">
<span slot="leading-icon" class="material-symbols-outlined">search</span>
</md-text-field>
</template><script>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import '@awc-ui/core/define';
</script>
<md-text-field variant="outlined" label="Search" type="search" clearable="internal" debounce="300" style="min-width: 260px;">
<span slot="leading-icon" class="material-symbols-outlined">search</span>
</md-text-field>| Event | Vetoable | Detail | Fires |
|---|---|---|---|
mdInput | no | string | On every keystroke — never debounced or throttled |
mdChange | no | string | On commit (blur / Enter), and when the field is cleared |
mdSearch | no | string | Same trigger as mdInput, but gated by debounce / throttle, de-duplicated against the last emitted value, and re-emitted as '' on clear |
mdClear | no | void | The clear affordance was used (icon or Escape) |
mdPasswordToggle | no | { visible } | Password visibility toggled |
mdSpeechResult | no | { transcript, listening } | Speech recognition update |
mdValidityChange | no | { valid, validationMessage, flags } | Validity changed — not composed |
These are notifications, not hooks — preventDefault() on any of them is a
no-op (unlike md-button’s mdClick). Cancel at the
source instead: restrict to block characters, or setCustomValidity() to
reject a value.
<md-text-field id="search" label="Search" type="search"
clearable="internal" debounce="300"></md-text-field>
<script type="module">
const field = document.getElementById('search');
field.addEventListener('mdInput', (e) => setQuery(e.detail)); // every keystroke
field.addEventListener('mdSearch', (e) => fetchResults(e.detail)); // debounced 300ms
field.addEventListener('mdClear', () => fetchResults(''));
field.addEventListener('mdValidityChange', (e) => {
console.log(e.detail.valid, e.detail.validationMessage);
});
</script>import { MdTextField } from '@awc-ui/react';
export function SearchField() {
return (
<MdTextField
label="Search"
type="search"
clearable="internal"
debounce={300}
onMdInput={(e) => setQuery(e.detail)}
onMdSearch={(e) => fetchResults(e.detail)}
onMdClear={() => fetchResults('')}
onMdValidityChange={(e) => console.log(e.detail.valid, e.detail.validationMessage)}
/>
);
}import { Component } from '@angular/core';
@Component({
selector: 'app-search-field',
template: `
<md-text-field label="Search" type="search"
clearable="internal" debounce="300"
(mdInput)="onInput($event)"
(mdSearch)="onSearch($event)"
(mdClear)="onClear()"
(mdValidityChange)="onValidity($event)"></md-text-field>
`,
})
export class SearchFieldComponent {
onInput(e: CustomEvent<string>) { this.setQuery(e.detail); }
onSearch(e: CustomEvent<string>) { this.fetchResults(e.detail); }
onClear() { this.fetchResults(''); }
onValidity(e: CustomEvent) { console.log(e.detail.valid, e.detail.validationMessage); }
}<script setup lang="ts">
function onInput(e: CustomEvent<string>) { setQuery(e.detail); }
function onSearch(e: CustomEvent<string>) { fetchResults(e.detail); }
function onClear() { fetchResults(''); }
function onValidity(e: CustomEvent) { console.log(e.detail.valid, e.detail.validationMessage); }
</script>
<template>
<md-text-field
label="Search"
type="search"
clearable="internal"
debounce="300"
@mdInput="onInput"
@mdSearch="onSearch"
@mdClear="onClear"
@mdValidityChange="onValidity"
/>
</template><script lang="ts">
function onInput(e: CustomEvent<string>) { setQuery(e.detail); }
function onSearch(e: CustomEvent<string>) { fetchResults(e.detail); }
function onClear() { fetchResults(''); }
function onValidity(e: CustomEvent) { console.log(e.detail.valid, e.detail.validationMessage); }
</script>
<md-text-field
label="Search"
type="search"
clearable="internal"
debounce="300"
on:mdInput={onInput}
on:mdSearch={onSearch}
on:mdClear={onClear}
on:mdValidityChange={onValidity}
></md-text-field>md-text-field is form-associated via ElementInternals, so name puts
the value into FormData across the shadow boundary — no hidden <input>
needed. required, pattern, min-length, max-length, min, max and
step all feed native constraint validation, and setCustomValidity() covers
server-side errors.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<form id="profile">
<md-text-field
label="Email" type="email" name="email" required
autocomplete="email" inputmode="email"
supporting-text="We'll never share it"
error-text="Enter a valid email address"
reserve-supporting-space
></md-text-field>
<md-text-field
label="Display name" name="name" required
min-length="2" max-length="32"
supporting-text="2 to 32 characters"
reserve-supporting-space
></md-text-field>
<md-button variant="filled" type="submit">Save</md-button>
</form>import { MdButton, MdTextField } from '@awc-ui/react';
export function Demo() {
return (
<>
<form id="profile">
<MdTextField
label="Email" type="email" name="email" required
autoComplete="email" inputmode="email"
supportingText="We'll never share it"
errorText="Enter a valid email address"
reserveSupportingSpace
></MdTextField>
<MdTextField
label="Display name" name="name" required
minLength="2" maxLength="32"
supportingText="2 to 32 characters"
reserveSupportingSpace
></MdTextField>
<MdButton variant="filled" type="submit">Save</MdButton>
</form>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<form id="profile">
<md-text-field
label="Email" type="email" name="email" required
autocomplete="email" inputmode="email"
supporting-text="We'll never share it"
error-text="Enter a valid email address"
reserve-supporting-space
></md-text-field>
<md-text-field
label="Display name" name="name" required
min-length="2" max-length="32"
supporting-text="2 to 32 characters"
reserve-supporting-space
></md-text-field>
<md-button variant="filled" type="submit">Save</md-button>
</form><script setup>
import '@awc-ui/core/define';
</script>
<template>
<form id="profile">
<md-text-field
label="Email" type="email" name="email" required
autocomplete="email" inputmode="email"
supporting-text="We'll never share it"
error-text="Enter a valid email address"
reserve-supporting-space
></md-text-field>
<md-text-field
label="Display name" name="name" required
min-length="2" max-length="32"
supporting-text="2 to 32 characters"
reserve-supporting-space
></md-text-field>
<md-button variant="filled" type="submit">Save</md-button>
</form>
</template><script>
import '@awc-ui/core/define';
</script>
<form id="profile">
<md-text-field
label="Email" type="email" name="email" required
autocomplete="email" inputmode="email"
supporting-text="We'll never share it"
error-text="Enter a valid email address"
reserve-supporting-space
></md-text-field>
<md-text-field
label="Display name" name="name" required
min-length="2" max-length="32"
supporting-text="2 to 32 characters"
reserve-supporting-space
></md-text-field>
<md-button variant="filled" type="submit">Save</md-button>
</form><form id="profile">
<md-text-field
label="Email" type="email" name="email" required
autocomplete="email" inputmode="email"
supporting-text="We'll never share it"
error-text="Enter a valid email address"
reserve-supporting-space
></md-text-field>
<md-text-field
label="Display name" name="name" required
min-length="2" max-length="32"
supporting-text="2 to 32 characters"
reserve-supporting-space
></md-text-field>
<md-button variant="filled" type="submit">Save</md-button>
</form>
<script type="module">
const form = document.getElementById('profile');
const field = form.querySelector('md-text-field');
form.addEventListener('submit', (e) => {
e.preventDefault();
console.log(Object.fromEntries(new FormData(e.target))); // { email: '…', name: '…' }
});
// Server-side validation
field.setCustomValidity('That email is already registered');
// clear it again with: field.setCustomValidity('')
</script>import { MdTextField, MdButton } from '@awc-ui/react';
export function ProfileForm() {
function onSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
console.log(Object.fromEntries(new FormData(e.currentTarget)));
}
return (
<form onSubmit={onSubmit}>
<MdTextField
label="Email"
type="email"
name="email"
required
autocomplete="email"
supportingText="We'll never share it"
errorText="Enter a valid email address"
reserveSupportingSpace
/>
<MdTextField
label="Display name"
name="name"
required
minLength={2}
maxLength={32}
supportingText="2 to 32 characters"
reserveSupportingSpace
/>
<MdButton variant="filled" type="submit">Save</MdButton>
</form>
);
}import { Component } from '@angular/core';
@Component({
selector: 'app-profile-form',
template: `
<form (submit)="onSubmit($event)">
<md-text-field label="Email" type="email" name="email" required
autocomplete="email"
supporting-text="We'll never share it"
error-text="Enter a valid email address"
reserve-supporting-space></md-text-field>
<md-text-field label="Display name" name="name" required
min-length="2" max-length="32"
supporting-text="2 to 32 characters"
reserve-supporting-space></md-text-field>
<md-button variant="filled" type="submit">Save</md-button>
</form>
`,
})
export class ProfileFormComponent {
onSubmit(e: Event) {
e.preventDefault();
console.log(Object.fromEntries(new FormData(e.target as HTMLFormElement)));
}
}<script setup lang="ts">
function onSubmit(e: Event) {
e.preventDefault();
console.log(Object.fromEntries(new FormData(e.target as HTMLFormElement)));
}
</script>
<template>
<form @submit="onSubmit">
<md-text-field
label="Email"
type="email"
name="email"
required
autocomplete="email"
supporting-text="We'll never share it"
error-text="Enter a valid email address"
reserve-supporting-space
/>
<md-text-field
label="Display name"
name="name"
required
min-length="2"
max-length="32"
supporting-text="2 to 32 characters"
reserve-supporting-space
/>
<md-button variant="filled" type="submit">Save</md-button>
</form>
</template><script lang="ts">
function onSubmit(e: Event) {
e.preventDefault();
console.log(Object.fromEntries(new FormData(e.target as HTMLFormElement)));
}
</script>
<form on:submit={onSubmit}>
<md-text-field
label="Email"
type="email"
name="email"
required
autocomplete="email"
supporting-text="We'll never share it"
error-text="Enter a valid email address"
reserve-supporting-space
></md-text-field>
<md-text-field
label="Display name"
name="name"
required
min-length="2"
max-length="32"
supporting-text="2 to 32 characters"
reserve-supporting-space
></md-text-field>
<md-button variant="filled" type="submit">Save</md-button>
</form>getValidity(), checkValidity() and reportValidity() mirror the native API;
setFocus() and select() handle focus and selection.
| Property | Attribute | Type | Default | Reflects |
|---|---|---|---|---|
reserveSupportingSpace | reserve-supporting-space | boolean | false | — |
variant | variant | 'filled' | 'outlined' | 'filled' | — |
label | label | string | '' | — |
value | value | string | '' | — |
placeholder | placeholder | string | '' | — |
type | type | string | 'text' | — |
name | name | string | '' | Yes |
pattern | pattern | string | '' | — |
minLength | min-length | number | undefined | — | — |
min | min | string | number | undefined | — | — |
max | max | string | number | undefined | — | — |
step | step | string | number | undefined | — | — |
autocomplete | autocomplete | string | '' | — |
inputMode | inputmode | string | '' | — |
enterKeyHint | enterkeyhint | string | '' | — |
autoCapitalize | autocapitalize | string | '' | — |
spellcheck | spellcheck | boolean | undefined | — | — |
disabled | disabled | boolean | false | Yes |
readOnly | readonly | boolean | false | — |
required | required | boolean | false | — |
error | error | boolean | false | — |
errorText | error-text | string | '' | — |
supportingText | supporting-text | string | '' | — |
prefixText | prefix-text | string | '' | — |
suffixText | suffix-text | string | '' | — |
maxLength | max-length | number | undefined | — | — |
clearable | clearable | 'internal' | 'external' | false | false | — |
passwordToggle | password-toggle | 'internal' | 'external' | false | false | — |
density | density | 0 | -1 | -2 | -3 | -4 | 0 | Yes |
multiline | multiline | 'auto-grow' | 'fixed' | false | false | — |
rows | rows | number | undefined | — | — |
speechToText | speech-to-text | 'internal' | 'external' | false | false | — |
speechLang | speech-lang | string | '' | — |
restrict | restrict | string | '' | — |
formatter | JS only | (value: string) => string | — | — |
parser | JS only | (displayValue: string) => string | — | — |
formatOn | format-on | 'blur' | 'input' | 'blur' | — |
focusBorderWidth | focus-border-width | number | 3 | Yes |
appearFocused | appear-focused | boolean | false | Yes |
chipsWrap | chips-wrap | boolean | false | Yes |
debounce | debounce | number | 0 | Yes |
throttle | throttle | number | 0 | Yes |
inputRole | input-role | '' | 'combobox' | '' | — |
inputExpanded | input-expanded | boolean | false | — |
inputAriaAutocomplete | input-aria-autocomplete | '' | 'none' | 'inline' | 'list' | 'both' | '' | — |
| Method | Parameters |
|---|---|
setFocus() | none |
select() | none |
getInputElement() | none |
getValidity() | none |
setCustomValidity() | message: string |
checkValidity() | none |
reportValidity() | none |
| Slot | Description |
|---|---|
leading-icon | Custom leading icon (overrides nothing — pure decoration) |
chips | — |
clear-icon | Custom clear-button glyph (replaces the default "cancel" icon) |
password-toggle-icon | Custom password-toggle glyph |
speech-icon | Custom microphone glyph |
error-icon | Custom error-state icon (replaces the default filled "error") |
trailing-icon | Custom trailing icon |
Override on the host element for per-instance theming:
| Property | Description |
|---|---|
--md-text-field-container-color | Filled-variant container background |
--md-text-field-input-color | Input text colour |
--md-text-field-label-color | Resting label colour |
--md-text-field-active-indicator-color | Filled bottom line + outlined border on focus |
--md-text-field-outline-color | Outlined-variant resting border |
--md-text-field-error-color | Error accent (label, indicator, icon, helper) |
--md-text-field-supporting-text-color | Supporting text + character counter |
--md-text-field-icon-color | Leading / trailing / clear / password / speech icons |
--md-text-field-icon-size | All glyph sizes (24px; tapers with |
--md-text-field-optical-nudge | Outlined only: px the input text is |
--md-text-field-container-shape | Border-radius for both variants |
--md-text-field-filled-pill | Filled only: 1 rounds all corners (pill); |
--md-text-field-cursor | Cursor over the field (default: text) |
--md-text-field-focus-border-width | Border thickness on focus (1, 2, or 3 px) |
--md-text-field-focus-inset | Inset of the focus ring (default 0 — it |
--md-text-field-padding-inline-start | — |
--md-text-field-padding-inline-end | — |
Style internal elements through shadow DOM with ::part():
| Part | Description |
|---|---|
input | The native input / textarea |
container | Field container (state layer + input row) |
label | Floating label |
chips | — |
supporting-text | Supporting / error text line |
counter | Character counter |
label provides the accessible name — always set it. aria-label works too,
but a visible label is better.readonly stays focusable and readable; disabled does not.--md-text-field-focus-border-width), and appear-focused can force the
focused look for composite triggers.max-length) is exposed alongside the field, not only visually.Escape clears a clearable="internal" field and stops there, so an
enclosing <dialog> does not also close.Tab through these: the read-only field takes focus and can be copied from, the
disabled one is skipped, the error field announces its message, and the last has
no visible label so it leans entirely on aria-label.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-text-field variant="outlined" label="Editable" value="Ada Lovelace" style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Read only — still focusable" value="AWC-4021" readonly style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Disabled — skipped" value="Unavailable" disabled style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Email" type="email" value="not-an-email" required error error-text="Enter a valid email address" style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" placeholder="Filter invoices" aria-label="Filter invoices" clearable="internal" value="4021" style="min-width: 220px;"></md-text-field>import { MdTextField } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdTextField variant="outlined" label="Editable" value="Ada Lovelace" style={{ minWidth: '220px' }}></MdTextField>
<MdTextField variant="outlined" label="Read only — still focusable" value="AWC-4021" readonly style={{ minWidth: '220px' }}></MdTextField>
<MdTextField variant="outlined" label="Disabled — skipped" value="Unavailable" disabled style={{ minWidth: '220px' }}></MdTextField>
<MdTextField variant="outlined" label="Email" type="email" value="not-an-email" required error errorText="Enter a valid email address" style={{ minWidth: '220px' }}></MdTextField>
<MdTextField variant="outlined" placeholder="Filter invoices" aria-label="Filter invoices" clearable="internal" value="4021" style={{ minWidth: '220px' }}></MdTextField>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-text-field variant="outlined" label="Editable" value="Ada Lovelace" style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Read only — still focusable" value="AWC-4021" readonly style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Disabled — skipped" value="Unavailable" disabled style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Email" type="email" value="not-an-email" required error error-text="Enter a valid email address" style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" placeholder="Filter invoices" aria-label="Filter invoices" clearable="internal" value="4021" style="min-width: 220px;"></md-text-field><script setup>
import '@awc-ui/core/define';
</script>
<template>
<md-text-field variant="outlined" label="Editable" value="Ada Lovelace" style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Read only — still focusable" value="AWC-4021" readonly style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Disabled — skipped" value="Unavailable" disabled style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Email" type="email" value="not-an-email" required error error-text="Enter a valid email address" style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" placeholder="Filter invoices" aria-label="Filter invoices" clearable="internal" value="4021" style="min-width: 220px;"></md-text-field>
</template><script>
import '@awc-ui/core/define';
</script>
<md-text-field variant="outlined" label="Editable" value="Ada Lovelace" style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Read only — still focusable" value="AWC-4021" readonly style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Disabled — skipped" value="Unavailable" disabled style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" label="Email" type="email" value="not-an-email" required error error-text="Enter a valid email address" style="min-width: 220px;"></md-text-field>
<md-text-field variant="outlined" placeholder="Filter invoices" aria-label="Filter invoices" clearable="internal" value="4021" style="min-width: 220px;"></md-text-field>The last field has no visible label, so aria-label is the only accessible
name it has — prefer a visible label wherever the layout allows one. Note that
its clear button is its own tab stop, and that Escape clears the field without
leaving it.
RTL — layout, prefix / suffix and icon sides mirror automatically. Set the direction on an ancestor and the whole field follows; nothing on the component needs changing. See RTL.
<div dir="rtl"> <md-text-field label="بحث" clearable="internal"></md-text-field></div><!-- index.html <head> — the icon font the components draw from -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=swap">
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<div style="display:grid;grid-template-columns:auto 1fr;gap:14px 16px;align-items:center;">
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">ltr</span>
<div dir="ltr" style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="outlined" label="Search" value="Hello world" clearable="internal" style="min-width:200px;"><span slot="leading-icon" class="material-symbols-outlined">search</span></md-text-field>
<md-text-field variant="outlined" label="Amount" prefix-text="$" suffix-text="USD" value="1200" inputmode="decimal" style="min-width:200px;"></md-text-field>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">rtl</span>
<div dir="rtl" style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="outlined" label="بحث" value="مرحبا بالعالم" clearable="internal" style="min-width:200px;"><span slot="leading-icon" class="material-symbols-outlined">search</span></md-text-field>
<md-text-field variant="outlined" label="المبلغ" prefix-text="$" suffix-text="USD" value="1200" inputmode="decimal" style="min-width:200px;"></md-text-field>
</div>
</div>// Icons need the Material Symbols stylesheet in index.html — see Installation.
import { MdTextField } from '@awc-ui/react';
export function Demo() {
return (
<>
<div style={{ display: 'grid', gridTemplateColumns: 'auto 1fr', gap: '14px 16px', alignItems: 'center' }}>
<span style={{ inlineSize: '3.5rem', opacity: '.65', fontSize: '.75rem', fontFamily: 'ui-monospace,monospace' }}>ltr</span>
<div dir="ltr" style={{ display: 'flex', gap: '12px', flexWrap: 'wrap', alignItems: 'center' }}>
<MdTextField variant="outlined" label="Search" value="Hello world" clearable="internal" style={{ minWidth: '200px' }}><span slot="leading-icon" className="material-symbols-outlined">search</span></MdTextField>
<MdTextField variant="outlined" label="Amount" prefixText="$" suffixText="USD" value="1200" inputmode="decimal" style={{ minWidth: '200px' }}></MdTextField>
</div>
<span style={{ inlineSize: '3.5rem', opacity: '.65', fontSize: '.75rem', fontFamily: 'ui-monospace,monospace' }}>rtl</span>
<div dir="rtl" style={{ display: 'flex', gap: '12px', flexWrap: 'wrap', alignItems: 'center' }}>
<MdTextField variant="outlined" label="بحث" value="مرحبا بالعالم" clearable="internal" style={{ minWidth: '200px' }}><span slot="leading-icon" className="material-symbols-outlined">search</span></MdTextField>
<MdTextField variant="outlined" label="المبلغ" prefixText="$" suffixText="USD" value="1200" inputmode="decimal" style={{ minWidth: '200px' }}></MdTextField>
</div>
</div>
</>
);
}// Icons need the Material Symbols stylesheet in index.html — see Installation.
// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<div style="display:grid;grid-template-columns:auto 1fr;gap:14px 16px;align-items:center;">
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">ltr</span>
<div dir="ltr" style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="outlined" label="Search" value="Hello world" clearable="internal" style="min-width:200px;"><span slot="leading-icon" class="material-symbols-outlined">search</span></md-text-field>
<md-text-field variant="outlined" label="Amount" prefix-text="$" suffix-text="USD" value="1200" inputmode="decimal" style="min-width:200px;"></md-text-field>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">rtl</span>
<div dir="rtl" style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="outlined" label="بحث" value="مرحبا بالعالم" clearable="internal" style="min-width:200px;"><span slot="leading-icon" class="material-symbols-outlined">search</span></md-text-field>
<md-text-field variant="outlined" label="المبلغ" prefix-text="$" suffix-text="USD" value="1200" inputmode="decimal" style="min-width:200px;"></md-text-field>
</div>
</div><script setup>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import '@awc-ui/core/define';
</script>
<template>
<div style="display:grid;grid-template-columns:auto 1fr;gap:14px 16px;align-items:center;">
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">ltr</span>
<div dir="ltr" style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="outlined" label="Search" value="Hello world" clearable="internal" style="min-width:200px;"><span slot="leading-icon" class="material-symbols-outlined">search</span></md-text-field>
<md-text-field variant="outlined" label="Amount" prefix-text="$" suffix-text="USD" value="1200" inputmode="decimal" style="min-width:200px;"></md-text-field>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">rtl</span>
<div dir="rtl" style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="outlined" label="بحث" value="مرحبا بالعالم" clearable="internal" style="min-width:200px;"><span slot="leading-icon" class="material-symbols-outlined">search</span></md-text-field>
<md-text-field variant="outlined" label="المبلغ" prefix-text="$" suffix-text="USD" value="1200" inputmode="decimal" style="min-width:200px;"></md-text-field>
</div>
</div>
</template><script>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import '@awc-ui/core/define';
</script>
<div style="display:grid;grid-template-columns:auto 1fr;gap:14px 16px;align-items:center;">
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">ltr</span>
<div dir="ltr" style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="outlined" label="Search" value="Hello world" clearable="internal" style="min-width:200px;"><span slot="leading-icon" class="material-symbols-outlined">search</span></md-text-field>
<md-text-field variant="outlined" label="Amount" prefix-text="$" suffix-text="USD" value="1200" inputmode="decimal" style="min-width:200px;"></md-text-field>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">rtl</span>
<div dir="rtl" style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="outlined" label="بحث" value="مرحبا بالعالم" clearable="internal" style="min-width:200px;"><span slot="leading-icon" class="material-symbols-outlined">search</span></md-text-field>
<md-text-field variant="outlined" label="المبلغ" prefix-text="$" suffix-text="USD" value="1200" inputmode="decimal" style="min-width:200px;"></md-text-field>
</div>
</div>prefix-text and suffix-text swap sides with the direction — check that a
currency symbol still lands where the locale expects it, because a $ that
belongs on the leading side in English belongs there in Arabic too, and the
mirror will move it.
density="-1…-4" compresses the container from 56px down to 40px, 4px per rung,
and the label, input line box and every glyph taper with it.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<div style="display:grid;grid-template-columns:auto 1fr;gap:14px 16px;align-items:center;">
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">0</span>
<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="filled" label="Email" density="0" value="ada@example.com" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="Email" density="0" value="ada@example.com" style="min-width:200px;"></md-text-field>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-1</span>
<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="filled" label="Email" density="-1" value="ada@example.com" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="Email" density="-1" value="ada@example.com" style="min-width:200px;"></md-text-field>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-2</span>
<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="filled" label="Email" density="-2" value="ada@example.com" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="Email" density="-2" value="ada@example.com" style="min-width:200px;"></md-text-field>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-3</span>
<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="filled" label="Email" density="-3" value="ada@example.com" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="Email" density="-3" value="ada@example.com" style="min-width:200px;"></md-text-field>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-4</span>
<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="filled" label="Email" density="-4" value="ada@example.com" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="Email" density="-4" value="ada@example.com" style="min-width:200px;"></md-text-field>
</div>
</div>import { MdTextField } from '@awc-ui/react';
export function Demo() {
return (
<>
<div style={{ display: 'grid', gridTemplateColumns: 'auto 1fr', gap: '14px 16px', alignItems: 'center' }}>
<span style={{ inlineSize: '3.5rem', opacity: '.65', fontSize: '.75rem', fontFamily: 'ui-monospace,monospace' }}>0</span>
<div style={{ display: 'flex', gap: '12px', flexWrap: 'wrap', alignItems: 'center' }}>
<MdTextField variant="filled" label="Email" density="0" value="ada@example.com" style={{ minWidth: '200px' }}></MdTextField>
<MdTextField variant="outlined" label="Email" density="0" value="ada@example.com" style={{ minWidth: '200px' }}></MdTextField>
</div>
<span style={{ inlineSize: '3.5rem', opacity: '.65', fontSize: '.75rem', fontFamily: 'ui-monospace,monospace' }}>-1</span>
<div style={{ display: 'flex', gap: '12px', flexWrap: 'wrap', alignItems: 'center' }}>
<MdTextField variant="filled" label="Email" density="-1" value="ada@example.com" style={{ minWidth: '200px' }}></MdTextField>
<MdTextField variant="outlined" label="Email" density="-1" value="ada@example.com" style={{ minWidth: '200px' }}></MdTextField>
</div>
<span style={{ inlineSize: '3.5rem', opacity: '.65', fontSize: '.75rem', fontFamily: 'ui-monospace,monospace' }}>-2</span>
<div style={{ display: 'flex', gap: '12px', flexWrap: 'wrap', alignItems: 'center' }}>
<MdTextField variant="filled" label="Email" density="-2" value="ada@example.com" style={{ minWidth: '200px' }}></MdTextField>
<MdTextField variant="outlined" label="Email" density="-2" value="ada@example.com" style={{ minWidth: '200px' }}></MdTextField>
</div>
<span style={{ inlineSize: '3.5rem', opacity: '.65', fontSize: '.75rem', fontFamily: 'ui-monospace,monospace' }}>-3</span>
<div style={{ display: 'flex', gap: '12px', flexWrap: 'wrap', alignItems: 'center' }}>
<MdTextField variant="filled" label="Email" density="-3" value="ada@example.com" style={{ minWidth: '200px' }}></MdTextField>
<MdTextField variant="outlined" label="Email" density="-3" value="ada@example.com" style={{ minWidth: '200px' }}></MdTextField>
</div>
<span style={{ inlineSize: '3.5rem', opacity: '.65', fontSize: '.75rem', fontFamily: 'ui-monospace,monospace' }}>-4</span>
<div style={{ display: 'flex', gap: '12px', flexWrap: 'wrap', alignItems: 'center' }}>
<MdTextField variant="filled" label="Email" density="-4" value="ada@example.com" style={{ minWidth: '200px' }}></MdTextField>
<MdTextField variant="outlined" label="Email" density="-4" value="ada@example.com" style={{ minWidth: '200px' }}></MdTextField>
</div>
</div>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<div style="display:grid;grid-template-columns:auto 1fr;gap:14px 16px;align-items:center;">
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">0</span>
<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="filled" label="Email" density="0" value="ada@example.com" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="Email" density="0" value="ada@example.com" style="min-width:200px;"></md-text-field>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-1</span>
<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="filled" label="Email" density="-1" value="ada@example.com" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="Email" density="-1" value="ada@example.com" style="min-width:200px;"></md-text-field>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-2</span>
<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="filled" label="Email" density="-2" value="ada@example.com" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="Email" density="-2" value="ada@example.com" style="min-width:200px;"></md-text-field>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-3</span>
<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="filled" label="Email" density="-3" value="ada@example.com" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="Email" density="-3" value="ada@example.com" style="min-width:200px;"></md-text-field>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-4</span>
<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="filled" label="Email" density="-4" value="ada@example.com" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="Email" density="-4" value="ada@example.com" style="min-width:200px;"></md-text-field>
</div>
</div><script setup>
import '@awc-ui/core/define';
</script>
<template>
<div style="display:grid;grid-template-columns:auto 1fr;gap:14px 16px;align-items:center;">
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">0</span>
<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="filled" label="Email" density="0" value="ada@example.com" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="Email" density="0" value="ada@example.com" style="min-width:200px;"></md-text-field>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-1</span>
<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="filled" label="Email" density="-1" value="ada@example.com" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="Email" density="-1" value="ada@example.com" style="min-width:200px;"></md-text-field>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-2</span>
<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="filled" label="Email" density="-2" value="ada@example.com" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="Email" density="-2" value="ada@example.com" style="min-width:200px;"></md-text-field>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-3</span>
<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="filled" label="Email" density="-3" value="ada@example.com" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="Email" density="-3" value="ada@example.com" style="min-width:200px;"></md-text-field>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-4</span>
<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="filled" label="Email" density="-4" value="ada@example.com" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="Email" density="-4" value="ada@example.com" style="min-width:200px;"></md-text-field>
</div>
</div>
</template><script>
import '@awc-ui/core/define';
</script>
<div style="display:grid;grid-template-columns:auto 1fr;gap:14px 16px;align-items:center;">
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">0</span>
<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="filled" label="Email" density="0" value="ada@example.com" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="Email" density="0" value="ada@example.com" style="min-width:200px;"></md-text-field>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-1</span>
<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="filled" label="Email" density="-1" value="ada@example.com" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="Email" density="-1" value="ada@example.com" style="min-width:200px;"></md-text-field>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-2</span>
<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="filled" label="Email" density="-2" value="ada@example.com" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="Email" density="-2" value="ada@example.com" style="min-width:200px;"></md-text-field>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-3</span>
<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="filled" label="Email" density="-3" value="ada@example.com" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="Email" density="-3" value="ada@example.com" style="min-width:200px;"></md-text-field>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-4</span>
<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="filled" label="Email" density="-4" value="ada@example.com" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="Email" density="-4" value="ada@example.com" style="min-width:200px;"></md-text-field>
</div>
</div>The density prop and a global data-density ancestor drive the same signal —
--md-sys-density-scale — so a wrapper sets the rung for everything inside it
and any one field can override it with a rung of its own.
<!-- index.html <head> — the icon font the components draw from -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=swap">
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<div dir="rtl" data-density="-2" style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="outlined" label="البريد الإلكتروني" value="ada@example.com" style="min-width:200px;"><span slot="leading-icon" class="material-symbols-outlined">mail</span></md-text-field>
<md-text-field variant="outlined" label="كلمة المرور" type="password" password-toggle="internal" value="hunter2" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="أكثر إحكاما" density="-4" value="مرحبا" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="افتراضي" value="مرحبا" style="--md-sys-density-scale: 0; min-width:200px;"></md-text-field>
</div>// Icons need the Material Symbols stylesheet in index.html — see Installation.
import { MdTextField } from '@awc-ui/react';
export function Demo() {
return (
<>
<div dir="rtl" data-density="-2" style={{ display: 'flex', gap: '12px', flexWrap: 'wrap', alignItems: 'center' }}>
<MdTextField variant="outlined" label="البريد الإلكتروني" value="ada@example.com" style={{ minWidth: '200px' }}><span slot="leading-icon" className="material-symbols-outlined">mail</span></MdTextField>
<MdTextField variant="outlined" label="كلمة المرور" type="password" passwordToggle="internal" value="hunter2" style={{ minWidth: '200px' }}></MdTextField>
<MdTextField variant="outlined" label="أكثر إحكاما" density="-4" value="مرحبا" style={{ minWidth: '200px' }}></MdTextField>
<MdTextField variant="outlined" label="افتراضي" value="مرحبا" style={{ '--md-sys-density-scale': '0', minWidth: '200px' }}></MdTextField>
</div>
</>
);
}// Icons need the Material Symbols stylesheet in index.html — see Installation.
// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<div dir="rtl" data-density="-2" style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="outlined" label="البريد الإلكتروني" value="ada@example.com" style="min-width:200px;"><span slot="leading-icon" class="material-symbols-outlined">mail</span></md-text-field>
<md-text-field variant="outlined" label="كلمة المرور" type="password" password-toggle="internal" value="hunter2" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="أكثر إحكاما" density="-4" value="مرحبا" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="افتراضي" value="مرحبا" style="--md-sys-density-scale: 0; min-width:200px;"></md-text-field>
</div><script setup>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import '@awc-ui/core/define';
</script>
<template>
<div dir="rtl" data-density="-2" style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="outlined" label="البريد الإلكتروني" value="ada@example.com" style="min-width:200px;"><span slot="leading-icon" class="material-symbols-outlined">mail</span></md-text-field>
<md-text-field variant="outlined" label="كلمة المرور" type="password" password-toggle="internal" value="hunter2" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="أكثر إحكاما" density="-4" value="مرحبا" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="افتراضي" value="مرحبا" style="--md-sys-density-scale: 0; min-width:200px;"></md-text-field>
</div>
</template><script>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import '@awc-ui/core/define';
</script>
<div dir="rtl" data-density="-2" style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;">
<md-text-field variant="outlined" label="البريد الإلكتروني" value="ada@example.com" style="min-width:200px;"><span slot="leading-icon" class="material-symbols-outlined">mail</span></md-text-field>
<md-text-field variant="outlined" label="كلمة المرور" type="password" password-toggle="internal" value="hunter2" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="أكثر إحكاما" density="-4" value="مرحبا" style="min-width:200px;"></md-text-field>
<md-text-field variant="outlined" label="افتراضي" value="مرحبا" style="--md-sys-density-scale: 0; min-width:200px;"></md-text-field>
</div>Density — reach for a rung, not a hand-tuned height: the rung tapers the
container, the padding, the label and the glyphs together, which a height
override cannot. See Density.
i18n — translate label, supporting-text, error-text, placeholder,
prefix-text and suffix-text. Set speech-lang per locale, and use Intl
inside formatter for locale-correct numbers and currency.
| Custom property | Purpose | Default |
|---|---|---|
--md-text-field-container-color | Filled-variant container background | --md-sys-color-surface-container-highest |
--md-text-field-input-color | Input text and caret colour | --md-sys-color-on-surface |
--md-text-field-label-color | Resting label colour | --md-sys-color-on-surface-variant |
--md-text-field-active-indicator-color | Filled underline, outlined border on focus | --md-sys-color-primary |
--md-text-field-outline-color | Outlined-variant resting border | --md-sys-color-outline |
--md-text-field-error-color | Error accent (label, indicator, icon, helper) | --md-sys-color-error |
--md-text-field-supporting-text-color | Supporting text and character counter | --md-sys-color-on-surface-variant |
--md-text-field-icon-color | Every glyph: leading, trailing, clear, password, speech | --md-sys-color-on-surface-variant |
--md-text-field-icon-size | Every glyph’s size; tapers 1px per density rung | 24px (18px floor) |
--md-text-field-container-shape | Corner radius, both variants | --md-sys-shape-corner-extra-small (4px) |
--md-text-field-filled-pill | Filled only: 1 rounds the bottom corners too (pill) | 0 |
--md-text-field-padding-inline-start / -end | Per-side container inset | --md-sys-spacing-inset-lg + 7px |
--md-text-field-optical-nudge | Outlined only: px the input text is nudged down | 0px |
--md-text-field-focus-border-width | Border thickness on focus | 3px |
--md-text-field-focus-inset | Negative inset compensating for the focus border | -2px |
--md-text-field-cursor | Cursor over the field | text |
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-text-field variant="outlined" label="Squared off" value="Custom" style="--md-text-field-container-shape: 0px; --md-text-field-outline-color: var(--md-sys-color-primary); min-width: 220px;"></md-text-field>
<md-text-field variant="filled" label="Pill" value="Custom" style="--md-text-field-filled-pill: 1; --md-text-field-container-shape: 28px; min-width: 220px;"></md-text-field>import { MdTextField } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdTextField variant="outlined" label="Squared off" value="Custom" style={{ '--md-text-field-container-shape': '0px', '--md-text-field-outline-color': 'var(--md-sys-color-primary)', minWidth: '220px' }}></MdTextField>
<MdTextField variant="filled" label="Pill" value="Custom" style={{ '--md-text-field-filled-pill': '1', '--md-text-field-container-shape': '28px', minWidth: '220px' }}></MdTextField>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-text-field variant="outlined" label="Squared off" value="Custom" style="--md-text-field-container-shape: 0px; --md-text-field-outline-color: var(--md-sys-color-primary); min-width: 220px;"></md-text-field>
<md-text-field variant="filled" label="Pill" value="Custom" style="--md-text-field-filled-pill: 1; --md-text-field-container-shape: 28px; min-width: 220px;"></md-text-field><script setup>
import '@awc-ui/core/define';
</script>
<template>
<md-text-field variant="outlined" label="Squared off" value="Custom" style="--md-text-field-container-shape: 0px; --md-text-field-outline-color: var(--md-sys-color-primary); min-width: 220px;"></md-text-field>
<md-text-field variant="filled" label="Pill" value="Custom" style="--md-text-field-filled-pill: 1; --md-text-field-container-shape: 28px; min-width: 220px;"></md-text-field>
</template><script>
import '@awc-ui/core/define';
</script>
<md-text-field variant="outlined" label="Squared off" value="Custom" style="--md-text-field-container-shape: 0px; --md-text-field-outline-color: var(--md-sys-color-primary); min-width: 220px;"></md-text-field>
<md-text-field variant="filled" label="Pill" value="Custom" style="--md-text-field-filled-pill: 1; --md-text-field-container-shape: 28px; min-width: 220px;"></md-text-field>Every default resolves through an md-sys-color role, so a field that sets no
custom properties follows the theme on its own:
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-text-field label="Outlined" value="Ada Lovelace" style="min-width: 220px;"></md-text-field>
<md-text-field variant="filled" label="Filled" value="Ada Lovelace" style="min-width: 220px;"></md-text-field>
<md-text-field label="With error" value="not-an-email" error error-text="Enter a valid email" style="min-width: 220px;"></md-text-field>import { MdTextField } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdTextField label="Outlined" value="Ada Lovelace" style={{ minWidth: '220px' }}></MdTextField>
<MdTextField variant="filled" label="Filled" value="Ada Lovelace" style={{ minWidth: '220px' }}></MdTextField>
<MdTextField label="With error" value="not-an-email" error errorText="Enter a valid email" style={{ minWidth: '220px' }}></MdTextField>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-text-field label="Outlined" value="Ada Lovelace" style="min-width: 220px;"></md-text-field>
<md-text-field variant="filled" label="Filled" value="Ada Lovelace" style="min-width: 220px;"></md-text-field>
<md-text-field label="With error" value="not-an-email" error error-text="Enter a valid email" style="min-width: 220px;"></md-text-field><script setup>
import '@awc-ui/core/define';
</script>
<template>
<md-text-field label="Outlined" value="Ada Lovelace" style="min-width: 220px;"></md-text-field>
<md-text-field variant="filled" label="Filled" value="Ada Lovelace" style="min-width: 220px;"></md-text-field>
<md-text-field label="With error" value="not-an-email" error error-text="Enter a valid email" style="min-width: 220px;"></md-text-field>
</template><script>
import '@awc-ui/core/define';
</script>
<md-text-field label="Outlined" value="Ada Lovelace" style="min-width: 220px;"></md-text-field>
<md-text-field variant="filled" label="Filled" value="Ada Lovelace" style="min-width: 220px;"></md-text-field>
<md-text-field label="With error" value="not-an-email" error error-text="Enter a valid email" style="min-width: 220px;"></md-text-field>CSS Parts — container (the field box), input (the native <input> /
<textarea>), label (the floating label), chips (the slotted chip region a
composite fills), supporting-text (the message line) and counter (the
character counter). The icons are slots, not parts — style them from your
own light-DOM CSS.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<style>
.parts-tf::part(container) { border-radius: 4px; }
.parts-tf::part(label) { text-transform: uppercase; letter-spacing: .08em; font-size: 11px; }
.parts-tf::part(supporting-text) { font-style: italic; }
.parts-tf::part(counter) { font-weight: 700; }
</style>
<md-text-field class="parts-tf" label="Styled parts" value="Ada Lovelace" max-length="40" supporting-text="Styled supporting text" style="--md-text-field-label-color: var(--md-sys-color-primary); min-width: 260px;"></md-text-field>import { MdTextField } from '@awc-ui/react';
export function Demo() {
return (
<>
<style>
.parts-tf::part(container) { border-radius: 4px; }
.parts-tf::part(label) { text-transform: uppercase; letter-spacing: .08em; font-size: 11px; }
.parts-tf::part(supporting-text) { font-style: italic; }
.parts-tf::part(counter) { font-weight: 700; }
</style>
<MdTextField className="parts-tf" label="Styled parts" value="Ada Lovelace" maxLength="40" supportingText="Styled supporting text" style={{ '--md-text-field-label-color': 'var(--md-sys-color-primary)', minWidth: '260px' }}></MdTextField>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<style>
.parts-tf::part(container) { border-radius: 4px; }
.parts-tf::part(label) { text-transform: uppercase; letter-spacing: .08em; font-size: 11px; }
.parts-tf::part(supporting-text) { font-style: italic; }
.parts-tf::part(counter) { font-weight: 700; }
</style>
<md-text-field class="parts-tf" label="Styled parts" value="Ada Lovelace" max-length="40" supporting-text="Styled supporting text" style="--md-text-field-label-color: var(--md-sys-color-primary); min-width: 260px;"></md-text-field><script setup>
import '@awc-ui/core/define';
</script>
<template>
<style>
.parts-tf::part(container) { border-radius: 4px; }
.parts-tf::part(label) { text-transform: uppercase; letter-spacing: .08em; font-size: 11px; }
.parts-tf::part(supporting-text) { font-style: italic; }
.parts-tf::part(counter) { font-weight: 700; }
</style>
<md-text-field class="parts-tf" label="Styled parts" value="Ada Lovelace" max-length="40" supporting-text="Styled supporting text" style="--md-text-field-label-color: var(--md-sys-color-primary); min-width: 260px;"></md-text-field>
</template><script>
import '@awc-ui/core/define';
</script>
<style>
.parts-tf::part(container) { border-radius: 4px; }
.parts-tf::part(label) { text-transform: uppercase; letter-spacing: .08em; font-size: 11px; }
.parts-tf::part(supporting-text) { font-style: italic; }
.parts-tf::part(counter) { font-weight: 700; }
</style>
<md-text-field class="parts-tf" label="Styled parts" value="Ada Lovelace" max-length="40" supporting-text="Styled supporting text" style="--md-text-field-label-color: var(--md-sys-color-primary); min-width: 260px;"></md-text-field>md-text-field::part(container) { border-radius: 4px; }md-text-field::part(supporting-text) { font-style: italic; }md-autocomplete ·
md-search ·
md-select ·
md-multi-select ·
md-date-picker ·
md-time-picker ·
md-color-picker ·
md-icon-button
md-text-fieldTwo artefacts to give your AI agent so it generates correct UI with this component. The per-component spec answers "how do I use this exact tag?". The main-llm spec answers "which tag should I pick in the first place?".
md-text-field spec card
Identity · when to use / when NOT · decision cues · behavioural contract · do/don't · anti-patterns · full API. Paste into your agent when you're implementing with this component.
System-prompt preamble · decision matrix · token reference · page recipes · anti-patterns. Paste into the system prompt at the start of a piece of work.