Skip to main content

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

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)}
/>

Sizes

<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)}
/>

States

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)}
/>

Props

id
string
required
The id of the input element, shared with the label
label
string
Text that appears above the input field
value
string
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
placeholder
string
Hint text displayed when the field is empty
helperText
string
Assistive text displayed below the input
feedback
'success' | 'error'
Visual feedback state for validation
required
boolean
default:"false"
If true, displays an asterisk and marks the field as required
disabled
boolean
default:"false"
If true, the field cannot be interacted with
readOnly
boolean
default:"false"
If true, the value cannot be changed but can be selected
minRows
number
default:"3"
Minimum number of rows for multiline input
isResizable
boolean
default:"false"
If true, allows user to resize multiline input
iconLeading
React.ReactElement
Icon displayed at the start of the input
action
'icon' | 'image'
Type of action element to display inside the input
IconComponent
React.ReactElement
Icon component for action. Required when action="icon"
ariaLabel
string
Accessibility label for the action icon button
onClick
() => void
Click handler for action icon. Required when action="icon"
src
string
Image source URL. Required when action="image"
alt
string
Alternative text for image. Required when action="image"
brand
BrandTypes
Brand theme to apply (avon, natura, theBodyShop, etc.)
className
string
Optional CSS class name
testID
string
Optional ID for testing
onBlur
React.FocusEventHandler
Callback fired when the field loses focus
onFocus
React.FocusEventHandler
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
InputAccessibilityProps
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}
    />
  )
}

Build docs developers (and LLMs) love