custom-headless-input-field
v1.1.0
Published
A customizable, accessible React input field component with Tailwind CSS
Readme
InputField Component
Description
The InputField component is a customizable input field with built-in dark mode support, flexible styling options, and scoped Tailwind CSS that won't interfere with your app's styles. It supports both single-line inputs and auto-resizing multiline text areas.
Installation
npm install custom-headless-input-field@latestFeatures
- ✅ Scoped Tailwind CSS - Won't override your app's styles
- ✅ Single & Multiline support - Input fields and auto-resizing textareas
- ✅ Built-in dark mode support with custom theme variables
- ✅ Auto-resize textarea - Automatically adjusts height based on content
- ✅ Icon support - Add icons to input fields
- ✅ Input validation - Built-in support for required fields and types
- ✅ Keyboard navigation - Full accessibility support
- ✅ Flexible customization - Extensive styling props
- ✅ Error state - Built-in error styling and error message display
- ✅ WCAG 2.1 AA - aria-required, aria-invalid, aria-describedby, aria-label support
Usage
import React, { useState } from "react";
import { InputField } from "custom-headless-input-field";
const App = () => {
const [name, setName] = useState("");
const [description, setDescription] = useState("");
const [age, setAge] = useState("");
return (
<div>
{/* Basic Input Field */}
<InputField
label="Full Name"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Enter your full name"
required={true}
/>
{/* Multiline Textarea */}
<InputField
label="Description"
value={description}
onChange={(e) => setDescription(e.target.value)}
placeholder="Tell us about yourself..."
multiline={true}
/>
{/* Number Input */}
<InputField
label="Age"
type="number"
value={age}
onChange={(e) => setAge(e.target.value)}
placeholder="Enter your age"
min={0}
/>
</div>
);
};Props
Core Props
| Prop | Type | Required | Description |
| ---------- | ------------------------------------------------------------------- | -------- | ------------------------------------ |
| value | string \| number | ✅ | The current value of the input field |
| onChange | (e: ChangeEvent<HTMLInputElement \| HTMLTextAreaElement>) => void | ✅ | Callback when input value changes |
Optional Props
| Prop | Type | Default | Description |
| ------------------ | ---------------------------- | -------- | ------------------------------------------------ |
| label | React.ReactNode | - | Label displayed above the input field |
| id | string | - | HTML id attribute for the input |
| type | string | "text" | Input type (text, email, password, number, etc.) |
| placeholder | string | - | Placeholder text for the input |
| required | boolean | false | Whether the field is required |
| disabled | boolean | false | Whether the field is disabled |
| multiline | boolean | false | Use textarea instead of input for multiple lines |
| min | number | - | Minimum value for number inputs |
| icon | React.ReactNode | - | Icon to display inside the input field |
| className | string | - | Custom CSS classes for the input/textarea |
| onKeyDown | (e: KeyboardEvent) => void | - | Callback for keyboard events |
| onBlur | () => void | - | Callback when input loses focus |
| name | string | - | HTML name attribute for form submission |
| maxLength | number | - | Maximum character length |
| autoFocus | boolean | - | Auto-focus the input on mount |
| readOnly | boolean | - | Make the input read-only |
| error | boolean | false | Display error styling (red border) |
| errorMessage | string | - | Error message displayed below the input |
| wrapperClassName | string | - | Custom CSS classes for the outer wrapper div |
| labelClassName | string | - | Custom CSS classes for the label element |
| aria-label | string | - | Accessible label for inputs without visible label|
Styles
The InputField component uses scoped Tailwind CSS that won't conflict with your application's styles. All Tailwind utilities are contained within the .inputfield-scoped wrapper.
Built-in Theme Variables
The component includes custom theme variables for consistent styling:
input-purple- Primary input focus color- Full Tailwind v4.1.11 utility support within the input scope
CSS Setup
Ensure Tailwind CSS is properly set up in your project. In your main CSS file:
@import "tailwindcss";
/* Your other styles */Important: The InputField component requires Tailwind CSS to be available in your project for styling to work properly.
Dark Mode Support
The component automatically adapts to dark mode when the dark class is present on a parent element:
// Enable dark mode for the entire app
<body className="dark">
<App />
</body>
// Or scope it to a specific section
<div className="dark">
<InputField ... />
</div>No Setup Required
The InputField component is completely self-contained:
- ✅ No external CSS imports needed
- ✅ Won't override your app's Tailwind setup
- ✅ Works independently of your project's CSS configuration
- ✅ Scoped CSS prevents style conflicts
Advanced Usage
Auto-Resizing Textarea
<InputField
label="Comments"
value={comments}
onChange={setComments}
multiline={true}
placeholder="Enter your comments here... This will auto-resize as you type!"
/>Input with Icon
import { MagnifyingGlassIcon } from "@heroicons/react/24/outline";
<InputField
label="Search"
value={searchTerm}
onChange={setSearchTerm}
placeholder="Search..."
icon={<MagnifyingGlassIcon className="h-5 w-5" />}
/>;Custom Styling Example
<InputField
label="Custom Styled Input"
value={value}
onChange={setValue}
className="border-blue-300 focus:ring-blue-500 bg-blue-50 dark:bg-blue-900"
placeholder="Custom styled input"
/>Error State
<InputField
id="email"
label="Email Address"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
error={!isValidEmail}
errorMessage="Please enter a valid email address"
/>Accessible Input Without Visible Label
<InputField
id="search"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Search..."
aria-label="Search"
icon={<MagnifyingGlassIcon className="h-5 w-5" />}
/>Custom Wrapper and Label Styling
<InputField
label="Username"
value={username}
onChange={(e) => setUsername(e.target.value)}
wrapperClassName="w-full mb-2"
labelClassName="text-sm text-gray-500 mb-1"
/>Form Validation
<InputField
label="Email Address"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="[email protected]"
required={true}
onBlur={() => {
// Validate email format
if (email && !email.includes("@")) {
alert("Please enter a valid email");
}
}}
/>Input Types
The InputField component supports all standard HTML input types:
text- Default text inputemail- Email validationpassword- Password input with hidden charactersnumber- Numeric input with optional min/maxtel- Telephone number inputurl- URL input- And more...
Accessibility
The InputField component meets WCAG 2.1 AA standards:
aria-requiredset automatically whenrequired={true}aria-disabledset automatically whendisabled={true}aria-invalidset automatically whenerror={true}aria-describedbylinks to the error message element whenerrorMessageis providedaria-labelprop for inputs without a visible label- Decorative icons marked with
aria-hidden="true" - Label associated with input via
htmlFor/id
Customization
The InputField component offers extensive customization options:
- Complete styling control through
className,wrapperClassName, andlabelClassNameprops - Single/multiline modes for different content types
- Auto-resizing textarea for dynamic content
- Icon integration for enhanced UX
- Built-in dark mode support with automatic adaptation
- Error state with customizable error messages
- Form validation support with required fields and types
- Scoped CSS to prevent style conflicts
