Field
A text input field with a label, helper text, FieldDropdown prefix, Button suffix, leading/trailing icon buttons, a clearable button, and a character counter. Supports all intent states and full RTL layout.
Installation
pnpm add @tessinaui/uiUsage
import { Field, FieldDropdown, FieldDropdownItem } from "@tessinaui/ui";
import { Button } from "@tessinaui/ui";<Field label="Email" placeholder="you@example.com" />Three label layout variants are available via labelPosition:
"outside-top"(default) — label above the field"inside"— label inside the container above the placeholder text"outside-left"— label to the left of the field (horizontal layout)
Playground
Configure every property interactively:
Showcase
All intents, sizes, and feature combinations:
API Reference
Props
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | — | Label text |
required | boolean | false | Shows a red * after the label and sets aria-required |
labelPosition | "outside-top" | "inside" | "outside-left" | "outside-top" | Label layout variant. inside renders the label inside the container above the input. outside-left creates a horizontal label + field layout |
infoText | string | — | Small info text shown top-right in the label row (or next to label for outside-left) |
intent | "none" | "error" | "warning" | "success" | "info" | "none" | Controls border color, focus ring color, and supporting text color/icon |
size | "xs" | "sm" | "md" | "lg" | "xl" | "md" | Controls height, padding (proportional to size), and text/icon size |
rounded | "full" | "lg" | "md" | "sm" | "none" | "full" | Border radius |
leadingIcon | React.ReactNode | — | Icon rendered inside the container on the leading side (as a ghost IconButton) |
leadingIconLabel | string | "" | Accessible label for the leading icon (screen readers) |
leadingIconOnClick | () => void | — | Makes the leading icon interactive when provided |
trailingIcon | React.ReactNode | — | Icon rendered inside the container on the trailing side |
trailingIconLabel | string | "" | Accessible label for the trailing icon |
trailingIconOnClick | () => void | — | Makes the trailing icon interactive when provided |
clearable | boolean | false | Shows an × IconButton when the field has a value. Visible alongside trailingIcon |
onClear | () => void | — | Called when the clear button is clicked |
prefix | React.ReactNode | — | Slot to the left of the input container — use <FieldDropdown> for the country selector pattern |
suffix | React.ReactNode | — | Slot to the right of the input container — use <Button> with matching size and rounded |
supportingText | string | — | Text below the input. Color and icon follow intent |
showCharacterCounter | boolean | false | Shows current / maxLength counter. Requires maxLength |
dir | "ltr" | "rtl" | — | Text direction. RTL flips the full layout |
wrapperClassName | string | — | Extra className for the outer wrapper <div> |
containerClassName | string | — | Extra className for the bordered container <div> |
disabled | boolean | false | Disables the input and mutes all styles |
maxLength | number | — | Native maxLength for the <input>. Used by character counter |
placeholder | string | — | Native placeholder text |
value / defaultValue | string | — | Controlled / uncontrolled value |
onChange | ChangeEventHandler | — | Native onChange handler |
All other native <input> attributes (type, name, autoComplete, etc.) are forwarded.
With Prefix & Suffix
Use <FieldDropdown> for the prefix (country selector, currency picker) and <Button> for the suffix. Pass the same size and rounded values to all three so they share identical border radius and height:
import { Field, FieldDropdown } from "@tessinaui/ui";
import { Button } from "@tessinaui/ui";
<Field
label="Phone"
placeholder="Enter number"
rounded="full"
size="md"
prefix={
<FieldDropdown
flag="si"
text="SLO(+386)"
size="md"
rounded="full"
/>
}
suffix={
<Button size="sm" rounded="full">
Verify
</Button>
}
/>FieldDropdown props
| Prop | Type | Default | Description |
|---|---|---|---|
flag | string | — | ISO 3166-1 alpha-2 country code (e.g. "si" for Slovenia). Loads from flagcdn.com |
text | string | — | Text label shown next to the flag (e.g. "SLO(+386)") |
showChevron | boolean | true | Whether to show the ⌄ chevron. When false, the button is non-interactive (pointer-events-none) |
children | React.ReactNode | — | Dropdown items (use <FieldDropdownItem>). When provided with showChevron={true}, clicking opens a Radix dropdown |
rounded | same as Field | "full" | Must match the parent Field's rounded prop |
size | same as Field | "md" | Must match the parent Field's size prop |
onClick | MouseEventHandler | — | Click handler when no children dropdown is used |
Controlled Usage
const [value, setValue] = useState("");
<Field
label="Search"
value={value}
onChange={(e) => setValue(e.target.value)}
clearable
onClear={() => setValue("")}
showCharacterCounter
maxLength={100}
/>Label Variants
{/* Inside — label floats above input text inside the container */}
<Field labelPosition="inside" label="Email" placeholder="you@example.com" />
{/* Outside left — horizontal layout, label column on the leading side */}
<Field labelPosition="outside-left" label="Email" placeholder="you@example.com" />RTL
Pass dir="rtl" to flip the full layout including the label row, input icons, prefix/suffix, and supporting text. Works with all labelPosition variants:
<Field dir="rtl" label="بحث" placeholder="نص العنصر النائب" leadingIcon={<Search />} />
<Field dir="rtl" labelPosition="outside-left" label="البريد" placeholder="you@example.com" />Accessibility
- The
<input>is associated with its<label>via a generated (or provided)id/htmlForpair aria-requiredis set whenrequired={true}aria-invalidis set whenintent="error"- The clear button has
aria-label="Clear"and is excluded from tab order (tabIndex={-1}) - Touch target for the clear button: ≥ 44×44 px
- Focus ring appears on the container (not the inner input) via
focus-within:ring-* - Color contrast: all intent states meet WCAG 2.1 AA
Progress
Communicate operation status with a linear bar or circular ring. Four variants (default/success/warning/error), three sizes, five rounding options, indeterminate animation, optional label with inside/outside positioning, and LTR/RTL support.
Checkbox
A form control that lets users select one or more options. Supports checked, unchecked, and indeterminate states. Five sizes, five intents, label/description/error patterns, and a CheckboxGroup compound component with select-all support.