# Token input (UI SDK): Controller

> A controller from `createTokenInputController()` inserts, updates and removes tokens from code. Pass a promise as `resolve` to keep a token pending until it settles.

Canonical: https://hextaui.com/docs/ui-sdk-token-input/examples/controller

Component docs: https://hextaui.com/docs/ui-sdk-token-input

## Add this example

```bash
npx shadcn@latest add https://hextaui.com/r/ui-sdk-token-input-controller.json
```

This adds `components/examples/ui-sdk-token-input/controller.tsx` with the Token input component and the HextaUI theme tokens.

## Source

```tsx title="components/examples/ui-sdk-token-input/controller.tsx"
"use client"

import * as React from "react"

import { Button } from "@/components/ui/button"
import {
  createTokenInputController,
  TokenInput,
  TokenInputEditor,
  type Token,
  type TokenInputValue,
} from "@/components/ui/ui-sdk-token-input"

const draft: TokenInputValue = [
  "Compare ",
  { type: "file", value: "src/routes.ts", label: "routes.ts" },
  " with ",
]

const loadFile = () => new Promise<void>((resolve) => setTimeout(resolve, 800))

function UiSdkTokenInputController() {
  const [prompt] = React.useState(createTokenInputController)
  const firstToken = () =>
    prompt
      .getValue()
      .find((segment): segment is Token => typeof segment !== "string")

  return (
    <div className="flex w-full max-w-md flex-col gap-3">
      <div
        className="flex flex-wrap gap-2"
        onMouseDown={(event) => event.preventDefault()}
      >
        <Button
          variant="outline"
          size="sm"
          onClick={() =>
            prompt.insert(
              { type: "file", value: "package.json", label: "package.json" },
              { at: "end", resolve: loadFile() }
            )
          }
        >
          Attach file
        </Button>
        <Button
          variant="outline"
          size="sm"
          onClick={() => {
            const token = firstToken()
            if (token) prompt.updateToken(token.id!, { label: token.value })
          }}
        >
          Show path
        </Button>
        <Button
          variant="outline"
          size="sm"
          onClick={() => {
            const token = firstToken()
            if (token) prompt.removeToken(token.id!)
          }}
        >
          Remove first
        </Button>
        <Button variant="ghost" size="sm" onClick={() => prompt.undo()}>
          Undo
        </Button>
        <Button variant="ghost" size="sm" onClick={() => prompt.clear()}>
          Clear
        </Button>
      </div>
      <TokenInput controller={prompt} defaultValue={draft}>
        <TokenInputEditor aria-label="Prompt" />
      </TokenInput>
    </div>
  )
}

export { UiSdkTokenInputController }
```

## Props in this example

### TokenInput

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `defaultValue` | `TokenInputValue` | – |  |
| `controller` | `TokenInputController` | – | From createTokenInputController(). |

## More Token input examples

- [Prompt](https://hextaui.com/docs/ui-sdk-token-input/examples/prompt)
- [Deleting tokens](https://hextaui.com/docs/ui-sdk-token-input/examples/deletion)
- [Form](https://hextaui.com/docs/ui-sdk-token-input/examples/form)
- [Submit shortcut](https://hextaui.com/docs/ui-sdk-token-input/examples/submit-shortcut)
- [Custom codec](https://hextaui.com/docs/ui-sdk-token-input/examples/codec)
- [Disabled](https://hextaui.com/docs/ui-sdk-token-input/examples/disabled)
- [Read-only](https://hextaui.com/docs/ui-sdk-token-input/examples/read-only)
- [Right to left](https://hextaui.com/docs/ui-sdk-token-input/examples/rtl)
