Addable text list
Reveal-on-click input for capturing a list of single-line, unstructured text values.
AddableTextList is the lightest primitive in the addable family. Each row is one short string — services offered, tags, back-office tools. The input is hidden until the user clicks Add New, then Enter commits and re-focuses for rapid entry, Escape cancels.
AddableTextList
Use when: One short, unstructured string per row. No vocabulary.
Don't: Vocabulary or structure — use a sibling.
<AddableTextList values={...} onChange={...} />AddableComboList
Use when: One string per row, picked from a known vocabulary (with optional free-form fallback).
Don't: No vocabulary — use AddableTextList.
<AddableComboList suggestions={...} />AddableEntryList
Use when: Each row needs a primary + secondary (URL + notes, name + description).
Don't: Single value — use TextList/ComboList.
<AddableEntryList entries={...} />For 2+ structured fields per row, use AddableFieldRowList.
Use it for
- Services offered (free-form, no catalog)
- Tags / labels on a record
- Back-office tools, integrations the user types from memory
- Any short-string list where capture speed matters more than structure
Import
import { AddableTextList } from '@brikdesigns/bds';Variants
Default
import { useState } from 'react';
const [values, setValues] = useState<string[]>([]);
<AddableTextList
label="Services offered"
values={values}
onChange={setValues}
placeholder="Add a service…"
addLabel="Add service"
/>With helper text + max items
<AddableTextList
label="Back-office tools"
helperText="Up to 5 tools — CRM, billing, scheduling, etc."
values={values}
onChange={setValues}
maxItems={5}
/>Sizes
sm, md (default), lg — match TextInput sizes for inline placement.
Disabled (read-only)
Renders tags without input or remove controls.
<AddableTextList values={values} onChange={() => {}} disabled />Allow duplicates
By default duplicates are blocked case-insensitively. Set allowDuplicates if dupes are meaningful (e.g. quantity-by-repeat patterns).
<AddableTextList values={values} onChange={setValues} allowDuplicates />Behavior
- Enter commits the trimmed value and keeps the input open for the next entry.
- Escape or blur on empty cancels and hides the input.
- Duplicates are blocked case-insensitively unless
allowDuplicatesis set. - When
maxItemsis reached, the Add button is hidden.
When not to use
Don't use AddableTextList for title + description pairs. This component console-warns in dev when any value contains structural separators (—, –, :, newline, tab) — that's the signal you reached for the wrong primitive. Use AddableEntryList.
- Don't use AddableTextList when a vocabulary exists. If the values come from a BCS getter or locked enum, use AddableComboList — users get autocomplete and you get consistent values.
- Don't use AddableTextList for ≥3 structured fields. Use AddableFieldRowList.
Accessibility
- Each tag is a
<li>with a labeled remove button (removeLabel, defaults to "Remove"). - Reveal input has
role="textbox"with platform-native autocomplete. - The Add button is a real
<button>— keyboard, focus, all platform.
API
| Prop | Type | Default |
|---|---|---|
values | string[] (required) | — |
onChange | (next: string[]) => void (required) | — |
label | string | — |
helperText | string | — |
placeholder | string | — |
addLabel | string | 'Add' |
emptyLabel | string | — |
size | 'sm' | 'md' | 'lg' | 'md' |
disabled | boolean | false |
maxItems | number | unlimited |
allowDuplicates | boolean | false |
Related
- AddableComboList — vocabulary-backed sibling
- AddableEntryList — primary + secondary sibling
- AddableFieldRowList — multi-field sibling
- Tag — the chip rendered for each value
- Storybook playground