

## Field Types [#field-types]

### InputField [#inputfield]

The most common field type for text input.

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="InputFieldSoloDemo" />
  </Tab>

  <Tab value="Code">
    ```tsx
    <InputField
      name="email"
      label="Email"
      description="We'll never share your email."
      tooltip="Used for account notifications"
      type="email"
      placeholder="Enter your email"
    />

    // Numeric coercion (Zod-friendly): when type="number", value is coerced to number
    <InputField
      name="qty"
      label="Quantity"
      description="Must be a number"
      tooltip="Must be a number"
      type="number"
    />

    // Or force coercion regardless of type via valueAsNumber
    <InputField
      name="qty"
      label="Quantity"
      description="Must be a number"
      tooltip="Must be a number"
      valueAsNumber
    />
    ```
  </Tab>
</Tabs>

Extends all native HTML input props plus:

| Prop            | Type                    | Description                                              |
| --------------- | ----------------------- | -------------------------------------------------------- |
| `name`          | `string`                | Form field name (simple API)                             |
| `field`         | `FieldApi`              | Field instance (advanced API)                            |
| `label`         | `React.ReactNode`       | Field label                                              |
| `description`   | `React.ReactNode`       | Helper text shown under the label                        |
| `tooltip`       | `React.ReactNode`       | Inline info icon content (shows on hover/focus)          |
| `size`          | `"sm" \| "md" \| "lg"`  | Input and field chrome size                              |
| `variant`       | `"default" \| "inline"` | Input visual variant                                     |
| `children`      | `React.ReactNode`       | Additional content (help text, etc.)                     |
| `valueAsNumber` | `boolean`               | Coerce to number on change; implied when `type="number"` |

### TextareaField [#textareafield]

Multi-line text input for longer content.

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="TextareaFieldSoloDemo" />
  </Tab>

  <Tab value="Code">
    ```tsx
    <TextareaField
      name="message"
      label="Message"
      placeholder="Type your message..."
      description="We'll never share your message."
      tooltip="Used for account notifications"
      rows={5}
    />
    ```
  </Tab>
</Tabs>

Extends all native HTML textarea props plus:

| Prop          | Type                   | Description                          |
| ------------- | ---------------------- | ------------------------------------ |
| `name`        | `string`               | Form field name (simple API)         |
| `field`       | `FieldApi`             | Field instance (advanced API)        |
| `label`       | `React.ReactNode`      | Field label                          |
| `description` | `React.ReactNode`      | Helper text under the label          |
| `tooltip`     | `React.ReactNode`      | Inline info icon content             |
| `size`        | `"sm" \| "md" \| "lg"` | Textarea and field chrome size       |
| `placeholder` | `string`               | Placeholder text                     |
| `children`    | `React.ReactNode`      | Additional content (help text, etc.) |

### CheckboxField [#checkboxfield]

Single checkbox for boolean values.

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="CheckboxFieldSoloDemo" />
  </Tab>

  <Tab value="Code">
    ```tsx
    <CheckboxField
      name="agree"
      label="I agree to the terms"
      description="We'll never share your message."
      tooltip="Used for account notifications"
    />
    ```
  </Tab>
</Tabs>

| Prop          | Type                   | Description                    |
| ------------- | ---------------------- | ------------------------------ |
| `name`        | `string`               | Form field name (simple API)   |
| `field`       | `BoolFieldApi`         | Field instance (advanced API)  |
| `label`       | `React.ReactNode`      | Checkbox label                 |
| `description` | `React.ReactNode`      | Helper text under the label    |
| `tooltip`     | `React.ReactNode`      | Inline info icon content       |
| `size`        | `"sm" \| "md" \| "lg"` | Checkbox and field chrome size |
| `className`   | `string`               | Additional classes             |

### SwitchField [#switchfield]

Toggle switch for boolean values.

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="SwitchFieldSoloDemo" />
  </Tab>

  <Tab value="Code">
    ```tsx
    <SwitchField
      name="notifications"
      label="Enable notifications"
      description="We'll never share your message."
      tooltip="Used for account notifications"
    />
    ```
  </Tab>
</Tabs>

| Prop          | Type                   | Description                   |
| ------------- | ---------------------- | ----------------------------- |
| `name`        | `string`               | Form field name (simple API)  |
| `field`       | `BoolFieldApi`         | Field instance (advanced API) |
| `label`       | `React.ReactNode`      | Switch label                  |
| `description` | `React.ReactNode`      | Helper text under the label   |
| `tooltip`     | `React.ReactNode`      | Inline info icon content      |
| `size`        | `"sm" \| "md" \| "lg"` | Switch and field chrome size  |
| `className`   | `string`               | Additional classes            |

### RadioGroupField [#radiogroupfield]

Group of radio buttons for single selection from multiple options.

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="RadioGroupFieldSoloDemo" />
  </Tab>

  <Tab value="Code">
    ```tsx
    <RadioGroupField
      name="plan"
      label="Select Plan"
      description="We'll never share your message."
      tooltip="Used for account notifications"
    >
      <Label htmlFor="plan-free" orientation="horizontal">
        <RadioGroupItem value="free" id="plan-free" />
        Free
      </Label>
      <Label htmlFor="plan-pro" orientation="horizontal">
        <RadioGroupItem value="pro" id="plan-pro" />
        Pro ($9/month)
      </Label>
    </RadioGroupField>
    ```
  </Tab>
</Tabs>

| Prop          | Type                   | Description                       |
| ------------- | ---------------------- | --------------------------------- |
| `name`        | `string`               | Form field name (simple API)      |
| `field`       | `StringFieldApi`       | Field instance (advanced API)     |
| `label`       | `React.ReactNode`      | Field label                       |
| `description` | `React.ReactNode`      | Helper text under the label       |
| `tooltip`     | `React.ReactNode`      | Inline info icon content          |
| `children`    | `React.ReactNode`      | `RadioGroupItem` children         |
| `className`   | `string`               | Additional classes                |
| `size`        | `"sm" \| "md" \| "lg"` | Radio group and field chrome size |

### SelectField [#selectfield]

Dropdown selection from multiple options.

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="SelectFieldSoloDemo" />
  </Tab>

  <Tab value="Code">
    ```tsx
    const currencyItems = [
      { label: "USD", value: "usd" },
      { label: "EUR", value: "eur" },
    ];

    <SelectField
      items={currencyItems}
      name="currency"
      label="Currency"
      labelSize="sm"
    >
      <SelectTrigger size="sm">
        <SelectValue placeholder="Select..." />
      </SelectTrigger>
      <SelectContent>
        {currencyItems.map((item) => (
          <SelectItem key={item.value} value={item.value}>
            {item.label}
          </SelectItem>
        ))}
      </SelectContent>
    </SelectField>
    ```
  </Tab>
</Tabs>

| Prop          | Type                                    | Description                                                                           |
| ------------- | --------------------------------------- | ------------------------------------------------------------------------------------- |
| `name`        | `string`                                | Form field name (simple API)                                                          |
| `field`       | `StringFieldApi`                        | Field instance (advanced API)                                                         |
| `label`       | `React.ReactNode`                       | Field label                                                                           |
| `description` | `React.ReactNode`                       | Helper text under the label                                                           |
| `tooltip`     | `React.ReactNode`                       | Inline info icon content                                                              |
| `labelSize`   | `"sm" \| "md" \| "lg"`                  | Form label, description, and message size                                             |
| `items`       | `{ label: ReactNode, value: string }[]` | Label map forwarded to `Select`; pass it when using the default `SelectValue` display |
| `children`    | `React.ReactNode`                       | Custom SelectTrigger/Value/Content/Items; control size lives on `SelectTrigger`       |
| `className`   | `string`                                | Additional classes for the wrapper                                                    |

### DateInputField [#dateinputfield]

Segmented date input bound to form state.

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="DateInputFieldSoloDemo" />
  </Tab>

  <Tab value="Code">
    ```tsx
    <DateInputField name="dob" label="Date of birth" />
    ```
  </Tab>
</Tabs>

| Prop          | Type                                 | Description                                                 |
| ------------- | ------------------------------------ | ----------------------------------------------------------- |
| `name`        | `string`                             | Form field name (simple API)                                |
| `field`       | `FieldApi&lt;Date\|string\|null&gt;` | Field instance (advanced API)                               |
| `label`       | `React.ReactNode`                    | Field label                                                 |
| `description` | `React.ReactNode`                    | Helper text under the label                                 |
| `tooltip`     | `React.ReactNode`                    | Inline info icon content                                    |
| `size`        | `"sm" \| "md" \| "lg"`               | Date input and field chrome size                            |
| `locale`      | `string`                             | Override the segmented input locale (defaults to `'en-AU'`) |
| `className`   | `string`                             | Additional classes for the wrapper                          |

### PhoneField [#phonefield]

Phone number input powered by the `PhoneInput` primitive (with country picker, search and flags). Stores values in canonical E.164 format. Defaults to AU for national input and supports international entry via leading `+`.

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="PhoneFieldSoloDemo" />
  </Tab>

  <Tab value="Code">
    ```tsx
    <PhoneField name="phone" label="Phone" description="We'll never share your message." tooltip="Used for account notifications" />

    // Set a different default country (still allows + for international)
    <PhoneField name="phone" label="Phone" defaultCountry="NZ" />
    ```
  </Tab>
</Tabs>

Note

* Includes a country selector combobox with flags and search; `defaultCountry` sets the initial country.
* Stores values in E.164 (canonical). With AU as default, entering 04xx… is saved as +61 4xx…; a leading + always accepts international.
* Built-in validation runs on blur using the phone library; an "Invalid phone number" message is shown until the number is valid, and cleared when empty/valid. Errors render like other fields via the form chrome.
* You can still add extra schema rules (e.g., AU-only mobiles) if needed.

| Prop             | Type                   | Description                                                             |
| ---------------- | ---------------------- | ----------------------------------------------------------------------- |
| `name`           | `string`               | Form field name (simple API)                                            |
| `field`          | `StringFieldApi`       | Field instance (advanced API)                                           |
| `label`          | `React.ReactNode`      | Field label                                                             |
| `description`    | `React.ReactNode`      | Helper text under the label                                             |
| `tooltip`        | `React.ReactNode`      | Inline info icon content                                                |
| `size`           | `"sm" \| "md" \| "lg"` | Phone input and field chrome size                                       |
| `className`      | `string`               | Additional classes for the wrapper                                      |
| `placeholder`    | `string`               | Placeholder for the phone input                                         |
| `disabled`       | `boolean`              | Disable the input                                                       |
| `readOnly`       | `boolean`              | Make the input read-only                                                |
| `defaultCountry` | `string`               | ISO 3166-1 alpha-2 country code used for national input (default: `AU`) |

### TagInputField [#taginputfield]

Multi-value input for managing tags (chips). Wraps the `TagInput` primitive and binds it to form state.

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="TagInputFieldSoloDemo" />
  </Tab>

  <Tab value="Code">
    ```tsx
    // Tag objects (default)
    <TagInputField name="topicObjects" label="Topic Objects" description="We'll never share your message." tooltip="Used for account notifications" />

    // String[] values (maps to Tag[] internally)
    <TagInputField name="topics" label="Topics" asStrings />


    // You can pass TagInput props too (e.g., Excel paste, ignore commas)
    <TagInputField
      name="skills"
      label="Skills"
      enableExcelPaste
      // Allow commas inside tags (typing + paste)
      enableCommaDelimiter={false}
      options={[{ id: "ts", label: "TypeScript" }, { id: "react", label: "React" }]}
      asStrings
    />
    ```
  </Tab>
</Tabs>

| Prop                   | Type                              | Description                                               |
| ---------------------- | --------------------------------- | --------------------------------------------------------- |
| `name`                 | `string`                          | Form field name (simple API)                              |
| `field`                | `TagsFieldApi \| StringsFieldApi` | Field instance (advanced API)                             |
| `label`                | `React.ReactNode`                 | Field label                                               |
| `description`          | `React.ReactNode`                 | Helper text under the label                               |
| `tooltip`              | `React.ReactNode`                 | Inline info icon content                                  |
| `size`                 | `"sm" \| "md" \| "lg"`            | Tag input and field chrome size                           |
| `options`              | `{ id: string; label: string }[]` | Predefined selectable tags                                |
| `placeholder`          | `string`                          | Placeholder for the input                                 |
| `className`            | `string`                          | Additional classes for the wrapper                        |
| `allowDuplicates`      | `boolean`                         | Allow duplicate tag labels (default: `false`)             |
| `enableExcelPaste`     | `boolean`                         | Split pasted CSV/TSV/newlines into tags (default: `true`) |
| `enableCommaDelimiter` | `boolean`                         | Comma key creates a tag (default: `true`)                 |
| `pasteDelimiters`      | `string[]`                        | Delimiters used when splitting pasted text                |
| `asStrings`            | `boolean`                         | Bind to `string[]` instead of `Tag[]`                     |

When provided, these sync the TagInputField’s tags to a string\[] URL parameter via TanStack Router search params.

| Prop                  | Type                              | Default | Description                                               |
| --------------------- | --------------------------------- | ------- | --------------------------------------------------------- |
| `paramName`           | `string`                          | —       | URL parameter name to sync. Enables URL state management. |
| `onUrlValueChange`    | `(value: string[]\|null) => void` | —       | Callback when URL parameter value changes.                |
| `paramClearOnDefault` | `boolean`                         | `true`  | Remove URL param when value equals default.               |
| `paramThrottle`       | `number`                          | —       | Throttle URL updates in milliseconds.                     |
| `paramDebounce`       | `number`                          | —       | Debounce URL updates in milliseconds.                     |

### SliderField [#sliderfield]

Range slider for numeric values.

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="SliderFieldSoloDemo" />
  </Tab>

  <Tab value="Code">
    ```tsx
    <SliderField
      name="volume"
      label="Volume"
      description="We'll never share your message."
      tooltip="Used for account notifications"
      valueLabel={true}
      min={0}
      max={100}
      step={10}
    />
    ```
  </Tab>
</Tabs>

| Prop          | Type                                                                    | Description                   |
| ------------- | ----------------------------------------------------------------------- | ----------------------------- |
| `name`        | `string`                                                                | Form field name (simple API)  |
| `field`       | `NumberFieldApi`                                                        | Field instance (advanced API) |
| `label`       | `React.ReactNode`                                                       | Field label                   |
| `description` | `React.ReactNode`                                                       | Helper text under the label   |
| `tooltip`     | `React.ReactNode`                                                       | Inline info icon content      |
| `valueLabel`  | `boolean \| React.ReactNode \| ((props: {value: string}) => ReactNode)` | Show current value            |
| `min`         | `number`                                                                | Minimum value                 |
| `max`         | `number`                                                                | Maximum value                 |
| `step`        | `number`                                                                | Step increment                |

### AutocompleteField [#autocompletefield]

Text input with real-time suggestions and filtering. Wraps the `Autocomplete` primitive and binds it to form state.

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="AutocompleteFieldSoloDemo" />
  </Tab>

  <Tab value="Code">
    ```tsx
    const locations = [
      { id: "1", label: "New York" },
      { id: "2", label: "London" },
      { id: "3", label: "Tokyo" },
    ];

    <AutocompleteField
      name="location"
      label="Location"
      description="Select your preferred location"
      tooltip="Where you want to work"
      items={locations}
      itemToString={(loc) => loc.label}
      itemToKey={(loc) => loc.id}
      placeholder="Search locations..."
      emptyMessage="No locations found"
    />;

    // Simple string array
    const tags = ["React", "TypeScript", "Next.js"];

    <AutocompleteField
      name="tag"
      label="Tag"
      items={tags}
      itemToString={(tag) => tag}
      placeholder="Search tags..."
    />;
    ```
  </Tab>
</Tabs>

| Prop           | Type                   | Description                                                      |
| -------------- | ---------------------- | ---------------------------------------------------------------- |
| `name`         | `string`               | Form field name (simple API)                                     |
| `field`        | `StringFieldApi`       | Field instance (advanced API)                                    |
| `label`        | `React.ReactNode`      | Field label                                                      |
| `description`  | `React.ReactNode`      | Helper text under the label                                      |
| `tooltip`      | `React.ReactNode`      | Inline info icon content                                         |
| `size`         | `"sm" \| "md" \| "lg"` | Autocomplete input and field chrome size                         |
| `items`        | `T[]`                  | Array of items to display. **Required**                          |
| `itemToString` | `(item: T) => string`  | Convert item to display string. **Required**                     |
| `itemToKey`    | `(item: T) => string`  | Get unique key for each item (defaults to itemToString)          |
| `placeholder`  | `string`               | Placeholder text                                                 |
| `emptyMessage` | `string`               | Message shown when no items match (default: "No results found.") |
| `disabled`     | `boolean`              | Disable the autocomplete                                         |
| `required`     | `boolean`              | Mark the field as required (adds aria-required)                  |
| `readOnly`     | `boolean`              | Make the autocomplete read-only                                  |
| `autoFocus`    | `boolean`              | Auto-focus the input on mount                                    |
| `compact`      | `boolean`              | Hide label, description, and error messages                      |
| `className`    | `string`               | Additional classes for the wrapper                               |

Note: This field also accepts all props from the underlying `Autocomplete` primitive (e.g., `autoHighlight`, `filter`, `open`, `onOpenChange`). See the [Autocomplete documentation](/primitives/autocomplete) for full details.

### Compact Mode [#compact-mode]

Use `compact` for dense layouts like data grids where you want just the input without chrome:

```tsx
// Standard mode - shows label, description, errors
<InputField name="email" label="Email" description="Your work email" />

// Compact mode - input only, no chrome
<InputField name="email" compact />
```

<Callout type="info">
  Compact mode is primarily used internally by the `FormBuilder.Bulk` grid
  component for inline editing.
</Callout>

## Dual Prop API [#dual-prop-api]

All field components accept either:

* **`name`**: Automatically binds to form context (recommended for most use cases)
* **`field`**: Direct field API control (for advanced scenarios)

| Prop API | Use Case                              | Example                                                                                               |
| -------- | ------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `name`   | Standard fields, clean syntax         | `&lt;InputField name="email" label="Email" /&gt;`                                                     |
| `field`  | Custom logic, validation state access | `&lt;form.Field name="email"> {(field) =&gt; &lt;InputField field={field} /&gt;} &lt;/form.Field&gt;` |
