@neynar/ui
Version:
React UI component library built on shadcn/ui and Tailwind CSS
327 lines (293 loc) • 7.34 kB
Markdown
# TextField
**Type**: component
TextField - Complete form field with label, input, and descriptive text A comprehensive form field component that combines Input and Label components with additional helper text and error handling capabilities. Automatically manages accessibility attributes, ID generation, and ARIA relationships to ensure forms are usable by all users including those using assistive technologies. Built on top of the Input and Label primitives, TextField provides a complete form field solution with consistent styling, proper semantic markup, and enhanced UX features. Supports all HTML input types while adding form validation states, descriptive text, and automatic accessibility compliance.
## JSX Usage
```jsx
import { TextField } from '@neynar/ui';
<TextField
label="value"
helperText="value"
error="value"
required={true}
id="value"
type={value}
placeholder="value"
value={value}
defaultValue={value}
disabled={true}
readOnly={true}
name="value"
autoComplete="value"
autoFocus={true}
maxLength={0}
minLength={0}
pattern="value"
min={value}
max={value}
step={value}
onChange={handleChange}
onFocus={handleFocus}
onBlur={handleBlur}
onKeyDown={handleKeyDown}
onKeyUp={handleKeyUp}
className="value"
/>
```
## Component Props
### label
- **Type**: `string`
- **Required**: No
- **Description**: No description available
### helperText
- **Type**: `string`
- **Required**: No
- **Description**: No description available
### error
- **Type**: `string`
- **Required**: No
- **Description**: No description available
### required
- **Type**: `boolean`
- **Required**: No
- **Description**: No description available
### id
- **Type**: `string`
- **Required**: No
- **Description**: No description available
### type
- **Type**: `React.HTMLInputTypeAttribute`
- **Required**: No
- **Description**: No description available
### placeholder
- **Type**: `string`
- **Required**: No
- **Description**: No description available
### value
- **Type**: `string | ReadonlyArray<string> | number`
- **Required**: No
- **Description**: No description available
### defaultValue
- **Type**: `string | ReadonlyArray<string> | number`
- **Required**: No
- **Description**: No description available
### disabled
- **Type**: `boolean`
- **Required**: No
- **Description**: No description available
### readOnly
- **Type**: `boolean`
- **Required**: No
- **Description**: No description available
### name
- **Type**: `string`
- **Required**: No
- **Description**: No description available
### autoComplete
- **Type**: `string`
- **Required**: No
- **Description**: No description available
### autoFocus
- **Type**: `boolean`
- **Required**: No
- **Description**: No description available
### maxLength
- **Type**: `number`
- **Required**: No
- **Description**: No description available
### minLength
- **Type**: `number`
- **Required**: No
- **Description**: No description available
### pattern
- **Type**: `string`
- **Required**: No
- **Description**: No description available
### min
- **Type**: `string | number`
- **Required**: No
- **Description**: No description available
### max
- **Type**: `string | number`
- **Required**: No
- **Description**: No description available
### step
- **Type**: `string | number`
- **Required**: No
- **Description**: No description available
### onChange
- **Type**: `(event: React.ChangeEvent<HTMLInputElement>) => void`
- **Required**: No
- **Description**: No description available
### onFocus
- **Type**: `(event: React.FocusEvent<HTMLInputElement>) => void`
- **Required**: No
- **Description**: No description available
### onBlur
- **Type**: `(event: React.FocusEvent<HTMLInputElement>) => void`
- **Required**: No
- **Description**: No description available
### onKeyDown
- **Type**: `(event: React.KeyboardEvent<HTMLInputElement>) => void`
- **Required**: No
- **Description**: No description available
### onKeyUp
- **Type**: `(event: React.KeyboardEvent<HTMLInputElement>) => void`
- **Required**: No
- **Description**: No description available
### className
- **Type**: `string`
- **Required**: No
- **Description**: No description available
## Examples
### Example 1
```tsx
// Basic text input with label
<TextField
label="Email Address"
type="email"
placeholder="Enter your email"
name="email"
/>
```
### Example 2
```tsx
// Required field with helper text
<TextField
label="Username"
placeholder="
### Example 3
```tsx
// Password field with validation error
<TextField
label="Password"
type="password"
required
error="Password must be at least 8 characters long"
value={password}
onChange={(e) => setPassword(e.target.value)}
minLength={8}
autoComplete="new-password"
/>
```
### Example 4
```tsx
// Controlled component with real-time validation
const [email, setEmail] = useState("");
const [error, setError] = useState("");
const validateEmail = (value: string) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(value)) {
setError("Please enter a valid email address");
} else {
setError("");
}
};
<TextField
label="Email"
type="email"
value={email}
onChange={(e) => {
setEmail(e.target.value);
validateEmail(e.target.value);
}}
onBlur={(e) => validateEmail(e.target.value)}
error={error}
required
autoComplete="email"
/>
```
### Example 5
```tsx
// Number input with constraints
<TextField
label="Age"
type="number"
min={0}
max={120}
step={1}
helperText="Enter your age in years"
placeholder="25"
/>
```
### Example 6
```tsx
// Search input with custom styling
<TextField
label="Search"
type="search"
placeholder="Search products..."
className="max-w-md"
onKeyDown={(e) => {
if (e.key === 'Enter') {
handleSearch(e.currentTarget.value);
}
}}
/>
```
### Example 7
```tsx
// Form integration with React Hook Form
const { register, formState: { errors } } = useForm();
<form onSubmit={handleSubmit(onSubmit)}>
<TextField
label="Full Name"
{...register("fullName", { required: "Full name is required" })}
error={errors.fullName?.message}
helperText="Enter your first and last name"
/>
<TextField
label="Phone Number"
type="tel"
{...register("phone", {
pattern: {
value: /^[\+]?[1-9][\d]{0,15}$/,
message: "Please enter a valid phone number"
}
})}
error={errors.phone?.message}
autoComplete="tel"
/>
</form>
```
### Example 8
```tsx
// File input with custom validation
<TextField
label="Profile Picture"
type="file"
accept="image/*"
helperText="Upload a PNG, JPG or GIF (max 5MB)"
onChange={(e) => {
const file = e.target.files?.[0];
if (file && file.size > 5 * 1024 * 1024) {
setError("File size must be less than 5MB");
} else {
setError("");
handleFileUpload(file);
}
}}
error={fileError}
/>
```
### Example 9
```tsx
// Date input with range constraints
<TextField
label="Birth Date"
type="date"
min="1900-01-01"
max={new Date().toISOString().split('T')[0]}
helperText="You must be 18 or older to register"
required
/>
```
### Example 10
```tsx
// Disabled field with explanation
<TextField
label="Account ID"
value="ACC-12345"
disabled
helperText="This value is automatically generated and cannot be changed"
/>
```