EQTY Lab Equality

Input

Single-line text input field

View as Markdown

Overview

Input is a single-line text field for collecting short values such as names, emails, passwords, and numbers. It wraps a native <input>, so it accepts all standard input attributes (type, placeholder, value, disabled, min/max, and so on) and forwards a ref to the underlying element.

Beyond the native element, it adds prefix and suffix slots for placing an icon or other content inside the field — useful for a leading search icon or a trailing password-reveal toggle. It also owns its supplementary copy: helpText and errorText render below the field, so every form in the product spaces and styles those messages the same way. Pair the input with a Label (via a shared id/htmlFor) so it has an accessible caption, or use it inside a Form field.

Usage

Import the component:

tsx
import { Input } from "@eqtylab/equality";

Basic usage:

tsx
<Input type="text" placeholder="Enter text here..." />

Controlled, driving the value yourself:

tsx
const [value, setValue] = useState("");

<Input value={value} onChange={(e) => setValue(e.target.value)} />;

States

Default

Disabled

Error

Pass errorText to put the field in its error state. The border turns red, the input is marked aria-invalid, and the message is rendered below the field.

Help & Error Text

The component renders one message slot below the field, so spacing and styling stay consistent across every form. The two props share that slot: the error replaces the help text rather than stacking under it, and the help text returns once the field is valid again. A field never shows two competing lines of small print.

Help Text

helpText is supplementary copy shown whenever the field is not in error. Use it for the technical constraints a user cannot infer from the label — character limits, password requirements, accepted formats, units. Keep it short and write it before the user makes a mistake, not after.

Lowercase letters, numbers, and hyphens. Maximum 32 characters.

Error Text

errorText appears only when the field is in the error state. Tell the user what is wrong and how to fix it — “Enter a valid email address”, not “Invalid input”. Leave the prop undefined (or empty) when the field is valid.

Because the error hides the help text, an error about a stated constraint should restate it: “Name must be 32 characters or fewer”, not “Too long”. Otherwise the user loses the requirement at the moment they need it.

A validator that reports several problems at once can pass them as an array — errorText={["Code is duplicated.", "Use letters, numbers, hyphens, and periods."]} — and each gets its own row, deduped. Pass a single string whenever you can; a stack of red rows is harder to act on than one clear sentence.

How the message enters depends on whether there is help text:

  • With help text — the slot is already occupied, so the error swaps in place. Nothing moves, and there is no animation to sit through before the message is readable.
  • Without help text — the error collapses open and closed, so validating on change never makes the layout jump.

The first field below has help text, the second does not. Type a short password into each.

Usage

tsx
<Input
  helpText="Lowercase letters, numbers, and hyphens. Maximum 32 characters."
  errorText={nameError}
/>

Whichever message is showing is wired to the input with aria-describedby, and the error carries role="alert", so a screen reader announces it as soon as it appears. Do not repeat the error in a separate element — that double-announces it.

When the constraint is a character limit, pair the help text with a counter beside the label (0/80 characters) rather than spending the help text on the number.

Input Types

Because the underlying element is a native <input>, set the type prop to any standard value.

Email

Password

Number

Usage

tsx
<Input type="email" placeholder="user@example.com" />
<Input type="password" placeholder="Enter password" />
<Input type="number" min="0" max="100" />

Prefix & Suffix

Use the prefix and suffix props to render content inside the field, before or after the text. Any node works, though an icon is the most common.

With Prefix Icon

With Suffix Icon

Usage

tsx
import { Search, Eye } from "lucide-react";

<Input placeholder="Search..." prefix={<Search />} />
<Input type="password" placeholder="Password" suffix={<Eye />} />

Props

Input accepts all standard <input> attributes (type, placeholder, value, defaultValue, onChange, disabled, min, max, etc.) in addition to the props below.

NameDescriptionTypeDefaultRequired
prefixContent rendered inside the field, before the text.ReactNode
suffixContent rendered inside the field, after the text.ReactNode
helpTextSupplementary copy below the field. Hidden while an error is showing.ReactNode
errorTextError message below the field. Setting it puts the field in its error state and replaces the help text. An array renders one row per message.ReactNode | string[]
typeThe native input type.stringtext