Tessina UI
ConfiguratorGitHubIntroduction
InstallationUsageTheming
ComponentsAccordionAction SheetAlertAlertDialogArea ChartAspectRatioAvatarBadgeBannerBar ChartBottom NavBreadcrumbButtonButtonGroupCalendarCardCarouselChartChatBubbleCheckboxChipCodeBlockCollapsibleColor PickerComboboxCommandContainerContextMenuDate PickerDividerDrawerDropdown MenuEmptyStateFABFieldFieldsetFile UploadFile Upload 2FlexFormGridHoverCardIconButtonLabelLine ChartLinkMenubarMeterModalNavigation MenuNumberFieldOTP InputPaginationPie ChartPopoverProgressPromptInputRadar ChartRadial ChartRadioRatingScroll AreaSearchSegmentedControlSelectShortcutSidebarSkeletonSliderSpacerSpinnerSplit ButtonStackStatusStepperSurfaceSwitchTableTabsTextareaTime PickerToastToggleButtonToggleGroupToolbarTooltipTop Header DesktopTop Header Mobile
Contributing
Components

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.

Playground

Installation

pnpm add @tessinaui/ui

Usage

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)

Examples

Default

The simplest field — a label paired with a placeholder.

Intents

Five validation states — none, error, warning, success, and info — each recoloring the border, focus ring, and supporting text.

Sizes

Five heights from xs to xl, scaling padding and text proportionally.

Icons & Clearable

Add a leading or trailing icon, or a clear button that appears when the field has a value.

Prefix & Suffix

Use <FieldDropdown> as a prefix and <Button> as a suffix, sharing the field's size and rounded.

Disabled

A disabled field mutes the surface and prevents interaction.

API Reference

Props

PropTypeDefaultDescription
labelstring—Label text
requiredbooleanfalseShows 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
infoTextstring—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
leadingIconReact.ReactNode—Icon rendered inside the container on the leading side (as a ghost IconButton)
leadingIconLabelstring""Accessible label for the leading icon (screen readers)
leadingIconOnClick() => void—Makes the leading icon interactive when provided
trailingIconReact.ReactNode—Icon rendered inside the container on the trailing side
trailingIconLabelstring""Accessible label for the trailing icon
trailingIconOnClick() => void—Makes the trailing icon interactive when provided
clearablebooleanfalseShows an × IconButton when the field has a value. Visible alongside trailingIcon
onClear() => void—Called when the clear button is clicked
prefixReact.ReactNode—Slot to the left of the input container — use <FieldDropdown> for the country selector pattern
suffixReact.ReactNode—Slot to the right of the input container — use <Button> with matching size and rounded
supportingTextstring—Text below the input. Color and icon follow intent
showCharacterCounterbooleanfalseShows current / maxLength counter. Requires maxLength
dir"ltr" | "rtl"—Text direction. RTL flips the full layout
wrapperClassNamestring—Extra className for the outer wrapper <div>
containerClassNamestring—Extra className for the bordered container <div>
disabledbooleanfalseDisables the input and mutes all styles
maxLengthnumber—Native maxLength for the <input>. Used by character counter
placeholderstring—Native placeholder text
value / defaultValuestring—Controlled / uncontrolled value
onChangeChangeEventHandler—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

PropTypeDefaultDescription
flagstring—ISO 3166-1 alpha-2 country code (e.g. "si" for Slovenia). Loads from flagcdn.com
textstring—Text label shown next to the flag (e.g. "SLO(+386)")
showChevronbooleantrueWhether to show the ⌄ chevron. When false, the button is non-interactive (pointer-events-none)
childrenReact.ReactNode—Dropdown items (use <FieldDropdownItem>). When provided with showChevron={true}, clicking opens a Radix dropdown
roundedsame as Field"full"Must match the parent Field's rounded prop
sizesame as Field"md"Must match the parent Field's size prop
onClickMouseEventHandler—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/htmlFor pair
  • aria-required is set when required={true}
  • aria-invalid is set when intent="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

FAB

A pill-shaped floating action button with optional leading icon, label, and trailing icon

Fieldset

Groups related form controls under a shared legend, description, and helper text — built on Base UI's Fieldset primitive with four variants, five sizes, intent accents, and full RTL support.

On this page

PlaygroundInstallationUsageExamplesDefaultIntentsSizesIcons & ClearablePrefix & SuffixDisabledAPI ReferencePropsWith Prefix & SuffixFieldDropdown propsControlled UsageLabel VariantsRTLAccessibility