import { TagInput } from "@elabs-ai/components-ui";npm install @elabs-ai/components-tokens @elabs-ai/components-uiPrompt for your coding agent
Paste it into Claude Code, Cursor, Codex or any other coding agent. Text in [brackets] is yours to fill in.
Add the brand-ui TagInput component (from @elabs-ai/components-ui) to this project. 1. Read https://elabs-ai.com/llms.txt first: it maps every package and the rules. If you can use MCP servers, connect https://elabs-ai.com/mcp and use its search, docs and tokens tools. If not, run the same lookups in the terminal: `npx -y @elabs-ai/components-cli search "<what you need>"` and `npx -y @elabs-ai/components-cli docs <Component>`. 2. Look TagInput up before writing code: `npx -y @elabs-ai/components-cli docs TagInput` prints its real props, variants, what it pairs with and what to avoid. 3. If @elabs-ai/components-ui is not installed yet: `pnpm add @elabs-ai/components-tokens @elabs-ai/components-ui` (or `npm install @elabs-ai/components-tokens @elabs-ai/components-ui`). If this is the first brand-ui package in the project, wire it once: import `@elabs-ai/components-tokens/styles.css` plus the `themes/light.css` and `themes/dark.css` stylesheets in the CSS entry, add one Tailwind `@source` line per installed @elabs-ai package (Tailwind does not scan node_modules, so without it everything renders unstyled), and wrap the app root in `ThemeProvider` from `@elabs-ai/components-tokens`. 4. Use it here: [the screen or file, and what it should show] 5. Rules: use only @elabs-ai/components-* components and the semantic tokens — no raw colours, no raw font sizes, no arbitrary Tailwind values. Look up each component's real props with the docs tool before you use it; never guess a prop. 6. Done means: the typecheck passes, `npx -y @elabs-ai/components-cli audit src --strict` reports nothing, and you have opened the app and looked at every screen you touched in the light and the dark theme.
Examples
Controlled
With Max
With Validation
Allow Duplicates
Disabled
Empty
Addresses
An address list: space and semicolon add too, everything is lower-cased, a tag that is not an e-mail gets a flag and the `destructive` badge, and the field commits on blur.
API
TagInput
| Prop | Type | Description |
|---|---|---|
value | string[] | Controlled tag list. |
defaultValue | string[] | Uncontrolled initial tag list. |
onValueChange | (value: string[]) => void | Called when the tag list changes. |
max | number | Maximum number of tags allowed. |
validate | (tag: string) => boolean | string | Validate a candidate tag before it is added. Return `true` to accept, `false` to silently reject, or a string to reject and show as an inline error message. |
delimiter | string[] | Characters (or strings) that trigger tag creation in addition to Enter. Defaults to `[","]`. |
allowDuplicates | boolean | Allow duplicate tags (default false). |
placeholder | string | Placeholder text for the entry field. |
disabled | boolean | Whether the input is disabled. |
id | string | id for the underlying text input (useful for external <label>). |
name | string | Name forwarded to the underlying input. |
inputMode | InputHTMLAttributes<HTMLInputElement>["inputMode"] | `inputMode` of the underlying text input (`"email"` for an address list). |
normalize | (tag: string) => string | Canonical form of a tag before it is compared and stored — lower-casing an e-mail address, say. Runs after trimming. |
addOnBlur | boolean | Commit whatever is typed when the field loses focus (default false). |
renderTag | (tag: string, index: number) => ReactNode | The chip's content. Default: the tag text. Use it to put a control beside the tag (a role picker per address); the remove button stays the input's. |
tagVariant | (tag: string, index: number) => Pick<BadgeProps, "variant" | "appearance"> | The chip's `Badge` look per tag — a flagged address can read `{ variant: "destructive", appearance: "tint" }`. Default: `secondary`. |