Tags Input
Tags Input Components like github and youtube
Tags Input Components like github and youtube
1'use client';2import React, { useState, useRef, useEffect } from 'react';34interface TagsInputProps {5tags: string[];6setTags: React.Dispatch<React.SetStateAction<string[]>>;7editTag?: boolean;8}910export const TagsInput: React.FC<TagsInputProps> = ({11tags,12setTags,13editTag = true,14}) => {15const [input, setInput] = useState('');16const [editingIndex, setEditingIndex] = useState<number | null>(null);17const editInputRef = useRef<HTMLInputElement>(null);1819const handleAddTag = (e: React.KeyboardEvent<HTMLInputElement>) => {20const trimmedInput = input.trim();2122if ((e.key === 'Enter' || e.key === ',') && trimmedInput) {23e.preventDefault();24if (editingIndex !== null) {25const updatedTags = [...tags];26updatedTags[editingIndex] = trimmedInput;27setTags(updatedTags);28setEditingIndex(null);29} else if (!tags.includes(trimmedInput)) {30setTags([...tags, trimmedInput]);31}32setInput('');33}34};3536const handleRemoveTag = (tag: string) => {37setTags(tags.filter((t) => t !== tag));38if (editingIndex !== null) {39setEditingIndex(null);40}41};4243const handleEditTag = (index: number) => {44if (editTag) {45setInput(tags[index]);46setEditingIndex(index);47setTimeout(() => editInputRef.current?.focus(), 0); // Focus on edit input48}49};5051const handleBlur = () => {52if (editingIndex !== null) {53const updatedTags = [...tags];54const trimmedInput = input.trim();55if (trimmedInput) {56updatedTags[editingIndex] = trimmedInput;57} else {58updatedTags.splice(editingIndex, 1);59}60setTags(updatedTags);61setEditingIndex(null);62}63setInput('');64};6566useEffect(() => {67// Resize the input width based on text content68if (editInputRef.current) {69editInputRef.current.style.width = `${input.length + 1}ch`;70}71}, [input]);7273return (74<div className='flex flex-wrap items-center gap-2 p-2 border-2 rounded-md focus-within:border-blue-500 bg-background'>75{tags.map((tag, index) => (76<div key={tag} className='relative'>77{editTag && editingIndex === index ? (78<input79ref={editInputRef}80type='text'81value={input}82onChange={(e) => setInput(e.target.value)}83onKeyDown={handleAddTag}84onBlur={handleBlur}85className='px-2 py-1 text-sm border rounded outline-none'86placeholder='Edit tag...'87style={{ width: `${input.length + 1 * 1.2}px` }}88autoFocus89/>90) : (91<span92onClick={() => handleEditTag(index)}93className='flex items-center gap-2 px-1 pl-2 py-1 text-sm font-medium text-white bg-blue-500 rounded cursor-pointer hover:bg-blue-600'94>95{tag}96<button97onClick={(e) => {98e.stopPropagation();99handleRemoveTag(tag);100}}101className='text-white hover:text-gray-300 px-1 focus:outline-none bg-background rounded'102>103×104</button>105</span>106)}107</div>108))}109<input110type='text'111value={input}112onChange={(e) => setInput(e.target.value)}113onKeyDown={handleAddTag}114className={`flex-grow px-2 py-1 text-sm border-none outline-none bg-background rounded-md ${115editingIndex !== null ? 'opacity-0' : 'opacity-100'116}`}117placeholder='Add a tag...'118/>119</div>120);121};
Prop | Type | Default | Description |
---|---|---|---|
tags | string[] | [] | Array of strings representing the tags to display in the input. |
setTags | React.Dispatch<React.SetStateAction<string[]>> | - | Function to update the tags array, typically used with a useState hook. |
editTag | boolean | true | Optional flag that enables or disables the ability to edit tags in the input compone |