Input

Text, textarea, dimension, and tag fields with built-in label, hint, and error treatment.

*

The project type will be added automatically

*

Unavailable.

Installation
$Terminal
npx shadcn@latest add https://sdk-components.thesqd.com/r/input.json
Usage
Each field is a single component that owns its label, hint, and error treatment. Drop in `iconLeading` / `iconTrailing` for inline glyphs.
TSImport
import {
  TextField,
  TextareaField,
  NumberInput,
  FileSizeInput,
  TagsInput,
  DurationInput,
  RepeatableInput,
} from "@/components/ui/input";
TSExample
import { SearchIcon } from "lucide-react";
import { TextField } from "@/components/ui/input";

export function Example() {
  return (
    <TextField
      label="Project title"
      placeholder="Enter project title…"
      caption="The project type will be added automatically."
      iconLeading={SearchIcon}
      required
    />
  );
}
Composition
Anatomy of the input primitives.
TextField                       (label + caption + input in one component)
├── Label                       (renders if `label` is passed)
├── Caption                     (renders if `caption` is passed — under the label)
├── (iconLeading)               (lucide icon component)
├── <input>
├── (iconTrailing)              (lucide icon component)
└── error                       (rendered below the control in red)

TextareaField                   (same surface, multi-line + optional character count)
FileSizeInput                   (width × height + unit selector)
TagsInput                       (chip list driven by Enter / Tab / , / paste)
DurationInput                   (segmented d/h/m/s field, value in total seconds)
Text field
Compound component with label, hint, and error — ported from PRF4’s Untitled UI field.
*

The project type will be added automatically

*

Unavailable.

Input types
Every native HTML type the team regularly reaches for, using the shadcn Input primitive.

Your unique identifier

Validates format on blur.

US format auto-applies as you type.

Must be at least 8 characters

3- or 4-digit account number.

Number field
Numeric input with stepper buttons. Pass `min`, `max`, and `step` for range/granularity. Drives the number-field renderer in @thesqd/dynamic-forms.

Maximum 50 seats per workspace.

File size
Width × height with a unit selector (inches, cm, mm, pixels, points). Pair with a Label for document dimensions, canvas sizes, or print bleeds.

Output: {"h":null,"w":null,"unit":"in"}

Output: {"h":null,"w":null,"unit":"px"}

pixels

Click the pencil to split into editable cards; ✓ to converge.

Textareas
Multi-line text input with and without validation.

Tell us a bit about yourself.

Uses Chrome's Web Speech API — button hides in other browsers.

Tags input
Multi-value input that commits each entry as a Squad Badge chip on Enter / Tab / comma. Backspace on an empty draft removes the previous chip; paste a comma- or newline-separated list to bulk-add.

Press Enter / Tab / , to add. Backspace to remove the last tag.

Sermon seriesEasterOutreach

The fourth tag is silently rejected.

VolunteersWorship
Duration input
Segmented time-duration field with configurable units (d/h/m/s). Segments auto-advance on fill and support keyboard navigation.

Total: 7384s

Repeatable input
A single input that grows into a list. Click the + ghost button next to any row to insert another input below it; the response is a `string[]`. Set `min` (defaults to 1) and an optional `max` to bound the row count.

Click + to add another URL. Outputs a string[].

Min 2, max 5.

Autocomplete
Pass `autocomplete` with a flat `items` array (`string[]` or `{ label, value }[]`) to turn the input into a suggest-as-you-type field. It filters live, reveals every option on focus, and shows a clear button once there's a value.
Autocomplete with descriptions
Add a `description` to any option to render a secondary line under the label — useful for disambiguating similar entries.
Autocomplete with icons
Add an `icon` to any option to render a leading glyph next to the label.
API Reference
Props exposed by each input primitive.

TextField

PropTypeDefaultDescription
labelstringRenders an associated <Label> above the input.
captionstringHelper copy shown below the input. Hidden when `error` is set.
errorstringError message — toggles the red focus ring + red helper line.
requiredbooleanMarks the label with a red asterisk.
iconLeadingComponentType<{ className?: string }>Lucide icon component rendered inside the leading slot.
iconTrailingComponentType<{ className?: string }>Lucide icon component rendered inside the trailing slot.
type"text" | "email" | "tel" | "password" | "url" | "number" | "search" | …"text"Native HTML type. `email` and `tel` get blur-time validation hooks.
invalidMessagestringError message to surface when the built-in email/tel validator rejects the value.
onValidityChange(valid: boolean) => voidFires with the result of the email/tel validator on blur.

TextareaField

PropTypeDefaultDescription
labelstringRenders an associated <Label> above the textarea.
captionstringHelper copy shown below the textarea.
errorstringError message — toggles the red treatment.
rowsnumber3Initial visible row count.
showCharacterCountbooleanRender a live character count in the trailing slot.
characterCountnumberOverride the displayed character count.
trailingContentReactNodeCustom node rendered below-right (e.g. dictation button).

NumberInput

PropTypeDefaultDescription
valuenumberControlled value.
defaultValuenumber0Uncontrolled initial value. When value is 0 the input displays empty (placeholder shown).
onValueChange(value: number) => voidFires with the parsed numeric value on every change.
minnumberLower bound — decrement button disables when reached.
maxnumberUpper bound — increment button disables when reached.
stepnumber1Amount added/subtracted per stepper click.
placeholderstring"0"Placeholder shown when the value is 0 or empty.
captionReactNodeHelper copy shown below the input via FieldHint. Hidden when `error` is set.
errorboolean | stringError state. `true` applies the destructive ring only; a string also renders the inline message (`text-xs mt-1.5 text-red-500`) below the input.
disabledbooleanDims the field and prevents interaction.

FileSizeInput

PropTypeDefaultDescription
value{ width, height, unit }Controlled value. Width and height are number | "" — unit is one of in/cm/mm/px/pt.
onChange(value) => voidFires whenever any of the three sub-fields change.
allowedUnitsArray<"in" | "cm" | "mm" | "px" | "pt">Restrict the unit dropdown — defaults to all five.
idstringForwarded to the width input for label association.

TagsInput

PropTypeDefaultDescription
valuestring[]Controlled tag list.
onChange(value: string[]) => voidFires whenever a tag is added or removed.
maxnumberCap the chip count. Extras are silently rejected.
placeholderstringPlaceholder rendered inside the draft input.
captionstringHelper text below the field.

DurationInput

PropTypeDefaultDescription
unitsArray<"d" | "h" | "m" | "s">["h","m","s"]Which segments to render, left-to-right.
valuenumberControlled value in total seconds.
defaultValuenumber0Uncontrolled initial value in total seconds.
onValueChange(totalSeconds: number) => voidFires with the parsed total seconds on every change.
disabledbooleanDims the field and prevents interaction.

RepeatableInput

PropTypeDefaultDescription
valuestring[]Controlled list of row values. The component outputs `string[]`.
defaultValuestring[]Uncontrolled initial list. Padded with empty strings up to `min`.
onChange(value: string[]) => voidFires whenever a row is added, removed, or edited.
typeHTMLInputType"text"Input type for every row — forwarded to the underlying TextField.
placeholderstringPlaceholder applied to each row's input.
minnumber1Minimum number of rows. The remove button hides when at the floor.
maxnumberOptional maximum. The + button disables once reached.
labelstringRenders the field label above the stack of inputs.
captionstringHelper text rendered directly under the label.
errorstringError message — toggles the red treatment on the first row.
requiredbooleanMarks the label with a red asterisk.
disabledbooleanDims every row and disables the +/− buttons.