# Build a Tags / Chip Input Component

Source: https://www.techinterview.org/post/3233475317/build-tags-chip-input-component/
Updated: 2026-06-30 · techinterview.org

"Build a tags input" is a frontend machine-coding question that looks easy and rewards careful thinking. The user types, hits Enter or comma, and the text becomes a styled chip; backspace removes the last chip; paste inserts multiple chips. Used in Gmail recipients, Stack Overflow tags, Linear labels, GitHub repo topics. The interview signals are pointer/keyboard handling, paste parsing, and accessibility.

## Clarify scope

- Free-text tags, or pick from a list (autocomplete)?

- Allow duplicates?

- Validate format (no spaces, max length, alphanumeric)?

- Editable chips (click to edit) or static?

- Drag-to-reorder?

## Architecture

One component, three concerns:

- State: array of tag strings

- Input: a contenteditable or input that lives at the end

- Render: chips before the input, with delete X on each

## Adding a tag

Trigger on:

- Enter key (preventDefault to avoid form submit)

- Comma typed — strip the comma, add the tag

- Tab (Gmail-style commit-and-move-on)

- Blur of the input (commit pending text)

Validate before committing: trim, check length, check format, check duplicate. Show inline error if invalid; do not silently drop input.

## Removing a tag

- Click the X on the chip

- Backspace when input is empty: select last chip; second backspace deletes it (Gmail pattern)

- Selected-chip delete: arrow keys navigate chips, Enter or Delete removes

## Paste handling

Paste is where junior implementations break:

- User pastes "alice@x.com, bob@y.com, charlie@z.com" — should produce three chips

- User pastes "single value" — produces one chip

- User pastes "  spaced , values  " — trim and split, drop empties

Split on common separators (comma, semicolon, newline, tab). Validate each. Reject invalid ones with a clear summary ("3 added, 2 invalid: ...").

## Autocomplete variant

If picking from a list, layer in the combobox pattern:

- Dropdown of matching options below the input

- Arrow keys navigate

- Enter inserts highlighted option

- Free-text creation as a special "+ Create new" item at the bottom

## Accessibility — the WAI-ARIA pattern

- Container has `role="combobox"` when autocomplete; otherwise just a labeled group

- Each chip is `role="button"` with explicit label "Remove tag X"

- Selected chip has `aria-selected` when keyboard-navigated

- Live region announces additions and removals (`aria-live="polite"`)

- Visible focus ring on the focused chip or input

## Visual states

- Default: pale background, dark text, X on hover

- Selected (keyboard nav): primary color border

- Invalid: red border + tooltip with reason

- Dragging (if reorderable): elevation / shadow

## Mobile considerations

- Comma key on mobile keyboards is buried; rely on the soft "Done" / Enter

- Backspace-to-delete-chip is awkward on mobile; rely on the X button being big enough

- Paste is more common on mobile than desktop in some flows; test it

## Edge cases interviewers love

- User types past the input width — chips wrap to next line

- User pastes 1000 emails — show progress, validate in chunks, do not freeze the UI

- IME composition (Japanese, Chinese) — do not commit on Enter during composition

- Initial value with already-set tags — render correctly on mount

## What separates senior from staff

Junior: types and removes work. Senior: paste handles bulk input cleanly, accessibility is correct, validation is meaningful. Staff: discusses the API for a controlled vs uncontrolled component, the typing surface for valid tag types (string, object, custom), and the upstream error handling integration.

## Frequently Asked Questions

### Library options for production?

react-tag-input, react-select (creatable variant), or downshift for a custom build. Most senior teams roll their own because requirements diverge enough to make libraries painful.

### How do I handle "too many tags"?

Cap and show "+N more" after a threshold; or scroll horizontally; or drop oldest. Whichever you pick, surface the limit in the UI before they hit it.

### Should chips be editable?

Click-to-edit is nice but adds complexity. Most products skip it; users delete and retype.
