Textfield
A text input supporting multiple types (text, email, password, multiline), validation variants, icons, and helper text. Password type includes an automatic visibility toggle.
Playground
Usage
<lt-textfield label="Email" type="email" placeholder="you@example.com" required></lt-textfield>
<lt-textfield
label="Password"
type="password"
helper-text="Minimum 8 characters"></lt-textfield>
<lt-textfield
label="Bio"
type="multiline"
placeholder="Tell us about yourself..."></lt-textfield>
<!-- Clear button, and a character count against the native max length -->
<lt-textfield label="Nickname" clearable counter max="20"></lt-textfield>
import { Textfield } from '@latty-ds/react';
<Textfield label="Email" type="email" placeholder="you@example.com" required />
<Textfield label="Password" type="password" helperText="Minimum 8 characters" />
<Textfield label="Bio" type="multiline" placeholder="Tell us about yourself..." />
// Clear button, and a character count against the native max length
<Textfield label="Nickname" clearable counter max={20} />
<template>
<lt-textfield label="Email" type="email" placeholder="you@example.com" required></lt-textfield>
<lt-textfield
label="Password"
type="password"
helper-text="Minimum 8 characters"></lt-textfield>
<lt-textfield
label="Bio"
type="multiline"
placeholder="Tell us about yourself..."></lt-textfield>
</template>
Validation
Validation runs automatically on blur — after the user leaves the field for the first time. Once touched, the field
re-validates on every keystroke so errors clear as soon as the value becomes valid. No extra wiring required; just
set the right type.
Format validation
Fields with type="email", type="url", or type="tel" check the value against their
respective format rules. An invalid value triggers the error state (red border + xmark icon) automatically.
<lt-textfield
type="email"
label="Email"
placeholder="you@example.com"
helper-text="Enter a valid email address"></lt-textfield>
<lt-textfield
type="url"
label="Website"
placeholder="https://example.com"
helper-text="Must start with http:// or https://"></lt-textfield>
<lt-textfield
type="tel"
label="Phone"
placeholder="+1 (555) 000-1234"
helper-text="Include country code for international numbers"></lt-textfield>
import { Textfield } from '@latty-ds/react';
<Textfield type="email" label="Email" placeholder="you@example.com" helperText="Enter a valid email address" />
<Textfield
type="url"
label="Website"
placeholder="https://example.com"
helperText="Must start with http:// or https://"
/>
<Textfield
type="tel"
label="Phone"
placeholder="+1 (555) 000-1234"
helperText="Include country code for international numbers"
/>
<template>
<lt-textfield
type="email"
label="Email"
placeholder="you@example.com"
helper-text="Enter a valid email address"></lt-textfield>
<lt-textfield
type="url"
label="Website"
placeholder="https://example.com"
helper-text="Must start with http:// or https://"></lt-textfield>
<lt-textfield
type="tel"
label="Phone"
placeholder="+1 (555) 000-1234"
helper-text="Include country code for international numbers"></lt-textfield>
</template>
Length and range bounds
The min and max props set bounds that are also checked on blur. For
type="number" they constrain the numeric value; for all other types they constrain the character length.
Both are passed through as native min/max or
minlength/maxlength attributes so the browser's built-in tooltip also works.
<!-- Character length: must be 8–64 chars -->
<lt-textfield
type="text"
label="Username"
min="8"
max="64"
helper-text="8–64 characters"></lt-textfield>
<!-- Numeric range: 0–120 -->
<lt-textfield
type="number"
label="Age"
min="0"
max="120"
helper-text="Enter your age"></lt-textfield>
import { Textfield } from '@latty-ds/react';
{/* Character length: must be 8–64 chars */}
<Textfield type="text" label="Username" min={8} max={64} helperText="8–64 characters" />
{/* Numeric range: 0–120 */}
<Textfield
type="number"
label="Age"
min={0}
max={120}
helperText="Enter your age"
/>
<template>
<!-- Character length: must be 8–64 chars -->
<lt-textfield
type="text"
label="Username"
:min="8"
:max="64"
helper-text="8–64 characters"></lt-textfield>
<!-- Numeric range: 0–120 -->
<lt-textfield
type="number"
label="Age"
:min="0"
:max="120"
helper-text="Enter your age"></lt-textfield>
</template>
Dynamic helper text
Pass a function to helper-text to show a different message depending on whether the field is in an error
state. The function receives a single boolean — true when the field is invalid — and must return a string.
This is set as a JavaScript property, not an HTML attribute.
<lt-textfield type="email" label="Email" id="email-field"></lt-textfield>
<script type="module">
import '@latty-ds/web';
document.querySelector('#email-field').helperText =
(error) => error ? 'Enter a valid email address' : "We'll never share your email";
</script>
<!-- Password with length hint that turns into an error message -->
<lt-textfield type="text" label="Password" id="pw-field"></lt-textfield>
<script type="module">
import '@latty-ds/web';
document.querySelector('#pw-field').helperText =
(error) => error ? 'Password is too short' : 'Minimum 8 characters';
document.querySelector('#pw-field').min = 8;
</script>
import { Textfield } from '@latty-ds/react';
<Textfield
type="email"
label="Email"
helperText={(error) => (error ? 'Enter a valid email address' : "We'll never share your email")}
/>
{/* Password with length hint that turns into an error message */}
<Textfield
type="text"
label="Password"
min={8}
helperText={(error) => error ? 'Password is too short' : 'Minimum 8 characters'}
/>
<template>
<lt-textfield
type="email"
label="Email"
:helper-text="(error) => error ? 'Enter a valid email address' : 'We\'ll never share your email'"></lt-textfield>
<!-- Password with length hint that turns into an error message -->
<lt-textfield
type="text"
label="Password"
:min="8"
:helper-text="(error) => error ? 'Password is too short' : 'Minimum 8 characters'"></lt-textfield>
</template>