Components / inputs
Tag Input
A text field where each entry becomes a removable tag: type and press Enter or a separator, or paste a list.
import { TagInput } from '@basiiik/ui';
The snippet an agent gets
From get_component_snippet, with the required props filled in from the spec. Every snippet is type-checked against the library before it is shipped.
import { TagInput } from '@basiiik/ui';
<TagInput label="Invite teammates" />- Example values were filled in for the required prop label: replace them with your own.
- Hover and Focused are CSS. Error is the
errorprop, or a rejected entry (the messagevalidatereturns). Disabled uses the disabled attribute. Filled is one or more entries, shown as tags. Needslabeloraria-label. - Compose with: tag.
- Storybook: Inputs/Tag Input.
Props
| Prop | Type | Notes |
|---|---|---|
size | "sm" | "md" | Default "md" |
label | ReactNode | |
helperText | ReactNode | |
placeholder | native attribute | |
error | ReactNode | |
disabled | native attribute | |
aria-label | string | |
aria-labelledby | string |
Other props
| Prop | Type | What it does |
|---|---|---|
max | number | The most entries allowed. |
values | string[] | The entries (controlled), in the order they were added. |
defaultValues | string[] | |
onValuesChange | (values: string[]) => void | |
separators | string | Characters that end an entry when typed or pasted. Default ",;\n". Add a space for things that never contain one, such as email addresses. Enter always ends an entry. In JSX pass an expression, separators={",; \n"}: inside a quoted attribute JSX does not unescape, so \n there would be a backslash and the letter n. A backslash-n or backslash-t written that way is read as a newline or a tab, so the mistake cannot turn every "n" into a separator. |
validate | (value: string) => boolean | string | Checks one entry. Return true to accept it, or false or a message to reject it: a rejected entry stays in the field with the message shown. |
allowDuplicates | boolean | Allow the same entry twice. Default false: a repeat (ignoring case) is ignored with a message. |
addOnBlur | boolean | Add what is typed when the field loses focus, so an entry is not lost when someone tabs away. Default true. |
formatAdded | (added: string[], count: number) => string | Announced when entries are added, for translation. Default: "ada@example.com added, 3 in total". |
formatRemoved | (value: string, count: number) => string | Announced when an entry is removed. Default: "ada@example.com removed, 2 in total". |
formatRejected | (value: string, reason: TagInputRejection, message?: string) => string | The message for a rejected entry (also announced). message is the text validate returned, if any. |
formatRemove | (value: string) => string | Accessible name of an entry's remove control. Default: "Remove ada@example.com". |
name | string | Name for a form: submits one value per entry. |
States. Hover and Focused are CSS. Error is the error prop, or a rejected entry (the message validate returns). Disabled uses the disabled attribute. Filled is one or more entries, shown as tags. Needs label or aria-label.
Native attributes such as className, id and data-* are forwarded to the root element.
Use it when
- Collect a list of free-text entries: email addresses to invite, keywords, skills, labels
- Entries someone may paste in bulk
- A list where each entry must pass a check (valid email, no spaces)
Do not use it when
- The entries come from a fixed list (use Multi Combobox)
- One value only (use Text Field)
- A few known options (use Checkbox)
- Long text or sentences (use Textarea)
- Entries that need more than a name, such as a name and a role (use a Table of rows with a Text Field)
Rules for agents
- The value is a list of strings: pass
values(ordefaultValues) andonValuesChange(values); the typed text is not part of the value until it is added - Needs a
labeloraria-label, like every field - For email addresses pass
separators={",; \n"}as a JSX expression in braces (a space ends an entry too) and avalidatethat returnstrue, or a message to reject:(v) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v) || 'Enter a valid email address' - Do not validate on your side after the fact:
validatekeeps the bad entry in the field with its message, so people can fix it - Set
maxwhen the count matters; setallowDuplicatesonly when a repeat is meaningful - Use
nameto submit one form field per entry - Say how to add in the helper text ("Press Enter or comma after each address, or paste a list"); the field does not show a hint of its own
- Use
errorwith a message when a required field has no entries (for example after a failed submit);requiredis met by one entry
Avoid
- Hand-building tags with Tag next to a Text Field and your own add logic
- Using it to pick from known options (use Multi Combobox)
- A comma-separated string in a Text Field that you split on submit
- A validate that silently drops the entry (return a message so people know why)
- Space as a separator for entries that can contain spaces (names, skills)
- Writing
separators=",; \n"as a quoted JSX attribute: JSX does not unescape, so it is a backslash and the letter n (the component reads a backslash-n as a newline, but write it in braces)
Writing the content
- Label: a plural noun or an action: "Invite teammates", "Skills"
- Placeholder: an example of one entry: "name@example.com"
- Helper text: how to add them, not what they are
Keyboard
- Enter, comma or semicolon ends an entry (more separators with
separators); Enter in an empty field is not swallowed, so a form can still submit - Backspace in an empty field removes the last tag
- Escape clears the typed text; the tags stay
- Each tag has a remove button in the tab order; Delete or Backspace on it removes the tag
Accessibility
- A labelled text field; the tags are buttons named "Remove ada@example.com" (translate with
formatRemove) - Every addition, removal and rejection is announced politely with the count (translate with
formatAdded,formatRemoved,formatRejected) - A rejected entry sets aria-invalid and its message is the field's description
Colour tokens it reads
color.bg.disabledcolor.bg.subtlecolor.bg.surfacecolor.border.dangercolor.border.defaultcolor.border.focuscolor.border.inputcolor.border.subtlecolor.text.dangercolor.text.disabledcolor.text.primarycolor.text.secondarycolor.text.tertiaryRelated
inputs 10 Figma variants Try it in the live demo