AniUI Academy
medium+190 XP

Build a tag input

Build an input that turns whatever you type into a removable tag when you press Enter.

Pressing Backspace while the input is empty removes the most recently added tag, rather than doing nothing.

Requirements

  • A `<input id="tag-input">` for typing new tags.
  • Each tag renders as `<span data-testid="tag">text</span>` inside a container `data-testid="tag-list"`, in the order added.
  • Pressing Enter with non-empty input text adds it as a new tag and clears the input.
  • Pressing Enter with only whitespace, or an empty input, adds nothing.
  • Each tag has a `<button data-testid="remove-tag">` that removes just that tag.
  • Pressing Backspace while the input is empty removes the last tag in the list.

Your workspace

import { useState } from "react";

export default function App() {
  const [tags, setTags] = useState([]);
  const [value, setValue] = useState("");

  function handleKeyDown(e) {
    // TODO: Enter with non-empty (non-whitespace-only) text adds a tag
    // and clears the input. Backspace with an empty input removes the
    // last tag.
  }

  function removeTag(index) {
    setTags((current) => current.filter((_, i) => i !== index));
  }

  return (
    <div style={{ fontFamily: "sans-serif", padding: 16 }}>
      <div
        data-testid="tag-list"
        style={{ display: "flex", flexWrap: "wrap", gap: 6, marginBottom: 8 }}
      >
        {tags.map((tag, index) => (
          <span
            key={index}
            data-testid="tag"
            style={{ background: "#eee", padding: "4px 8px", borderRadius: 12 }}
          >
            {tag}
            <button
              data-testid="remove-tag"
              onClick={() => removeTag(index)}
              style={{ marginLeft: 6 }}
            >
              &times;
            </button>
          </span>
        ))}
      </div>
      <input
        id="tag-input"
        value={value}
        onChange={(e) => setValue(e.target.value)}
        onKeyDown={handleKeyDown}
        placeholder="Type and press Enter..."
        style={{ padding: 8, width: "100%", boxSizing: "border-box" }}
      />
    </div>
  );
}

Ready to check it?

5 tests run against your rendered component, right here in your browser. Sign in to claim the XP when you pass.

Stuck? The react course covers the ideas this problem is built on.