Build a Tags / Chip Input Component

“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:

  1. State: array of tag strings
  2. Input: a contenteditable or input that lives at the end
  3. 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.

Scroll to Top