Skip to content

Input

The control you reach for whenever the value is typed rather than chosen. It is a real <input>, so type, placeholder, required, pattern, minLength and the rest work exactly as they do on the platform — what the library adds is the design system's metrics, the two-tone focus ring, and the wiring that makes it participate in a Field without a line of glue.

input/basic.tsx

Lowercase letters, numbers and dashes.

Base UI's Input is Field.Control under a friendlier name. That is why there is no Field.Control in this library and no <Field.Control render={...}> dance: <Input> inside a <Field.Root> already picks up the label, the description, the error message, the name used on submit, and the validity attributes.

Import

import { Input } from "@forte-ui/react";

Examples

Sizes

size moves height, inline padding and font size together, and the numbers come from the same --forte-control-* tokens Select.Trigger reads — so an input and a select on one row are the same height at every data-forte-density setting.

input/sizes.tsx

Variants

variant changes only how much weight the control carries: outline reads as a form control, soft as a filled field, ghost as an inline affordance — the same three the select trigger has.

input/variants.tsx

States

Disabled and read-only are not the same thing and do not look the same. Disabled drops to 55% opacity and takes cursor: not-allowed. Read-only keeps full contrast, a panel-coloured background, and the text cursor — everywhere else in this library a read-only control falls back to the default arrow, but selecting and copying the value is the point of the state, so the text cursor stays.

input/states.tsx

Multi-line

Use Textarea. It is the same Field.Control rendered as a <textarea>, wearing the same variants, sizes and colour slots, and it adds the things a paragraph needs that a control height cannot express — a height counted in rows, a growth ceiling, and autoResize.

Accessibility

An input needs an accessible name, and <Field.Label> is the way to give it one — it renders a real <label> wired with htmlFor, so clicking the text focuses the control and the hit target grows by the width of the label. Where the design has no visible label, aria-label on the input is the fallback.

Placeholder text is coloured --forte-color-foreground-muted (5.82:1) rather than --forte-color-foreground-subtle (3.73:1). SC 1.4.3 has no exemption for placeholders in an enabled control, and Firefox's own 0.54 ::placeholder opacity is reset for the same reason.

In forced-colors mode the control paints Field / FieldText with a FieldText boundary. That last part matters for soft and ghost, whose border is transparent — a value forced-colors replaces with a system colour of its choosing rather than leaving invisible, so without the restatement the three variants would stop looking like the same control.

Theming

Every --forte-input-* property is declared on the input element itself, and an element's own declaration beats an inherited one — so setting these on :root, on a theme scope or on any ancestor does nothing. Set them on the input, through className (an unlayered rule beats @layer forte.components whatever its specificity) or an inline style.

The global tokens they resolve to — --forte-color-*, --forte-control-*, --forte-radius-* — are the exception: this component only reads those, so re-pointing them from :root or a theme scope moves every input at once.

Theming tokens for Input
PropertyControlsDefault
--forte-input-heightControl height (reset per size)var(--forte-control-h-md)
--forte-input-padding-xInline padding (reset per size)var(--forte-control-px-md)
--forte-input-font-sizeFont size (reset per size)var(--forte-font-size-2)
--forte-input-radiusCorner radiusvar(--forte-radius-control)
--forte-input-border-widthBorder width1px
--forte-input-bgBackground (reset per variant)var(--forte-color-background)
--forte-input-bg-hoverBackground on hovervar(--forte-color-panel-hover)
--forte-input-fgText colourvar(--forte-color-foreground)
--forte-input-placeholder-fgPlaceholder colourvar(--forte-color-foreground-muted)
--forte-input-border-colorBorder colour (reset per variant, and by data-invalid)var(--forte-color-border)
--forte-input-border-color-hoverBorder colour on hovervar(--forte-color-border-strong)
--forte-input-caret-colorCaret colourvar(--forte-color-primary)
--forte-input-selection-bgSelection backgroundvar(--forte-color-primary-soft)
--forte-input-selection-fgSelection text colourvar(--forte-color-primary-text)

API reference

Input

Props for Input
PropTypeDefaultDescription
classNamestringAdditional class name(s). Applied after the internal styles so consumer utilities (e.g. Tailwind) win without needing `!important`.
fullWidthbooleanfalseStretch the input to fill the width of its container. Only needed outside a `Field.Root` — a field is a flex column, so an input inside one already stretches.
sizeInputSizemdSize of the control. Height, inline padding and font size all move together, and the actual numbers follow the ambient `data-forte-density` setting. Matches `Select.Trigger`'s scale, so an input and a select on the same row line up. This shadows the native `size` attribute (which sets a width in characters). Reach for `fullWidth`, a CSS `inline-size`, or `render={<input size={10} />}` if you need that instead.
variantInputVariantoutlineHow much visual weight the control carries. `outline` reads as a form control, `soft` as a filled field, `ghost` as an inline affordance.

Everything else is a native <input> prop and passes straight through, plus Base UI's render, onValueChange and defaultValue.