Input
The Input component provides a flexible text input with support for labels, hints, icons, password fields, and various input types. It includes built-in validation states and accessibility features.
Import
Section titled “Import”import { Input, type InputRef } from '@space-uy/pulsar-ui';Basic usage
Section titled “Basic usage”const [value, setValue] = useState('');
<Input  label="Email"  placeholder="Enter your email"  value={value}  onChangeText={setValue}/>;Properties
Section titled “Properties”| Property | Type | Required | Default value | Description | 
|---|---|---|---|---|
| label | string | ❌ | - | Label text displayed above the input | 
| placeholder | string | ❌ | - | Placeholder text when input is empty | 
| value | string | ❌ | - | Current input value | 
| onChangeText | (text: string) => void | ❌ | - | Callback when input text changes | 
| error | boolean | ❌ | false | Whether the input is in error state | 
| hint | string | ❌ | - | Hint text displayed below the input | 
| iconName | IconName | ❌ | - | Icon displayed on the left side | 
| variant | 'text' | 'password' | ❌ | 'text' | Input variant (text or password) | 
| clearable | boolean | ❌ | false | Whether to show clear button when has content | 
| editable | boolean | ❌ | true | Whether the input is editable | 
| style | StyleProp<ViewStyle> | ❌ | - | Custom styles for the input container | 
| ...rest | TextInputProps | ❌ | - | Additional TextInput props | 
InputRef Methods
Section titled “InputRef Methods”When using a ref, the following methods are available:
| Method | Type | Description | 
|---|---|---|
| focus | () => void | Focus the input | 
| blur | () => void | Remove focus from input | 
Basic examples
Section titled “Basic examples”Simple text input
Section titled “Simple text input”const [email, setEmail] = useState('');
<Input  label="Email"  placeholder="Enter your email address"  value={email}  onChangeText={setEmail}/>;Password input
Section titled “Password input”const [password, setPassword] = useState('');
<Input  label="Password"  placeholder="Enter your password"  variant="password"  value={password}  onChangeText={setPassword}/>;Input with icon
Section titled “Input with icon”<Input  label="Search"  placeholder="Search for items..."  iconName="Search"  value={searchQuery}  onChangeText={setSearchQuery}/>Clearable input
Section titled “Clearable input”<Input  label="Username"  placeholder="Choose a username"  clearable={true}  value={username}  onChangeText={setUsername}/>Advanced examples
Section titled “Advanced examples”Form with validation
Section titled “Form with validation”const [formData, setFormData] = useState({  email: '',  password: '',  confirmPassword: '',});const [errors, setErrors] = useState<Record<string, boolean>>({});
const validateEmail = (email: string) => {  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);};
const handleEmailChange = (email: string) => {  setFormData((prev) => ({ ...prev, email }));  setErrors((prev) => ({ ...prev, email: !validateEmail(email) }));};
<View style={{ gap: 16 }}>  <Input    label="Email"    placeholder="Enter your email"    value={formData.email}    onChangeText={handleEmailChange}    error={errors.email}    hint={      errors.email        ? 'Please enter a valid email address'        : "We'll never share your email"    }    iconName="Mail"    keyboardType="email-address"    autoCapitalize="none"  />
  <Input    label="Password"    placeholder="Create a password"    variant="password"    value={formData.password}    onChangeText={(password) => setFormData((prev) => ({ ...prev, password }))}    error={formData.password.length > 0 && formData.password.length < 8}    hint="Password must be at least 8 characters"  />
  <Input    label="Confirm Password"    placeholder="Confirm your password"    variant="password"    value={formData.confirmPassword}    onChangeText={(confirmPassword) =>      setFormData((prev) => ({ ...prev, confirmPassword }))    }    error={      formData.confirmPassword !== formData.password &&      formData.confirmPassword.length > 0    }    hint={      formData.confirmPassword !== formData.password        ? 'Passwords do not match'        : ''    }  /></View>;Different input types
Section titled “Different input types”<View style={{ gap: 16 }}>  <Input    label="Phone Number"    placeholder="+1 (555) 123-4567"    iconName="Phone"    keyboardType="phone-pad"    value={phone}    onChangeText={setPhone}  />
  <Input    label="Age"    placeholder="Enter your age"    iconName="User"    keyboardType="numeric"    value={age}    onChangeText={setAge}  />
  <Input    label="Website"    placeholder="https://example.com"    iconName="Globe"    keyboardType="url"    autoCapitalize="none"    value={website}    onChangeText={setWebsite}  /></View>Controlled input with ref
Section titled “Controlled input with ref”const inputRef = useRef<InputRef>(null);
const handleFocusInput = () => {  inputRef.current?.focus();};
<View style={{ gap: 16 }}>  <Button text="Focus Input" onPress={handleFocusInput} />  <Input    ref={inputRef}    label="Focused Input"    placeholder="This input can be focused programmatically"    value={value}    onChangeText={setValue}  /></View>;Search input with actions
Section titled “Search input with actions”const [searchQuery, setSearchQuery] = useState('');const [isSearching, setIsSearching] = useState(false);
const handleSearch = async () => {  setIsSearching(true);  try {    await performSearch(searchQuery);  } finally {    setIsSearching(false);  }};
<View style={{ flexDirection: 'row', gap: 12, alignItems: 'flex-end' }}>  <Input    style={{ flex: 1 }}    label="Search"    placeholder="Search products..."    iconName="Search"    clearable    value={searchQuery}    onChangeText={setSearchQuery}    onSubmitEditing={handleSearch}    returnKeyType="search"  />  <IconButton    iconName="Search"    loading={isSearching}    onPress={handleSearch}    disabled={!searchQuery.trim()}  /></View>;Disabled input
Section titled “Disabled input”<Input  label="Read Only Field"  value="This field cannot be edited"  editable={false}  hint="This field is read-only"/>Input with custom styling
Section titled “Input with custom styling”<Input  label="Custom Styled Input"  placeholder="Custom appearance"  value={value}  onChangeText={setValue}  style={{    backgroundColor: colors.primary + '10',    borderColor: colors.primary,    borderWidth: 2,  }}/>Multi-step form input
Section titled “Multi-step form input”const [currentStep, setCurrentStep] = useState(0);const [formData, setFormData] = useState({  firstName: '',  lastName: '',  email: '',  phone: '',});
const steps = [  {    title: 'Personal Information',    fields: [      { key: 'firstName', label: 'First Name', icon: 'User' },      { key: 'lastName', label: 'Last Name', icon: 'User' },    ],  },  {    title: 'Contact Information',    fields: [      {        key: 'email',        label: 'Email',        icon: 'Mail',        keyboardType: 'email-address',      },      {        key: 'phone',        label: 'Phone',        icon: 'Phone',        keyboardType: 'phone-pad',      },    ],  },];
const currentStepData = steps[currentStep];
<Card>  <Text variant="h4">{currentStepData.title}</Text>  <View style={{ gap: 16, marginTop: 16 }}>    {currentStepData.fields.map((field) => (      <Input        key={field.key}        label={field.label}        iconName={field.icon as IconName}        keyboardType={field.keyboardType}        value={formData[field.key as keyof typeof formData]}        onChangeText={(value) =>          setFormData((prev) => ({ ...prev, [field.key]: value }))        }        placeholder={`Enter your ${field.label.toLowerCase()}`}      />    ))}  </View></Card>;Implementation notes
Section titled “Implementation notes”- Built on top of InputContainer for consistent styling and behavior
- Password variant automatically shows/hides password with eye icon
- Clearable inputs show an X button when they contain text
- Focus and blur states are automatically managed with visual feedback
- The component handles platform-specific cursor and selection colors
- Icons are positioned on the left side with proper spacing
- Error states change border color and display hint text in error color
Keyboard types
Section titled “Keyboard types”The input supports various keyboard types for better user experience:
- default: Standard keyboard
- email-address: Email-optimized keyboard
- numeric: Number pad
- phone-pad: Phone number pad
- url: URL-optimized keyboard
Styling
Section titled “Styling”Theme integration
Section titled “Theme integration”The Input automatically applies theme styling:
- Background: Uses theme background colors
- Border: Uses theme border colors with focus state changes
- Text: Uses theme typography and foreground colors
- Icons: Use theme foreground color with opacity variations
Error states
Section titled “Error states”Error styling is automatically applied when error={true}:
- Border color: Changes to destructive color
- Hint text: Displays in destructive color
- Focus state: Maintains error styling even when focused
Accessibility
Section titled “Accessibility”- Input fields are fully keyboard accessible
- Labels are properly associated with input fields
- Hint text provides additional context for screen readers
- Error states are communicated to assistive technologies
- Focus management works correctly with keyboard navigation
- Proper contrast ratios are maintained in all states