Text Field
Text fields let users enter and edit text. MD3 Expressive Text Fields feature smooth floating label animation, animated active indicator lines, and a notch effect for the outlined variant.
Text fields are one of the most common UI elements in forms. The MD3 Expressive TextField features fluid Framer Motion animations for the floating label, active indicator, and outlined notch — all respecting prefers-reduced-motion.
Introduction
The MD3 Expressive Text Field is designed for clarity and ease of use. It supports two primary visual variants (Filled and Outlined) and a range of interactive features like prefix/suffix text, leading/trailing icons, and adaptive multi-line support. The expressive nature comes from the smooth transitions between focus states and the fluid motion of the label and indicator elements.
Anatomy
- Container: The outer wrapper providing the background (Filled) or border (Outlined).
- Leading Icon (Optional): A visual indicator at the start of the field (e.g., Search, Email icon).
- Floating Label: Moves from the center of the input to the top when the field is focused or has content.
- Input Area: Where the user enters text.
- Trailing Icon (Optional): For actions like clearing the input, toggling password visibility, or custom actions.
- Active Indicator: A bottom line (Filled) or a highlighted border (Outlined) that animates on focus.
- Supporting Text: Helper or error text displayed below the field.
- Character Counter (Optional): Tracks the length of the input against a maximum limit.
Variants
Filled (Default)
The filled variant features a background color and a bottom indicator line. It is high emphasis and works well on surfaces where the input needs to stand out.
Outlined
The outlined variant features a border around the entire input. It is medium emphasis and often used for denser forms or when multiple fields are placed together.
Features
States
TextFields support various functional states:
- Focus: Label floats and indicator animates.
- Error: Turns all elements to the error color roles.
- Disabled: Mutes the UI and prevents interaction.
- Read Only: Allows selection but prevents editing.
Icons & Actions
The trailingIconMode prop provides built-in behaviors for common patterns:
- Clear: Shows a ✕ button when there is text.
- Password Toggle: Toggles visibility for password fields.
- Custom: Allows passing a custom ReactNode to the
trailingIconprop.
Adaptive Multi-line (Auto-resize)
Use type="textarea" and autoResize={true} to allow the field to grow vertically as the user types. Use maxRows to limit this growth.
Usage
Basic Usage
import { TextField } from "@bug-on/m3-expressive";
<TextField label="Username" />
Password with Toggle
<TextField
label="Password"
type="password"
trailingIconMode="password-toggle"
/>
With Supporting Text & Counter
<TextField
label="Biography"
maxLength={140}
supportingText="Tell us about yourself"
/>
Best Practices
Do
- Use Filled for primary forms and Outlined for secondary or dense layouts.
- Provide clear, concise labels that remain visible even after the user starts typing.
- Use
supportingTextto explain requirements (e.g., "Must be at least 8 characters"). - Group related fields together with consistent spacing.
Don't
- Don't use placeholders as a replacement for labels.
- Don't use too many icons that might clutter the input area.
- Avoid long labels that might be truncated on small screens.
Design Tokens
| Size | Height (Default) | Height (Dense) | Label Size (Small) |
|---|---|---|---|
| Height | 56dp | 48dp | 12dp |
| Padding | 16dp | 12dp | — |
Accessibility
- Keyboard: Full support for standard input keys.
Tabto focus,Enterto submit (if in a form). - ARIA: Automatically links labels via
htmlForand supporting text viaaria-describedby. - Validation: Sets
aria-invalidandaria-requiredbased on state. - Interactive Icons: All icon buttons have a minimum 48x48dp touch target.
- Motion: Respects
prefers-reduced-motionsettings.
API Reference
TextField
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "filled" | "outlined" | "filled" | Visual variant. |
label | string | — | Floating label text. |
value | string | — | Controlled value. |
defaultValue | string | "" | Initial value. |
onChange | (value, event) => void | — | Callback fired on change. |
type | string | "text" | Input type (includes "textarea"). |
placeholder | string | — | Shown when label is floated. |
error | boolean | false | Forces error visual state. |
errorText | string | — | Error message below the field. |
supportingText | string | — | Helper text below the field. |
maxLength | number | — | Max characters; enables counter. |
required | boolean | false | Marks field as required. |
leadingIcon | ReactNode | — | Icon at the start. |
trailingIconMode | "none" | "clear" | "password-toggle" | "custom" | "none" | Built-in icon behaviors. |
prefixText | string | — | Text prefix (e.g., "$"). |
suffixText | string | — | Text suffix (e.g., ".00"). |
dense | boolean | false | Reduces height to 48px. |
autoResize | boolean | false | Textarea expands with content. |
maxRows | number | — | Max height for autoResize. |
fullWidth | boolean | true | Fills container width. |
TextFieldHandle (Imperative)
Accessible via ref.
| Method | Description |
|---|---|
focus() | Focuses the input. |
clear() | Clears the value. |
getValue() | Returns current value string. |
reportValidity() | Shows native validation UI. |