TagInput
taginput-1779393692749.tsx
'use client'
import { useState, useRef } from 'react'
export default function TagInput({ placeholder = 'Add tag...' }) {
const [tags, setTags] = useState(['react', 'typescript'])
const [input, setInput] = useState('')
const ref = useRef(null)
const addTag = () => {
const val = input.trim().toLowerCase()
if (val && !tags.includes(val)) setTags(t => [...t, val])
setInput('')
}
const handleKey = (e) => {
if (e.key === 'Enter' || e.key === ',') { e.preventDefault(); addTag() }
if (e.key === 'Backspace' && !input) setTags(t => t.slice(0, -1))
}
return (
<div
onClick={() => ref.current?.focus()}
style={{
display: 'flex', flexWrap: 'wrap', gap: '6px',
border: '2px solid #e2e8f0', borderRadius: '10px', padding: '8px 12px',
cursor: 'text', minHeight: '48px', alignItems: 'center',
}}
>
{tags.map(tag => (
<span key={tag} style={{
display: 'inline-flex', alignItems: 'center', gap: '4px',
background: '#ede9fe', color: '#6d28d9',
padding: '3px 10px', borderRadius: '6px', fontSize: '13px', fontWeight: 500,
}}>
{tag}
<button onClick={() => setTags(t => t.filter(x => x !== tag))} style={{
background: 'none', border: 'none', color: '#7c3aed', cursor: 'pointer', fontSize: '14px', padding: 0
}}>×</button>
</span>
))}
<input
ref={ref} value={input}
onChange={e => setInput(e.target.value)}
onKeyDown={handleKey} onBlur={addTag}
placeholder={tags.length === 0 ? placeholder : ''}
style={{ border: 'none', outline: 'none', fontSize: '14px', minWidth: '80px', flex: 1 }}
/>
</div>
)
}Component info
CategoryInputs & Forms
Frameworkreact
TierFREE
Views0
Copies0
About
Multi-tag input with keyboard navigation and delete support
More from Inputs & Forms
'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 [suggestTagInput
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
'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 [minValRangeSlider
Inputs & Forms