Single-line or multi-line text input with a label, help text and error message.
import { TextField } from "@rdloom/react";
export default function TextFieldBasicExample() {
return (
<TextField className="w-64" label="Full name" />
);
}Installation
npx rdloom add text-fieldCopies the source into src/components/rdloom. Edit it freely: rdloom upgrade merges later versions into your changes. It needs react-aria-components; add --install to install them.
Use another registry client
npx shadcn@latest add https://rdloom.vimalbhatt.com/r/text-field.jsonWorks, but without upgrade tracking.
Usage
import { TextField } from "@rdloom/react";
<TextField className="w-64" label="Full name" />With description
import { TextField } from "@rdloom/react";
export default function TextFieldWithDescriptionExample() {
return (
<TextField className="w-64" label="Email" type="email" placeholder="you@company.com" description="We only use it for sign-in." />
);
}Invalid
import { Button, TextField } from "@rdloom/react";
export default function TextFieldInvalidExample() {
return (
<form className="flex flex-col items-start gap-3" onSubmit={(e) => e.preventDefault()}>
{/* Declare the rules; errors show on submit and are announced. */}
<TextField
className="w-64"
label="Username"
isRequired
validate={(v) => (v.length > 0 && v.length < 3 ? "Use at least 3 characters." : null)}
/>
<Button type="submit">Create account</Button>
</form>
);
}Multiline
import { TextField } from "@rdloom/react";
export default function TextFieldMultilineExample() {
return (
<TextField className="w-80" label="Feedback" multiline placeholder="What could be better?" />
);
}Sizes
import { TextField } from "@rdloom/react";
export default function TextFieldSizesExample() {
return (
<div className="flex flex-wrap items-end gap-3">
<TextField className="w-40" label="Small" size="sm" />
<TextField className="w-40" label="Medium" size="md" />
<TextField className="w-40" label="Large" size="lg" />
</div>
);
}API Reference
Defined by the spec. Components also accept the props of the React Aria component they wrap.
| Prop | Type | Default |
|---|---|---|
labelrequiredVisible label. Required so the field is always named. | string | none |
descriptionHelp text shown under the input. | string | none |
errorMessageShown when the field is invalid. | string | none |
placeholderExample value. Never a replacement for the label. | string | none |
sizeHeight and font size. | "sm" | "md" | "lg" | "md" |
multilineRenders a textarea instead of an input. | boolean | false |
isDisabledPrevents editing and dims the field. | boolean | false |
isInvalidMarks the value as invalid and shows errorMessage. | boolean | false |
isRequiredMarks the field as required for form submission. | boolean | false |
valueControlled value. | string | none |
defaultValueInitial value when uncontrolled. | string | none |
onChangeCalled with the new value on every edit. | (value: string) => void | none |
Accessibility
Role textbox, WCAG 2.2 AA. Tested with axe and keyboard tests; screen reader checks are in the audit checklist.
Keyboard
- Tab moves focus in and out
Screen readers announce
- On focus: the label, then the field type (edit text), then the description
- Required fields are announced as required
- Invalid: announced as invalid, and the error message is read
- Multiline fields are announced as multi-line
What your code must do
- Label is always rendered and linked to the input
- Description and error are linked with aria-describedby
- Invalid state is exposed with aria-invalid
Guidelines
Use it when
- Collecting free-form text such as names, emails or notes
Avoid it when
- Picking from a known list: use Select or Combobox
- Dates: use DatePicker
Don't
- Placeholder used as the only label
- Showing errors before the user has finished typing
- Passing isInvalid for required or format checks (even isInvalid={false}): any defined value takes over validity and hides the built-in errors. Use isRequired and validate; pass isInvalid only for errors the app finds itself, such as from the server
Design tokens
The semantic tokens this component uses. Change them once and every component follows; see Design tokens.
--rd-color-surface-default--rd-color-border-default--rd-color-border-strong--rd-color-text-default--rd-color-text-muted--rd-color-feedback-danger--rd-color-focus-ring--rd-radius-control