TextFieldUpdated

A text input component with label, description, and error handling for collecting user input.

Import

import { TextField } from 'heroui-native';

Anatomy

<TextField>
  <Label>...</Label>
  <Input />
  <Description>...</Description>
  <FieldError>...</FieldError>
</TextField>
  • TextField: Root container that provides spacing and state management
  • Label: Label with optional asterisk for required fields (from Label component)
  • Input: Input container with animated border and background (from Input component)
  • Description: Secondary descriptive helper text (from Description component)
  • FieldError: Validation error message display (from FieldError component)

Usage

Basic Usage

TextField provides a complete form input structure with label and description.

<TextField>
  <Label>Email</Label>
  <Input placeholder="Enter your email" />
  <Description>We'll never share your email</Description>
</TextField>

With Required Field

Mark fields as required to show an asterisk in the label.

<TextField isRequired>
  <Label>Username</Label>
  <Input placeholder="Choose a username" />
</TextField>

With Validation

Display error messages when the field is invalid.

import { FieldError, Input, Label, TextField } from 'heroui-native';

<TextField isRequired isInvalid={true}>
  <Label>Email</Label>
  <Input placeholder="Enter your email" />
  <FieldError>Please enter a valid email</FieldError>
</TextField>

With Local Invalid State Override

Override the context's invalid state for individual components.

import { Description, FieldError, Input, Label, TextField } from 'heroui-native';

<TextField isInvalid={true}>
  <Label isInvalid={false}>Email</Label>
  <Input placeholder="Enter your email" isInvalid={false} />
  <Description isInvalid={false}>
    This shows despite input being invalid
  </Description>
  <FieldError>Email format is incorrect</FieldError>
</TextField>

Multiline Input

Create text areas for longer content.

<TextField>
  <Label>Message</Label>
  <Input
    placeholder="Type your message..."
    multiline
    numberOfLines={4}
  />
  <Description>Maximum 500 characters</Description>
</TextField>

Disabled State

Disable the entire field to prevent interaction.

<TextField isDisabled>
  <Label>Disabled Field</Label>
  <Input placeholder="Cannot edit" value="Read only value" />
</TextField>

With Variant

Use different variants to style the input based on context.

<TextField>
  <Label>Primary Variant</Label>
  <Input placeholder="Primary style" variant="primary" />
</TextField>

<TextField>
  <Label>Secondary Variant</Label>
  <Input placeholder="Secondary style" variant="secondary" />
</TextField>

Custom Styling

Customize the input appearance using className.

<TextField>
  <Label>Custom Styled</Label>
  <Input
    placeholder="Custom colors"
    className="bg-blue-50 border-blue-500 focus:border-blue-700"
  />
</TextField>

Example

import { Ionicons } from '@expo/vector-icons';
import { Description, Input, Label, TextField } from 'heroui-native';
import { useState } from 'react';
import { Pressable, View } from 'react-native';
import { withUniwind } from 'uniwind';

const StyledIonicons = withUniwind(Ionicons);

export const TextInputContent = () => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [isPasswordVisible, setIsPasswordVisible] = useState(false);

  return (
    <View className="gap-4">
      <TextField isRequired>
        <Label>Email</Label>
        <Input
          placeholder="Enter your email"
          keyboardType="email-address"
          autoCapitalize="none"
          value={email}
          onChangeText={setEmail}
        />
        <Description>
          We'll never share your email with anyone else.
        </Description>
      </TextField>

      <TextField isRequired>
        <Label>New password</Label>
        <View className="w-full flex-row items-center">
          <Input
            value={password}
            onChangeText={setPassword}
            className="flex-1 px-10"
            placeholder="Enter your password"
            secureTextEntry={!isPasswordVisible}
          />
          <StyledIonicons
            name="lock-closed-outline"
            size={16}
            className="absolute left-3.5 text-muted"
            pointerEvents="none"
          />
          <Pressable
            className="absolute right-4"
            onPress={() => setIsPasswordVisible(!isPasswordVisible)}
          >
            <StyledIonicons
              name={isPasswordVisible ? 'eye-off-outline' : 'eye-outline'}
              size={16}
              className="text-muted"
            />
          </Pressable>
        </View>
        <Description>
          Password must be at least 6 characters
        </Description>
      </TextField>
    </View>
  );
};

You can find more examples in the GitHub repository.

API Reference

TextField

proptypedefaultdescription
childrenReact.ReactNode-Content to render inside the text field
isDisabledbooleanfalseWhether the entire text field is disabled
isInvalidbooleanfalseWhether the text field is in an invalid state
isRequiredbooleanfalseWhether the text field is required (shows asterisk)
classNamestring-Custom class name for the root element
animation"disable-all" | undefinedundefinedAnimation configuration. Use "disable-all" to disable all animations including children
...ViewPropsViewProps-All standard React Native View props are supported

Note: For Label, Input, Description, and FieldError components, see their respective documentation:

These components automatically consume form state from TextField via the form-item-state context.

Hooks

useTextField

Hook to access the TextField context values. Must be used within a TextField component.

import { TextField, useTextField } from 'heroui-native';

function CustomComponent() {
  const { isDisabled, isInvalid, isRequired } = useTextField();

  // Use the context values...
}

Returns

propertytypedescription
isDisabledbooleanWhether the entire text field is disabled
isInvalidbooleanWhether the text field is in an invalid state
isRequiredbooleanWhether the text field is required

On this page