タグ入力(TagsInput / PillsInput)ライブラリ比較
4つのアプローチでタグ入力UIを実装し、サジェスト・バリデーション・カスタムPillの違いを比較
共通の動作仕様
各デモではテキスト入力でタグを追加・削除できます。Enterキーで追加、×ボタンまたはBackspaceで削除します。
{
"追加方法": "Enterキー / ×ボタン",
"削除方法": "×ボタン / Backspaceキー",
"バリデーション": "空文字・重複チェック",
"サジェスト": "ライブラリによって異なる"
}1. Mantine TagsInput
シンプルなタグ入力 — サジェスト候補・区切り文字・最大数制限が1コンポーネントで完結
特徴
- • Enterキーでタグ追加、×ボタンで削除
- •
dataプロパティにサジェスト候補を指定可能 - •
splitCharsでカンマ・スペース等の区切り文字を設定 - •
maxTagsで最大タグ数を制限
インストール
npm install @mantine/core @mantine/hooks'use client';
import { MantineProvider, TagsInput } from '@mantine/core';
import '@mantine/core/styles.css';
import { useState } from 'react';
const suggestions = ['React', 'TypeScript', 'Next.js', 'Tailwind CSS', 'Node.js'];
export function MantineTagsInputDemo() {
const [value, setValue] = useState<string[]>(['React', 'TypeScript']);
return (
<MantineProvider>
<TagsInput
label="タグを追加"
placeholder="Enterキーで追加"
value={value}
onChange={setValue}
data={suggestions}
clearable
/>
</MantineProvider>
);
}🤖 AIプロンプトテンプレート
React + Tailwind CSSで、Mantine TagsInputを使ったタグ入力UIを実装してください。
- 使用ライブラリ: @mantine/core の TagsInput コンポーネント
- MantineProvider でラップし、@mantine/core/styles.css をインポートすること
- value/onChange でタグの状態を管理すること
- data プロパティにサジェスト候補の配列を渡すこと
- splitChars={[",", " "]} でカンマ・スペース区切りに対応すること
- maxTags で最大タグ数を制限すること
- comboboxProps.transitionProps でドロップダウンのアニメーションを設定すること⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。
2. Mantine PillsInput + Combobox
カスタム実装用プリミティブ — Comboboxと組み合わせてドロップダウン付きマルチセレクトを構築
特徴
- •
PillsInput+Comboboxの組み合わせで柔軟なUIを構築 - • 選択済みアイテムをPill(チップ)形式で表示
- • Backspaceキーで最後のPillをキーボードから削除
- • ドロップダウンに選択済みチェックマークを表示
インストール
npm install @mantine/core @mantine/hooks'use client';
import { MantineProvider, PillsInput, Pill, Combobox, useCombobox } from '@mantine/core';
import '@mantine/core/styles.css';
import { useState } from 'react';
const OPTIONS = ['React', 'TypeScript', 'Next.js', 'Tailwind CSS', 'Node.js'];
export function MantinePillsInputDemo() {
const [selected, setSelected] = useState<string[]>([]);
const [search, setSearch] = useState('');
const combobox = useCombobox();
const filtered = OPTIONS.filter(o => o.toLowerCase().includes(search.toLowerCase()));
const toggle = (val: string) =>
setSelected(prev => prev.includes(val) ? prev.filter(v => v !== val) : [...prev, val]);
return (
<MantineProvider>
<Combobox store={combobox} onOptionSubmit={toggle}>
<Combobox.DropdownTarget>
<PillsInput onClick={() => combobox.openDropdown()}>
<Pill.Group>
{selected.map(s => (
<Pill key={s} withRemoveButton onRemove={() => toggle(s)}>{s}</Pill>
))}
<Combobox.EventsTarget>
<PillsInput.Field
placeholder="検索..."
value={search}
onChange={e => { setSearch(e.currentTarget.value); combobox.openDropdown(); }}
/>
</Combobox.EventsTarget>
</Pill.Group>
</PillsInput>
</Combobox.DropdownTarget>
<Combobox.Dropdown>
<Combobox.Options>
{filtered.map(o => (
<Combobox.Option key={o} value={o}>
{selected.includes(o) ? '✓ ' : ''}{o}
</Combobox.Option>
))}
</Combobox.Options>
</Combobox.Dropdown>
</Combobox>
</MantineProvider>
);
}🤖 AIプロンプトテンプレート
React + Tailwind CSSで、Mantine PillsInput + Comboboxを使ったドロップダウン付きマルチセレクトUIを実装してください。 - 使用ライブラリ: @mantine/core の PillsInput、Pill、Combobox、useCombobox - MantineProvider でラップし、@mantine/core/styles.css をインポートすること - useCombobox フックで onDropdownClose/onDropdownOpen を制御すること - Combobox.DropdownTarget 内に PillsInput を配置し、Pill.Group で選択済みPillを表示すること - Combobox.EventsTarget 内に PillsInput.Field を配置し、検索文字列を管理すること - Backspaceキーで最後のPillを削除する処理を onKeyDown に実装すること - オプションに CheckIcon で選択済み状態を表示すること
⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。
3. shadcn/ui(Input + Badge)
シンプルなタグ入力 — Input と Badge を組み合わせて基本的なタグ入力を実装
特徴
- • Enter またはカンマでタグ追加、×ボタン・Backspaceで削除
- •
Input+Badgeの組み合わせで実装 - • サジェストが必要な場合は Combobox で別途実装
- • バリデーション・サジェストは手動実装が必要
インストール
npx shadcn@latest add input badge'use client';
import { useState, KeyboardEvent } from 'react';
import { Input } from '@/components/ui/input';
import { Badge } from '@/components/ui/badge';
export function ShadcnTagsInputDemo() {
const [tags, setTags] = useState<string[]>(['React', 'TypeScript']);
const [input, setInput] = useState('');
const addTag = (value: string) => {
const trimmed = value.trim();
if (trimmed && !tags.includes(trimmed)) {
setTags([...tags, trimmed]);
}
setInput('');
};
const removeTag = (tag: string) => setTags(tags.filter(t => t !== tag));
const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter' || e.key === ',') {
e.preventDefault();
addTag(input);
}
if (e.key === 'Backspace' && input === '' && tags.length > 0) {
removeTag(tags[tags.length - 1]);
}
};
return (
<div className="flex flex-wrap gap-2 p-2 border rounded-md min-h-10 items-center">
{tags.map(tag => (
<Badge key={tag} variant="secondary" className="gap-1">
{tag}
<button onClick={() => removeTag(tag)} className="ml-1 hover:text-destructive">×</button>
</Badge>
))}
<Input
className="border-none shadow-none p-0 h-auto flex-1 min-w-20 focus-visible:ring-0"
value={input}
onChange={e => setInput(e.target.value)}
onKeyDown={handleKeyDown}
onBlur={() => input && addTag(input)}
placeholder="タグを入力..."
/>
</div>
);
}🤖 AIプロンプトテンプレート
React + Tailwind CSSで、shadcn/uiを使ったタグ入力UIを実装してください。 - shadcn/ui には TagsInput 専用コンポーネントがないため、Input と Badge を組み合わせて実装する - npx shadcn@latest add input badge でインストール - div コンテナ内に Badge と Input を並べてタグ入力を実現 - Input の className で border / shadow / focus-ring を非表示にして自然に統合する - Enterキーでタグ追加、Backspaceキーで最後のタグを削除 - BadgeのchildrenにタグテキストとXボタンを配置 - onBlur で未確定のテキストを自動追加
⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。
4. Chakra UI TagsInput
シンプルで直感的なタグ入力 — TagsInput.Root の複合コンポーネントパターンで構成
特徴
- •
TagsInput.Rootの複合パターンで各パーツを明示的に制御 - •
TagsInput.Item / ItemText / ItemDeleteTriggerでタグの見た目をカスタマイズ - •
onValueChangeで値の変更を管理 - •
ClearTriggerで全タグ一括削除に対応 - • WAI-ARIA 準拠でアクセシビリティが標準対応
インストール
npm install @chakra-ui/react @emotion/react'use client'
import { useState } from 'react'
import { createSystem, defaultConfig, ChakraProvider, TagsInput } from '@chakra-ui/react'
const system = createSystem(defaultConfig, { globalCss: {}, preflight: false })
export function ChakraTagsInputDemo() {
const [value, setValue] = useState<string[]>(['React', 'TypeScript'])
return (
<ChakraProvider value={system}>
<TagsInput.Root
value={value}
onValueChange={(e) => setValue(e.value)}
maxW="sm"
>
<TagsInput.Label>タグを追加</TagsInput.Label>
<TagsInput.Control>
{value.map((tag, i) => (
<TagsInput.Item key={i} index={i} value={tag}>
<TagsInput.ItemText>{tag}</TagsInput.ItemText>
<TagsInput.ItemDeleteTrigger />
</TagsInput.Item>
))}
<TagsInput.Input placeholder="Enterキーで追加" />
</TagsInput.Control>
<TagsInput.ClearTrigger>すべて削除</TagsInput.ClearTrigger>
</TagsInput.Root>
</ChakraProvider>
)
}🤖 AIプロンプトテンプレート
React + Tailwind CSSで、Chakra UI v3のTagsInputを使ったタグ入力UIを実装してください。
- 使用ライブラリ: @chakra-ui/react の TagsInput コンポーネント(v3)
- ChakraProvider に createSystem(defaultConfig, { globalCss: {}, preflight: false }) を渡すこと
- TagsInput.Root / Control / Item / ItemText / ItemDeleteTrigger / Input の複合パターンで実装
- onValueChange で値の変更を管理
- TagsInput.ClearTrigger で全タグ一括削除に対応
- WAI-ARIA 準拠でキーボード操作(Enter で追加、Backspace で削除)が標準対応⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。
5. カスタム実装(CSS / Tailwind)
ライブラリ不要の完全カスタム実装 — 重複チェック・空文字バリデーション・Backspace削除
Enterで追加 / Backspaceで最後のタグを削除 / 重複チェック・空文字バリデーション内蔵
特徴
- • 外部ライブラリ不要で依存関係が最小限
- • 空文字バリデーション・重複チェックを自前で実装
- • Backspaceキーで最後のタグを削除
- • コンテナクリックでinputにフォーカス
インストール
追加パッケージ不要(React + Tailwind CSS のみ)'use client';
import { useState, useRef } from 'react';
export function CustomTagsInputDemo() {
const [tags, setTags] = useState<string[]>(['React', 'TypeScript']);
const [input, setInput] = useState('');
const [error, setError] = useState('');
const inputRef = useRef<HTMLInputElement>(null);
const addTag = (value: string) => {
const trimmed = value.trim();
if (!trimmed) { setError('空のタグは追加できません'); return; }
if (tags.includes(trimmed)) { setError(`「${trimmed}」はすでに追加されています`); return; }
setTags(prev => [...prev, trimmed]);
setInput('');
setError('');
};
const removeTag = (tag: string) => setTags(prev => prev.filter(t => t !== tag));
return (
<div className="space-y-2">
<div
className="flex flex-wrap gap-2 p-2 border-2 rounded-lg min-h-[48px] cursor-text border-gray-300 focus-within:border-blue-500"
onClick={() => inputRef.current?.focus()}
>
{tags.map(tag => (
<span key={tag} className="inline-flex items-center gap-1 px-2.5 py-0.5 bg-blue-100 text-blue-800 rounded-full text-sm">
{tag}
<button onClick={() => removeTag(tag)} className="w-4 h-4 rounded-full flex items-center justify-center hover:bg-blue-200">×</button>
</span>
))}
<input
ref={inputRef}
value={input}
onChange={e => { setInput(e.target.value); setError(''); }}
onKeyDown={e => {
if (e.key === 'Enter') { e.preventDefault(); addTag(input); }
if (e.key === 'Backspace' && input === '' && tags.length > 0) removeTag(tags[tags.length - 1]);
}}
placeholder={tags.length === 0 ? 'タグを入力してEnter' : ''}
className="flex-1 min-w-[120px] outline-none bg-transparent text-sm"
/>
</div>
{error && <p className="text-xs text-red-500">{error}</p>}
</div>
);
}🤖 AIプロンプトテンプレート
React + Tailwind CSSで、ライブラリ不要のカスタムタグ入力UIを実装してください。 - 使用ライブラリ: React + Tailwind CSS のみ(外部タグ入力ライブラリなし) - useState でタグの配列と入力文字列を管理すること - Enterキーでタグを追加、Backspaceキー(入力が空の状態)で最後のタグを削除する処理を実装すること - 空文字バリデーション・重複チェックを行い、エラーメッセージを表示すること - タグはrounded-fullのバッジ形式で表示し、×ボタンで個別削除できるようにすること - コンテナをクリックするとinputにフォーカスするよう実装すること
⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。
ライブラリ比較表
| 項目 | Mantine TagsInput | Mantine PillsInput | shadcn/ui | Chakra UI | カスタム実装 |
|---|---|---|---|---|---|
| サジェスト候補 | 内蔵(data prop) | Comboboxで自作 | ⚠️ Comboboxで別途実装 | ⚠️ Combobox との組み合わせで実装 | 自作 |
| カスタムPill | 限定的 | 完全カスタム可能 | ✅ Badge でカスタマイズ | ✅ ItemText / DeleteTrigger でカスタム | 完全カスタム可能 |
| バリデーション | 内蔵(重複・空文字) | 自作 | ⚠️ 手動で実装 | ⚠️ onInvalid で自作 | 自作 |
| 区切り文字設定 | splitChars prop | 自作 | ✅ onKeyDown で実装 | ⚠️ 非対応(Enter のみ) | 自作 |
| 最大タグ数 | maxTags prop | 自作 | ⚠️ 手動で実装 | ✅ max prop | 自作 |
| キーボード操作 | Enter追加・Backspace削除 | Backspace削除(自作) | ✅ Enter追加・Backspace削除 | ✅ Enter追加・Backspace削除 | Enter追加・Backspace削除 |
| バンドルサイズ | 中程度(Mantine) | 中程度(Mantine) | ✅ 使った分だけ | ⚠️ 中(emotion含む) | 最小 |
選択のポイント
Mantine TagsInput — シンプルなタグ入力に最適。サジェスト候補・区切り文字・最大数制限が1行のpropsで設定でき、学習コストが低い。Mantineをすでに使っているプロジェクトでの採用を推奨。
Mantine PillsInput + Combobox — ドロップダウン付きのマルチセレクトを構築したい場合に。TagsInputより実装量は増えるが、Pillの見た目やComboboxの動作を細かくカスタマイズできる上級パターン。
shadcn/ui(Input + Badge) — TagsInput専用コンポーネントはないが、InputとBadgeを組み合わせることで基本的なタグ入力を実装できる。サジェストやバリデーションが必要な場合はMantineのTagsInputや他のライブラリが適している。
Chakra UI TagsInput — TagsInput.Root の複合コンポーネントパターンでタグの各パーツを明示的に制御できる。WAI-ARIA 準拠でアクセシビリティが標準対応。Chakra UI をすでに採用しているプロジェクトでの採用を推奨。
カスタム実装 — 外部ライブラリへの依存を避けたい場合や、独自のデザインシステムに完全に合わせたい場合に最適。バリデーションロジックを自前で制御できる。
タグ入力UI(TagsInput)は、テキスト入力でタグを追加・削除するフォームコンポーネント。入力した文字列がタグ(Pill)として表示される。
ブログ記事のタグ付け・スキルセット入力・メールアドレスの複数入力・フィルター条件の設定など、複数の値をインタラクティブに管理する場面で使われる。
- •基本型(Enter で追加)
- •サジェスト型(候補表示)
- •バリデーション付き型
- •カスタムPill型
- •上限数制限型