TextFieldUpdated
A text input component with label, description, and error handling for collecting user input.
Import
import { TextField } from 'heroui-native';Anatomy
<TextField>
<TextField.Label>...</TextField.Label>
<TextField.Input />
<TextField.Description>...</TextField.Description>
<TextField.ErrorMessage>...</TextField.ErrorMessage>
</TextField>- TextField: Root container that provides spacing and state management
- TextField.Label: Label with optional asterisk for required fields
- TextField.Input: Input container with animated border and background
- TextField.Description: Helper text displayed below the input
- TextField.ErrorMessage: Error message shown when field is invalid
Usage
Basic Usage
TextField provides a complete form input structure with label and description.
<TextField>
<TextField.Label>Email</TextField.Label>
<TextField.Input placeholder="Enter your email" />
<TextField.Description>We'll never share your email</TextField.Description>
</TextField>With Required Field
Mark fields as required to show an asterisk in the label.
<TextField isRequired>
<TextField.Label>Username</TextField.Label>
<TextField.Input placeholder="Choose a username" />
</TextField>With Validation
Display error messages when the field is invalid.
<TextField isRequired isInvalid={true}>
<TextField.Label>Email</TextField.Label>
<TextField.Input placeholder="Enter your email" />
<TextField.ErrorMessage>Please enter a valid email</TextField.ErrorMessage>
</TextField>With Local Invalid State Override
Override the context's invalid state for individual components.
<TextField isInvalid={true}>
<TextField.Label isInvalid={false}>Email</TextField.Label>
<TextField.Input placeholder="Enter your email" isInvalid={false} />
<TextField.Description>
This shows despite input being invalid
</TextField.Description>
<TextField.ErrorMessage>Email format is incorrect</TextField.ErrorMessage>
</TextField>Multiline Input
Create text areas for longer content.
<TextField>
<TextField.Label>Message</TextField.Label>
<TextField.Input
placeholder="Type your message..."
multiline
numberOfLines={4}
/>
<TextField.Description>Maximum 500 characters</TextField.Description>
</TextField>Disabled State
Disable the entire field to prevent interaction.
<TextField isDisabled>
<TextField.Label>Disabled Field</TextField.Label>
<TextField.Input placeholder="Cannot edit" value="Read only value" />
</TextField>With Variant
Use different variants to style the input based on context.
<TextField>
<TextField.Label>Primary Variant</TextField.Label>
<TextField.Input placeholder="Primary style" variant="primary" />
</TextField>
<TextField>
<TextField.Label>Secondary Variant</TextField.Label>
<TextField.Input placeholder="Secondary style" variant="secondary" />
</TextField>Custom Styling
Customize the input appearance using className.
<TextField>
<TextField.Label>Custom Styled</TextField.Label>
<TextField.Input
placeholder="Custom colors"
className="bg-blue-50 border-blue-500 focus:border-blue-700"
/>
</TextField>Example
import { Ionicons } from '@expo/vector-icons';
import { 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>
<TextField.Label>Email</TextField.Label>
<TextField.Input
placeholder="Enter your email"
keyboardType="email-address"
autoCapitalize="none"
value={email}
onChangeText={setEmail}
/>
<TextField.Description>
We'll never share your email with anyone else.
</TextField.Description>
</TextField>
<TextField isRequired>
<TextField.Label>New password</TextField.Label>
<View className="w-full flex-row items-center">
<TextField.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>
<TextField.Description>
Password must be at least 6 characters
</TextField.Description>
</TextField>
</View>
);
};You can find more examples in the GitHub repository.
API Reference
TextField
| prop | type | default | description |
|---|---|---|---|
| children | React.ReactNode | - | Content to render inside the text field |
| isDisabled | boolean | false | Whether the entire text field is disabled |
| isInvalid | boolean | false | Whether the text field is in an invalid state |
| isRequired | boolean | false | Whether the text field is required (shows asterisk) |
| className | string | - | Custom class name for the root element |
| animation | "disable-all" | undefined | undefined | Animation configuration. Use "disable-all" to disable all animations including children |
| ...ViewProps | ViewProps | - | All standard React Native View props are supported |
TextField.Label
| prop | type | default | description |
|---|---|---|---|
| children | React.ReactNode | - | Label text content |
| isInvalid | boolean | undefined | Whether the label is in an invalid state (overrides context) |
| className | string | - | Custom class name for the label element |
| classNames | ElementSlots<LabelSlots> | - | Custom class names for different parts of the label |
| animation | TextFieldLabelAnimation | - | Animation configuration |
| ...Animated.TextProps | AnimatedProps<TextProps> | - | All Reanimated Animated.Text props are supported |
ElementSlots<LabelSlots>
| prop | type | description |
|---|---|---|
| text | string | Custom class name for the label text |
| asterisk | string | Custom class name for the asterisk |
TextFieldLabelAnimation
Animation configuration for TextField.Label component. Can be:
falseor"disabled": Disable all animationstrueorundefined: Use default animationsobject: Custom animation configuration
| prop | type | default | description |
|---|---|---|---|
state | 'disabled' | boolean | - | Disable animations while customizing properties |
entering.value | EntryOrExitLayoutType | FadeIn.duration(150).easing(Easing.out(Easing.ease)) | Custom entering animation |
exiting.value | EntryOrExitLayoutType | FadeOut.duration(150).easing(Easing.out(Easing.ease)) | Custom exiting animation |
TextField.Input
| prop | type | default | description |
|---|---|---|---|
| isInvalid | boolean | undefined | Whether the input is in an invalid state (overrides context) |
| variant | 'primary' | 'secondary' | 'primary' | Variant style for the input |
| className | string | - | Custom class name for the input |
| selectionColorClassName | string | "accent-accent" | Custom className for the selection color |
| placeholderColorClassName | string | "field-placeholder" | Custom className for the placeholder text color |
| ...TextInputProps | TextInputProps | - | All standard React Native TextInput props are supported |
TextField.Description
| prop | type | default | description |
|---|---|---|---|
| children | React.ReactNode | - | Description text content |
| isInvalid | boolean | undefined | Whether the description is in an invalid state (overrides context) |
| className | string | - | Custom class name for the description element |
| animation | TextFieldDescriptionAnimation | - | Animation configuration |
| ...Animated.TextProps | AnimatedProps<TextProps> | - | All Reanimated Animated.Text props are supported |
TextFieldDescriptionAnimation
Animation configuration for TextField.Description component. Can be:
falseor"disabled": Disable all animationstrueorundefined: Use default animationsobject: Custom animation configuration
| prop | type | default | description |
|---|---|---|---|
state | 'disabled' | boolean | - | Disable animations while customizing properties |
entering.value | EntryOrExitLayoutType | FadeIn.duration(150).easing(Easing.out(Easing.ease)) | Custom entering animation |
exiting.value | EntryOrExitLayoutType | FadeOut.duration(150).easing(Easing.out(Easing.ease)) | Custom exiting animation |
TextField.ErrorMessage
Note:
TextField.ErrorMessageextendsErrorViewcomponent. For complete API reference, see ErrorView documentation.
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
| property | type | description |
|---|---|---|
| isDisabled | boolean | Whether the entire text field is disabled |
| isInvalid | boolean | Whether the text field is in an invalid state |
| isRequired | boolean | Whether the text field is required |