Text fields with variants, sizes, labels, icons, clear control, numeric stepper, change or blur value commit, addons, input groups, hover and focus borders, and validation.
Also known as: text field, text input, text box, form input, number input, numeric stepper, spinbutton
Install with the CLI, or copy the component source into your project.
Add input (npm)
1npx --yes -p @default-file/ui df-ui add input
Primary text input.
Primary surface field and secondary soft wash. Secondary keeps full-contrast value text with no border.
Height steps from sm to xl, plus an exact height token override.
Label and hint above and below the field.
Floating label inside the field. It rises on focus or when text is entered.
Decorative start icon with a placeholder.
Interactive end control for show and hide.
Trailing clear control appears when the field has a value.
Helper line under a read-only field.
Badge in the label trailing slot.
Static https:// prefix. Only the host is editable.
Join a field and action button in one control.
Invalid field chrome with a muted hint. Default tints the label. invalidLabel false keeps the label at its normal color.
Solid focus outline instead of the ring recipe.
Inherits the theme hover border. Override with hoverBorderColor, or set hoverBorder false.
Custom fill, border color, tokenized border width step, and radius.
Tokenized border width steps: hairline, thin, and thick.
Axis and per-side padding via spacing tokens.
Place multiple inputs side by side with a simple grid.
Numeric field with kit increment and decrement controls. Steps with the buttons or ArrowUp and ArrowDown. Swap icons with incrementIcon and decrementIcon.
Same controlled duration twice. Backspace Second in each row: change snaps while typing; blur stays editable until you leave.
commitMode="change" (default)
commitMode="blur"
Non-interactive state with a muted fill, hairline border, and muted value text.
Single-line text field with primary and secondary variants, size, height, padding, and border width control, outside or inside labels, chrome overrides, hover and focus border recipes, icons, clearable trailing control, optional numeric stepper with swappable icons, change or blur value commit, prefix and suffix addons, an attached action for input groups, and validation state.
| Prop | Type | Default | Notes |
|---|---|---|---|
| variant | "primary" | "secondary" | "primary" | primary is a surface fill with a hairline border. secondary is a soft secondary wash with secondary-foreground value text and a transparent border. |
| size | "sm" | "md" | "lg" | "xl" | "md" | Field height step. Maps to --df-control-height-sm through --df-control-height-xl via --df-input-height. Replaces the native HTML size attribute. |
| height | string | - | Exact field height. Prefer a control token such as var(--df-control-height-2xl). Sets --df-input-height and overrides size. |
| padding | string | - | Padding on all sides. Prefer spacing tokens such as calc(2 * var(--spacing-unit)). Sets each --df-input-padding-* side. |
| paddingX | string | - | Horizontal padding. Sets --df-input-padding-left and --df-input-padding-right. Overrides padding on those sides. |
| paddingY | string | - | Vertical padding. Sets --df-input-padding-top and --df-input-padding-bottom. Overrides padding on those sides. |
| paddingTop | string | - | Top padding. Prefer spacing tokens. Sets --df-input-padding-top and wins over paddingY and padding. |
| paddingRight | string | - | Right padding. Prefer spacing tokens. Sets --df-input-padding-right and wins over paddingX and padding. |
| paddingBottom | string | - | Bottom padding. Prefer spacing tokens. Sets --df-input-padding-bottom and wins over paddingY and padding. |
| paddingLeft | string | - | Left padding. Prefer spacing tokens. Sets --df-input-padding-left and wins over paddingX and padding. Leading icons and floating labels follow this inset. |
| label | ReactNode | - | Field title. With labelPosition outside, renders the kit Label above the control. With inside, renders a floating label in the field that rises on focus or when the value is filled. |
| labelPosition | "outside" | "inside" | "outside" | outside places the label above the field. inside uses a floating label inside the field chrome. Empty versus filled state is driven by the field value via data-empty. |
| labelTrailing | ReactNode | - | Meta on the label row. Forwards to Label trailing when outside. Supports Badge or any node. |
| labelInsetAlign | "left" | "content" | "custom" | "left" | Outside label inset. Forwards to Label insetAlign. content tracks paddingLeft when set, otherwise --df-control-content-inset-inline. |
| labelInsetSize | string | - | Outside label custom inset. Forwards to Label insetSize when labelInsetAlign is custom. |
| labelColor | string | - | Label color. Prefer tokens such as var(--foreground). Sets --df-input-label. |
| background | string | - | Field fill. Prefer tokens such as var(--background). Sets --df-input-bg and overrides the variant recipe. |
| borderColor | string | - | Field border color. Prefer tokens such as var(--input). Sets --df-input-border. |
| borderWidth | "hairline" | "thin" | "thick" | "hairline" | Field border width step. Maps to --border-width-hairline, --border-width-thin, or --border-width-thick via --df-input-border-width. |
| hoverBorder | boolean | - | Instance hover border. Omit to inherit the theme. Set false to keep the resting border. Set true to force the hover border on. When set, the control writes data-hover-border; omit to inherit data-df-hover-border from the host. |
| hoverBorderColor | string | - | Hover border color when hover is active. Prefer tokens such as var(--foreground). Sets --df-input-hover-border. Focus and invalid borders take priority. |
| foreground | string | - | Value text color. Prefer tokens such as var(--foreground). Sets --df-input-fg. |
| placeholderColor | string | - | Placeholder color. Prefer tokens such as var(--muted-foreground). Sets --df-input-placeholder. |
| radius | "none" | "xxs" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "4xl" | "full" | "4xl" | Corner radius step. Maps to a --radius-* token via --df-input-radius. |
| cornerShape | "round" | "smooth" | - | Instance corner curve. Omit to inherit --df-corner-shape from the theme (set at create/init). |
| focusVariant | "ring" | "border" | "ring" | ring uses the focus ring token. border uses a solid focus outline only. |
| focusBorderColor | string | - | Focus border color when focusVariant is border. Prefer tokens such as var(--foreground). Sets --df-input-focus-border. |
| invalid | boolean | false | Validation state. Sets aria-invalid and applies the destructive border with --focus-ring-error. Hint text stays muted. |
| invalidLabel | boolean | true | When invalid is true, tint the owned label with the error color. Set false to keep the label at its normal color. |
| errorBorderColor | string | - | Invalid border color. Prefer tokens such as var(--destructive). Sets --df-input-error-border. |
| errorLabelColor | string | - | Owned label color when invalid and invalidLabel are true. Prefer tokens such as var(--destructive). Sets --df-input-error-label. |
| leadingIcon | ReactNode | - | Decorative icon at the start of the field. |
| trailingIcon | ReactNode | - | Icon or control at the end of the text area. Allows interaction for show and hide controls. |
| clearable | boolean | false | Show a clear control on the trailing edge when the field has a value. Hidden while disabled or readOnly. |
| onClear | () => void | - | Called when the clear control is activated. |
| prefix | ReactNode | - | Static start addon inside the field. Muted and non-editable. Not part of the input value. Use for schemes such as https://. |
| suffix | ReactNode | - | Static end addon inside the field. Same rules as prefix. |
| addonColor | string | - | Prefix and suffix color. Prefer tokens such as var(--muted-foreground). Sets --df-input-addon. |
| action | ReactNode | - | Attached end action for an input group. Typically a kit Button. Shares the field border with a vertical divider. |
| stepper | boolean | false | Show kit increment and decrement controls when the field is editable. Steps with ArrowUp, ArrowDown, and the control buttons. Honors min, max, and step. Hides browser spin buttons. Hidden when disabled or readOnly. With commitMode change, forces type number. With commitMode blur, keeps the type prop (default text) so empty and padded drafts remain editable. |
| incrementIcon | ReactNode | - | Icon for the increment control. Defaults to ChevronUp. Only used when stepper is true. |
| decrementIcon | ReactNode | - | Icon for the decrement control. Defaults to ChevronDown. Only used when stepper is true. |
| commitMode | "change" | "blur" | "change" | When onChange receives the field value. change fires on every keystroke. blur keeps a local draft while focused and commits on blur or Enter. Stepper buttons, ArrowUp, ArrowDown, and clear still commit immediately. If a controlled parent normalizes or rejects that value, the draft reconciles to the committed value. Prefer blur when the parent pads or clamps on commit. |
| hint | ReactNode | - | Helper line under the field. Wired with aria-describedby. Stays muted in the invalid state. |
| hintColor | string | - | Hint color. Prefer tokens such as var(--muted-foreground). Sets --df-input-hint. |
| type | string | "text" | Native input type (text, email, password, and others). |
| value | string | - | Controlled field value. |
| defaultValue | string | - | Uncontrolled initial field value. |
| placeholder | string | - | Empty-state hint text in the editable segment. |
| disabled | boolean | - | Non-interactive field. Muted fill, hairline border, and muted value text. |
| className | string | - | Additional styles on the outermost wrapper when the field is shelled, otherwise on the native input. |
DOM structure markers for styling and tests. These are not component props. data-df="input-root": Column wrapper when label, hint, or field chrome is present. data-df="input-field": Relative shell for icons, addons, action, and inside labels. data-empty marks an empty inside-label field. data-df="input-label": Inside-label title. data-df="input-prefix": Static start addon. data-df="input-suffix": Static end addon. data-df="input-icon": Icon slot. data-side is start or end. data-df="input-clear": Clear control on the trailing edge when clearable is active and the field has a value. data-df="input-stepper": Stacked increment and decrement controls when stepper is true. data-df="input-stepper-button": Stepper button. data-direction is up or down. data-df="input-action": Attached action for the input group. data-df="input-hint": Helper line under the field. data-df="input": Native input element. Also uses class df-input. data-commit-mode: Present with value blur when commitMode is blur. Omitted for change. data-border-width: Border width step on the field shell and native input: hairline, thin, or thick. data-hover-border: true or false when hoverBorder is set; omit to inherit the host theme.
Theme defaults live on :root. Override these globally or on a local host.
| Token | Type | Default | Notes |
|---|---|---|---|
| --df-input-bg | CSS color | var(--background) | Field fill. Set by variant or the background prop. |
| --df-input-border | CSS color | var(--input) | Field border. Set by variant or the borderColor prop. |
| --df-input-border-width | CSS length | var(--border-width-hairline) | Resolved field border width from the borderWidth step. |
| --border-width-hairline | CSS length | 1px | Hairline border width step. |
| --border-width-thin | CSS length | 1.5px | Thin border width step. |
| --border-width-thick | CSS length | 2px | Thick border width step. |
| --df-input-fg | CSS color | var(--foreground) | Value text color. |
| --df-input-placeholder | CSS color | var(--muted-foreground) | Placeholder color. |
| --df-input-autofill-bg | CSS color | color-mix(in oklch, var(--secondary) 45%, var(--background)) | Browser autofill fill. Applied to the field shell so the wash follows the field radius, including under leading and trailing icons. |
| --df-input-autofill-fg | CSS color | var(--df-input-fg) | Browser autofill value text color. |
| --df-input-hint | CSS color | var(--muted-foreground) | Hint line color. |
| --df-input-label | CSS color | var(--foreground) | Owned label color. |
| --df-input-addon | CSS color | var(--muted-foreground) | Prefix and suffix color. |
| --df-input-radius | CSS length | var(--radius-4xl) | Resolved corner radius from the radius prop. |
| --df-input-height | CSS length | var(--df-control-height-md) | Field height from size or height. Defaults to the md control height. |
| --df-input-font-size | CSS length | var(--df-text-sm) | Value and placeholder font size. Defaults to --df-text-sm. Size steps override this token. |
| --df-input-line-height | CSS length | var(--df-leading-5) | Value and placeholder leading. Paired with the size step as an even pixel value so single-line text centers without sub-pixel drift. |
| --df-input-floating-min-height | CSS length | var(--df-control-height-xl) | Minimum height when labelPosition is inside so the floating label has room to rise. |
| --df-input-padding-top | CSS length | calc(1 * var(--spacing-unit)) | Top content padding. Set by padding, paddingY, or paddingTop. |
| --df-input-padding-right | CSS length | var(--df-control-content-inset-inline) | Right content padding. Set by padding, paddingX, or paddingRight. Defaults to --df-control-content-inset-inline. |
| --df-input-padding-bottom | CSS length | calc(1 * var(--spacing-unit)) | Bottom content padding. Set by padding, paddingY, or paddingBottom. |
| --df-input-padding-left | CSS length | var(--df-control-content-inset-inline) | Left content padding. Set by padding, paddingX, or paddingLeft. Icons and floating labels follow this inset. Defaults to --df-control-content-inset-inline. |
| --df-hover-border | CSS keyword | on | Theme field hover border. on paints the ink hover border; off keeps the resting border. Runtime gating uses data-df-hover-border on html. Set with df-ui init --hover-border. Default on. |
| --df-input-hover-border | CSS color | var(--foreground) | Hover border when the theme or instance enables hover. Defaults to the ink foreground. Override with hoverBorderColor. |
| --df-input-focus-border | CSS color | var(--foreground) | Solid focus border when focusVariant is border. |
| --df-input-error-border | CSS color | var(--destructive) | Invalid border color. |
| --df-input-error-label | CSS color | var(--destructive) | Owned label color when invalidLabel is active. |
| --input | CSS color | var(--df-neutral-100) | Default border token. |
| --ring | CSS color | var(--df-neutral-400) | Ring focus border color. |
| --focus-ring-width | CSS length | 3px | Shared spread for --focus-ring and --focus-ring-inset. |
| --focus-ring | CSS box-shadow | 0 0 0 var(--focus-ring-width) color-mix(in oklch, var(--ring) 50%, transparent) | Outer ring focus glow for controls with surrounding space. |
| --focus-ring-inset | CSS box-shadow | inset 0 0 0 var(--focus-ring-width) color-mix(in oklch, var(--ring) 50%, transparent) | Inset ring focus glow for dense rows inside overflow scrollports (for example Sidebar menus). |
| --focus-ring-error | CSS box-shadow | 0 0 0 var(--focus-ring-width) color-mix(in oklch, var(--destructive) 20%, transparent) | Invalid glow. |
| --destructive | CSS color | var(--df-destructive) | Invalid label and default error border. |
| --background | CSS color | var(--df-neutral-0) | Primary fill default. |
| --secondary | CSS color | var(--df-neutral-50) | Secondary variant wash source. |
| --secondary-foreground | CSS color | var(--df-neutral-850, var(--df-neutral-900)) | Secondary variant value text. |
| --muted | CSS color | var(--df-neutral-50) | Disabled fill default. |
| --muted-foreground | CSS color | var(--df-neutral-500) | Disabled value text. |
| --foreground | CSS color | var(--df-neutral-900) | Default text color. |
| --df-corner-shape | CSS corner-shape | var(--df-corner-shape-round) | Theme corner curve for all kit chrome. round = circular arcs; smooth = continuous squircle. Set with df-ui init --corner-shape, or override on :root. Default round. |