[](https://www.npmjs.com/package/@versini/ui-textinput) 
!npm package minimized gzipped size>)
> Accessible and feature-rich React text input components built with TypeScript and TailwindCSS.
The TextInput package provides standard text inputs and masked text inputs with comprehensive form features including validation states, helper text, and customizable styling. Perfect for building accessible forms and user interfaces.
- Features
- Installation
- Usage
- API
- 🎯 Multiple Input Types: TextInput and TextInputMask components
- ♿ Accessible: WCAG compliant with proper labeling and keyboard navigation
- 🎨 Customizable: Multiple sizes, themes, and styling options
- 🔧 Form Integration: Built-in validation states and helper text
- 🌲 Tree-shakeable: Lightweight and optimized for bundle size
- 🔧 TypeScript: Fully typed with comprehensive prop definitions
- 🎠Theme Support: Built-in support for light, dark, and system themes
``bash`
npm install @versini/ui-textinput
> Note: This component requires TailwindCSS and the @versini/ui-styles plugin for proper styling. See the installation documentation for complete setup instructions.
`tsx
import { TextInput } from "@versini/ui-textinput";
function App() {
return (
name="email"
type="email"
placeholder="Enter your email"
/>
);
}
`
`tsx
import { TextInput } from "@versini/ui-textinput";
function App() {
return (
name="password"
type="password"
helperText="Must be at least 8 characters long"
placeholder="Enter your password"
/>
);
}
`
`tsx
import { TextInput } from "@versini/ui-textinput";
function App() {
return (
name="username"
error
helperText="Username is already taken"
defaultValue="invalid-username"
/>
);
}
`
`tsx
import { TextInput } from "@versini/ui-textinput";
import { Button } from "@versini/ui-button";
function App() {
return (
name="search"
placeholder="Search for anything..."
rightElement={
}
/>
);
}
`
`tsx
import { TextInputMask } from "@versini/ui-textinput";
import { ButtonIcon } from "@versini/ui-button";
import { IconEye, IconEyeOff } from "@versini/ui-icons";
import { useState } from "react";
function App() {
const [masked, setMasked] = useState(true);
return (
name="password"
type={masked ? "password" : "text"}
onMaskChange={setMasked}
rightElement={
noBackground
>
{masked ?
}
/>
);
}
`
| Prop | Type | Default | Description |
| --------------------- | ----------------------------------------------- | ---------- | -------------------------------------------------- |
| label | string | - | The label of the TextInput (required) |string
| name | | - | The name of the TextInput (required) |React.ReactElement
| rightElement | | - | Element to render on the right side |string
| rightElementClassName | | - | Extra classes for the right element container |boolean
| error | | false | Whether the TextInput is in error state |string
| helperText | | - | Text to add to the bottom of the TextInput |"xs" \| "sm" \| "md" \| "lg" \| "xl"
| size | | "md" | Controls input height and padding |"dark" \| "light" \| "system" \| "alt-system"
| mode | | "system" | The mode of TextInput (controls color) |"dark" \| "light" \| "system" \| "alt-system"
| focusMode | | "system" | The focus ring color mode |boolean
| labelHidden | | false | Hides the label visually but retains accessibility |string
| labelId | | - | Id to use for the TextInput label |boolean
| noBorder | | false | Whether the TextInput has a border |boolean
| raw | | false | Whether to render with styles |string
| inputClassName | | - | CSS class(es) for the actual input element |
_Also supports all standard HTML input element attributes_
| Prop | Type | Default | Description |
| ------------------- | --------------------------- | ------- | ---------------------------------------------- |
| rightElement | React.ReactElement | - | Element to render on the right side (required) |(masked: boolean) => void
| onMaskChange | | - | Callback fired when mask state changes |() => void
| onTextInputMaskBlur | | - | Callback fired when user blurs out |
_Also supports all TextInput props except rightElement is required_
`tsx
import { TextInput } from "@versini/ui-textinput";
import { Button } from "@versini/ui-button";
import { useState } from "react";
function ValidationForm() {
const [errors, setErrors] = useState({});
const [values, setValues] = useState({
email: "",
password: "",
confirmPassword: ""
});
const handleSubmit = (e) => {
e.preventDefault();
// Validation logic here
};
return (
$3
`tsx
import { TextInput } from "@versini/ui-textinput";function SizeExamples() {
return (
label="Extra Small"
name="xs"
size="xs"
placeholder="Extra small input"
/>
label="Medium"
name="md"
size="md"
placeholder="Medium input (default)"
/>
label="Extra Large"
name="xl"
size="xl"
placeholder="Extra large input"
/>
);
}
`$3
`tsx
import { TextInput } from "@versini/ui-textinput";
import { ButtonIcon } from "@versini/ui-button";
import { IconSearch } from "@versini/ui-icons";function SearchInput() {
return (
label="Search Products"
name="search"
placeholder="Search for products..."
rightElement={
}
rightElementClassName="mr-2"
/>
);
}
`$3
`tsx
import { TextInput } from "@versini/ui-textinput";
import { ButtonIcon } from "@versini/ui-button";
import { IconClose } from "@versini/ui-icons";
import { useState } from "react";function ClearableInput() {
const [value, setValue] = useState("");
return (
label="Search Query"
name="query"
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder="Type to search..."
rightElement={
value ? (
setValue("")}>
) : undefined
}
/>
);
}
`$3
`tsx
import { TextInputMask } from "@versini/ui-textinput";
import { ButtonIcon } from "@versini/ui-button";
import { IconEye, IconEyeOff } from "@versini/ui-icons";
import { useState } from "react";function PasswordWithStrength() {
const [password, setPassword] = useState("");
const [masked, setMasked] = useState(true);
const getPasswordStrength = (password) => {
// Simple strength calculation
let strength = 0;
if (password.length >= 8) strength++;
if (/[A-Z]/.test(password)) strength++;
if (/[0-9]/.test(password)) strength++;
if (/[^A-Za-z0-9]/.test(password)) strength++;
return strength;
};
const strength = getPasswordStrength(password);
const strengthColors = ["red", "orange", "yellow", "green"];
const strengthLabels = ["Weak", "Fair", "Good", "Strong"];
return (
label="Password"
name="password"
type={masked ? "password" : "text"}
value={password}
onChange={(e) => setPassword(e.target.value)}
onMaskChange={setMasked}
rightElement={
label={masked ? "Show password" : "Hide password"}
noBackground
>
{masked ? : }
}
/> {password && (
{[...Array(4)].map((_, i) => (
key={i}
className={h-1 flex-1 rounded ${
i < strength
? bg-${strengthColors[strength - 1]}-500
: "bg-gray-200"
}}
/>
))}
Password strength: {strengthLabels[strength - 1] || "Too weak"}
)}
);
}
`$3
`tsx
import { TextInput } from "@versini/ui-textinput";function ThemeVariations() {
return (
label="Light Theme"
name="light"
mode="light"
placeholder="Light theme input"
/> label="Dark Theme"
name="dark"
mode="dark"
placeholder="Dark theme input"
/>
label="System Theme"
name="system"
mode="system"
placeholder="System theme input"
/>
);
}
``