# Combobox

> Searchable select for long lists, single or multiple, with optional create.

Component · Forms · Pro kit · [Live page](https://ui.twentyfirst.media/pro/components/Combobox/)

Searchable select for long lists, single or multiple, with optional create. `TagInput` is the free-text sibling for tags.

Combobox props: `label`, `options` (strings or {value, label, hint, icon, avatar}), `value`/`defaultValue`, `onChange`, `multiple`, `creatable`, `placeholder`, `hint`, `error`, `required`.
TagInput props: `label`, `value`/`defaultValue` (string[]), `onChange`, `placeholder`, `hint`.

- Keyboard: ↑ ↓ to move, Enter to pick, Esc to close, Backspace removes the last token.
- Up to five fixed options without search: use RadioGroup or a native Select instead.
- Selected items in `multiple` show as tokens inside the field; keep their labels short.
- Show a `hint` on people (team, email) so two people with the same name can be told apart.

## Example

```tsx
import * as React from "react";
import { Combobox, TagInput } from "@twentyfirstmedia/pro";

const TZ = [
  "Europe/Berlin (UTC+1)",
  "Europe/London (UTC+0)",
  "Asia/Dubai (UTC+4)",
  "Asia/Singapore (UTC+8)",
  "America/New_York (UTC−5)",
  "America/Los_Angeles (UTC−8)",
];
const PEOPLE = [
  {
    value: "ava",
    label: "Ava Vogel",
    hint: "Engineering",
    avatar: true,
  },
  {
    value: "ben",
    label: "Ben Okafor",
    hint: "Sales",
    avatar: true,
  },
  {
    value: "clara",
    label: "Clara Haddad",
    hint: "Design",
    avatar: true,
  },
  {
    value: "elif",
    label: "Elif Sato",
    hint: "Engineering",
    avatar: true,
  },
];
function App() {
  const t = React.useState<string | string[] | null>("Asia/Dubai (UTC+4)"),
    p = React.useState<string | string[] | null>(["ava", "clara"]),
    tags = React.useState(["urgent", "q3"]);
  return (
    <div
      className="tf-panel tf-grid"
      style={
        {
          "--cols": "1fr 1fr",
          gap: 16,
          alignContent: "start",
        } as React.CSSProperties
      }
    >
      <Combobox
        label="Time zone"
        options={TZ}
        value={t[0]}
        onChange={t[1]}
        placeholder="Search time zones"
      />
      <Combobox
        label="Reviewers"
        multiple
        options={PEOPLE}
        value={p[0]}
        onChange={p[1]}
        placeholder="Add people"
      />
      <Combobox
        label="Label"
        creatable
        options={["Customers", "Agents", "Finance"]}
        placeholder="Pick or create"
        hint="Type a new name to create it"
      />
      <TagInput label="Tags" value={tags[0]} onChange={tags[1]} />
    </div>
  );
}
export default App;
```

## Props

### Combobox

| Prop | Type | Notes |
| --- | --- | --- |
| `label?` | `string` |  |
| `options` | `(string \| Option)[]` | Required |
| `value?` | `string \| string[] \| null` |  |
| `defaultValue?` | `string \| string[]` |  |
| `onChange?` | `(v: string \| string[] \| null) => void` |  |
| `multiple?` | `boolean` |  |
| `creatable?` | `boolean` |  |
| `placeholder?` | `string` |  |
| `hint?` | `string` |  |
| `error?` | `string` |  |
| `required?` | `boolean` |  |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |

### TagInput

| Prop | Type | Notes |
| --- | --- | --- |
| `label?` | `string` |  |
| `value?` | `string[]` |  |
| `defaultValue?` | `string[]` |  |
| `onChange?` | `(v: string[]) => void` |  |
| `placeholder?` | `string` |  |
| `hint?` | `string` |  |
| `error?` | `string` |  |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |
