Overview
The TextField component provides a complete text input solution with integrated label, input field, and helper text. It’s a higher-level wrapper around the Input component with additional features for common use cases.
import { TextField } from '@naturacosmeticos/natds-react'
Basic Usage
import React, { useState } from 'react'
import { TextField } from '@naturacosmeticos/natds-react'
function App() {
const [value, setValue] = useState('')
return (
<TextField
id="username"
label="Username"
placeholder="Enter your username"
helperText="Choose a unique username"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
)
}
Input Types
TextField supports different input types:
// Text Input
<TextField
id="email"
label="Email"
type="text"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
// Password Input
<TextField
id="password"
label="Password"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
// Multiline (Textarea)
<TextField
id="description"
label="Description"
type="multiline"
minRows={4}
value={description}
onChange={(e) => setDescription(e.target.value)}
/>
<TextField
id="medium-field"
label="Medium Size"
size="medium"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
<TextField
id="mediumx-field"
label="Medium X Size (Default)"
size="mediumX"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
Feedback States
Provide visual feedback for validation:
// Error State
<TextField
id="email-error"
label="Email"
feedback="error"
helperText="Please enter a valid email address"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
// Success State
<TextField
id="email-success"
label="Email"
feedback="success"
helperText="Email is valid"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
Required Field
<TextField
id="required-field"
label="Full Name"
required
helperText="This field is required"
value={name}
onChange={(e) => setName(e.target.value)}
/>
Read Only
<TextField
id="readonly-field"
label="User ID"
readOnly
value="USER-12345"
onChange={() => {}}
/>
Disabled
<TextField
id="disabled-field"
label="Inactive Field"
disabled
value="Cannot edit"
onChange={() => {}}
/>
With Icons
Icon Leading
import { Icon } from '@naturacosmeticos/natds-react'
<TextField
id="search"
label="Search"
iconLeading={<Icon name="outlined-action-search" color="highEmphasis" />}
value={search}
onChange={(e) => setSearch(e.target.value)}
/>
Action Icon
<TextField
id="password-toggle"
label="Password"
type={showPassword ? 'text' : 'password'}
action="icon"
IconComponent={<Icon name="outlined-action-visibility" color="highEmphasis" />}
ariaLabel="Toggle password visibility"
onClick={() => setShowPassword(!showPassword)}
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
Action Image
<TextField
id="profile-input"
label="Profile"
action="image"
src="/avatar.png"
alt="User avatar"
value={profile}
onChange={(e) => setProfile(e.target.value)}
/>
Multiline with Resize
<TextField
id="notes"
label="Notes"
type="multiline"
minRows={5}
isResizable
placeholder="Enter your notes here..."
value={notes}
onChange={(e) => setNotes(e.target.value)}
/>
The id of the input element, shared with the label
Text that appears above the input field
The current value of the input field
onChange
React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement>
Callback fired when the value changes
type
'text' | 'password' | 'multiline'
default:"text"
The type of input field
size
'medium' | 'mediumX'
default:"mediumX"
The height of the input field
Hint text displayed when the field is empty
Assistive text displayed below the input
Visual feedback state for validation
If true, displays an asterisk and marks the field as required
If true, the field cannot be interacted with
If true, the value cannot be changed but can be selected
Minimum number of rows for multiline input
If true, allows user to resize multiline input
Icon displayed at the start of the input
Type of action element to display inside the input
Icon component for action. Required when action="icon"
Accessibility label for the action icon button
Click handler for action icon. Required when action="icon"
Image source URL. Required when action="image"
Alternative text for image. Required when action="image"
Brand theme to apply (avon, natura, theBodyShop, etc.)
Callback fired when the field loses focus
Callback fired when the field gains focus
onKeyDown
React.KeyboardEventHandler
Callback fired when a key is pressed down
onKeyUp
React.KeyboardEventHandler
Callback fired when a key is released
Accessibility attributes including:
aria-label
aria-labelledby
aria-describedby
aria-required
aria-invalid
aria-disabled
aria-autocomplete
tabIndex
Accessibility
Labels and Descriptions
<TextField
id="email-input"
label="Email Address"
helperText="We'll never share your email"
accessibility={{
'aria-describedby': 'email-helper',
'aria-required': true,
'aria-invalid': hasError
}}
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
Best Practices
- Always provide a
label for the field
- Use
helperText to provide additional context
- Set
required prop for mandatory fields
- Use
feedback prop to indicate validation states
- Provide clear error messages in
helperText
- Ensure sufficient color contrast for all states
- Use appropriate
type for different input purposes
Form Integration
import React, { useState } from 'react'
import { TextField } from '@naturacosmeticos/natds-react'
function ContactForm() {
const [formData, setFormData] = useState({
name: '',
email: '',
message: ''
})
const [errors, setErrors] = useState<Record<string, string>>({})
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault()
// Validation logic
}
return (
<form onSubmit={handleSubmit}>
<TextField
id="name"
label="Full Name"
required
value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
feedback={errors.name ? 'error' : undefined}
helperText={errors.name || 'Enter your full name'}
/>
<TextField
id="email"
label="Email"
required
type="text"
value={formData.email}
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
feedback={errors.email ? 'error' : undefined}
helperText={errors.email || 'We will send confirmation to this email'}
/>
<TextField
id="message"
label="Message"
type="multiline"
minRows={5}
value={formData.message}
onChange={(e) => setFormData({ ...formData, message: e.target.value })}
helperText="Tell us what you need help with"
/>
<button type="submit">Submit</button>
</form>
)
}
TypeScript
import { TextFieldProps } from '@naturacosmeticos/natds-react'
interface FormFieldProps {
fieldId: string
fieldLabel: string
value: string
onValueChange: (value: string) => void
error?: string
}
const FormField: React.FC<FormFieldProps> = ({
fieldId,
fieldLabel,
value,
onValueChange,
error
}) => {
return (
<TextField
id={fieldId}
label={fieldLabel}
value={value}
onChange={(e) => onValueChange(e.target.value)}
feedback={error ? 'error' : undefined}
helperText={error}
/>
)
}
Related Components