← Components/Inputs & Forms

TagInput

taginput-1779354191805.tsx
'use client';

import { useState, useEffect } from 'react';

interface Tag {
  id: number;
  name: string;
}

const TagInput = () => {
  const [tags, setTags] = useState<Tag[]>([]);
  const [inputValue, setInputValue] = useState('');
  const [suggestions, setSuggestions] = useState<string[]>([
    'Apple',
    'Banana',
    'Cherry',
    'Date',
    'Elderberry',
  ]);

  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === 'Enter' && inputValue.trim() !== '') {
      if (tags.length < 10) {
        setTags([...tags, { id: tags.length, name: inputValue.trim() }]);
        setInputValue('');
      }
    } else if (e.key === 'Backspace' && inputValue.trim() === '') {
      setTags(tags.slice(0, -1));
    }
  };

  const handleRemoveTag = (id: number) => {
    setTags(tags.filter((tag) => tag.id !== id));
  };

  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const value = e.target.value;
    setInputValue(value);
    setSuggestions(
      suggestions.filter((suggestion) =>
        suggestion.toLowerCase().includes(value.toLowerCase())
      )
    );
  };

  return (
    <div className="w-full max-w-md p-4 bg-zinc-950 rounded-lg">
      <div className="flex flex-wrap gap-2 mb-2">
        {tags.map((tag) => (
          <div
            key={tag.id}
            className="flex items-center gap-1 py-1 px-2 bg-zinc-800 rounded-lg"
          >
            <span className="text-gold">{tag.name}</span>
            <button
              onClick={() => handleRemoveTag(tag.id)}
              className="text-xs text-gold hover:text-white transition duration-200"
            >
              X
            </button>
          </div>
        ))}
      </div>
      <input
        type="text"
        value={inputValue}
        onChange={handleInputChange}
        onKeyDown={handleKeyDown}
        className="w-full p-2 pl-10 text-sm text-white bg-zinc-800 rounded-lg focus:outline-none focus:ring-gold focus:ring-1"
        placeholder="Type and press Enter to add tags"
      />
      {suggestions.length > 0 && inputValue.trim() !== '' && (
        <ul className="list-none p-0 m-0 mt-2">
          {suggestions.map((suggestion) => (
            <li
              key={suggestion}
              className="py-1 px-2 text-sm text-white bg-zinc-800 rounded-lg hover:bg-zinc-700 transition duration-200"
            >
              {suggestion}
            </li>
          ))}
        </ul>
      )}
    </div>
  );
};

export default TagInput;

Component info

CategoryInputs & Forms
Frameworkreact
TierFREE
Views0
Copies0

About

Tag/chip input with autocomplete

More from Inputs & Forms

'use client';

import React, { useState } from 'react';

interface RangeSliderProps {
  min: number;
  max: number;
  defaultValue: [number, number];
}

const RangeSlider: React.FC<RangeSliderProps> = ({ min, max, defaultValue }) => {
  const [minVal
RangeSlider
Inputs & Forms
'use client';

import React, { useState } from 'react';

interface Color {
  hex: string;
}

interface Swatch {
  hex: string;
}

const ColorPicker = () => {
  const [color, setColor] = useState<Color>({ hex: '#C9A84C' });
  const [customColor, setCu
ColorPicker
Inputs & Forms
'use client';

import React, { useState } from 'react';

interface File {
  name: string;
  size: number;
  progress: number;
}

const FileUpload = () => {
  const [dragOver, setDragOver] = useState(false);
  const [files, setFiles] = useState<File[]
FileUpload
Inputs & Forms
import React, { useState } from 'react';

const OTPInput = () => {
  const [otp, setOtp] = useState(new Array(6).fill(''));
  const [activeIndex, setActiveIndex] = useState(0);

  const handleChange = (e, index) => {
    const value = e.target.value;
OTPInput
Inputs & Forms