RHFInput
Text input component integrated with React Hook Form
You are reading the v1 docs. v2 renamed several props and replaced GeckoUIPortal with GeckoUIProvider. Read this page in v2.
Live examples are only rendered in the v2 docs.
RHFInput
A text input component integrated with React Hook Form that automatically displays error states with a red border when validation fails. Supports value transformation for input/output formatting.
Installation
import { RHFInput } from '@geckoui/geckoui';Basic Usage
import { useForm, FormProvider } from 'react-hook-form';
import { RHFInput } from '@geckoui/geckoui';
function Example() {
const methods = useForm({
defaultValues: {
username: ''
}
});
return (
<FormProvider {...methods}>
<RHFInput name="username" placeholder="Enter username" />
</FormProvider>
);
}Props API
Extends all props from Input component plus:
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | - | Field name (required) |
control | Control | Auto-injected | Optional: Pass explicitly for nested forms or custom form context |
rules | RegisterOptions | - | Inline validation rules (see Inline Rules Validation) |
transform | { input, output } | - | Value transformation functions |
prefix | `ReactNode \ | Function` | - |
suffix | `ReactNode \ | Function` | - |
onChange | (value: string) => void | - | Change callback (receives value, not event) |
onBlur | (value: string) => void | - | Blur callback |
| ...rest | InputProps | - | All Input component props |
Examples
With Validation (Zod)
import { useForm, FormProvider } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { RHFInput, RHFInputGroup, Button } from '@geckoui/geckoui';
const schema = z.object({
email: z.string().email('Invalid email address').min(1, 'Email is required')
});
function Example() {
const methods = useForm({
resolver: zodResolver(schema),
mode: 'onBlur', // Validate on blur
defaultValues: { email: '' }
});
return (
<FormProvider {...methods}>
<RHFInputGroup label="Email Address" required>
<RHFInput name="email" type="email" placeholder="Enter email" />
</RHFInputGroup>
</FormProvider>
);
}Inline Rules Validation
For simple forms, you can use the rules prop for inline validation instead of a schema resolver:
<RHFInput
name="email"
rules={{
required: 'Email is required',
pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: 'Invalid email address'
}
}}
/>
<RHFInput
name="username"
rules={{
required: 'Username is required',
minLength: { value: 3, message: 'Must be at least 3 characters' },
maxLength: { value: 20, message: 'Must be 20 characters or less' }
}}
/>Note: For complex forms with many fields, we recommend using a schema resolver (Zod, Yup) instead of inline rules for better maintainability and type safety.
With Prefix and Suffix
<RHFInput
name="amount"
type="number"
prefix="$"
suffix="USD"
placeholder="0.00"
/>With Value Transformation
Transform values on input/output (e.g., phone number formatting):
const formatPhone = (value: string) => {
const cleaned = value.replace(/\\D/g, '');
const match = cleaned.match(/^(\\d{3})(\\d{3})(\\d{4})$/);
if (match) {
return `(${match[1]}) ${match[2]}-${match[3]}`;
}
return value;
};
const sanitizePhone = (value: string) => {
return value.replace(/\\D/g, '');
};
<RHFInput
name="phone"
placeholder="Phone number"
transform={{
input: formatPhone,
output: sanitizePhone
}}
/>Custom Suffix with Error Icon
<RHFInput
name="password"
type="password"
suffix={({ fieldState }) => <>fieldState.error ? <ErrorIcon /> : null</>}
/>Disabled State
<RHFInput name="readonly" disabled />Complete Form Example
import { useForm, FormProvider } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { RHFInput, RHFInputGroup, Button } from '@geckoui/geckoui';
const schema = z.object({
username: z.string().min(3, 'Username must be at least 3 characters'),
email: z.string().email('Invalid email address'),
password: z.string().min(8, 'Password must be at least 8 characters')
});
function RegistrationForm() {
const methods = useForm({
resolver: zodResolver(schema),
mode: 'onBlur', // Validate on blur
defaultValues: {
username: '',
email: '',
password: ''
}
});
return (
<FormProvider {...methods}>
<form onSubmit={methods.handleSubmit(console.log)}>
<RHFInputGroup label="Username" required>
<RHFInput name="username" placeholder="Enter username" />
</RHFInputGroup>
<RHFInputGroup label="Email Address" required>
<RHFInput name="email" type="email" placeholder="Enter email" />
</RHFInputGroup>
<RHFInputGroup label="Password" required>
<RHFInput name="password" type="password" placeholder="Enter password" />
</RHFInputGroup>
<Button type="submit">Submit</Button>
</form>
</FormProvider>
);
}Error States
RHFInput automatically displays error states with:
- Red border via
data-errorattribute on the root element whenfieldState.errorexists - No automatic error icon (you must add via suffix prop if desired)
.GeckoUIRHFInput[data-error] {
border-color: red;
}Recommended: Use RHFInputGroup for label + input + error layouts. It automatically detects the RHF input and displays validation errors:
<RHFInputGroup label="Username" required>
<RHFInput name="username" />
</RHFInputGroup>Or combine with RHFError component manually:
<RHFInput name="username" />
<RHFError name="username" />Tip: Use mode: 'onBlur' in useForm to validate on blur for better UX:
const methods = useForm({
resolver: zodResolver(schema),
mode: 'onBlur' // Validates when user leaves the field
});Value Transformation
The transform prop allows formatting values differently for display vs storage:
// Currency formatting
<RHFInput
name="price"
transform={{
input: (value) => value ? `$${value}` : '',
output: (value) => value.replace('$', '')
}}
/>
// Uppercase transformation
<RHFInput
name="code"
transform={{
input: (value) => value?.toUpperCase() || '',
output: (value) => value
}}
/>Dynamic Prefix/Suffix
Both prefix and suffix can be functions that receive render props:
<RHFInput
name="email"
prefix={({ field }) => (
field.value ? <CheckIcon /> : <MailIcon />
)}
suffix={({ fieldState }) => (
fieldState.error ? <ErrorIcon /> : null
)}
/>Accessibility
- Inherits all accessibility features from Input component
- Proper ARIA attributes for error states
- Keyboard navigable
- Screen reader compatible
Related Components
- Input - Base input component
- RHFTextarea - Multi-line text input
- RHFNumberInput - Number-only input
- RHFError - Error message display