PE03▸⌨️ Input · 進階輸入▸選擇
Multi Select
多選
難度 ★★★★★標籤 multi · chips · 搜尋3 min read
模式簡述
Multi Select:選多個 tag。每選一個變 chip,可移除。search filter、permission 設定常用。
選擇框架⋯
已選 0 項
Claude Code Prompt
參考:PE03 multi-select 組件:MultiSelect.tsx Multi Select:選多個 tag。每選一個變 chip,可移除。search filter、permission 設定常用。 限制: - chip 過多沒折疊 - 沒做 backspace 刪最後一個 - chip 顏色太多種
完整程式碼
"use client";
import { useEffect, useState } from "react";
import { X, ChevronDown } from "lucide-react";
type State = "empty" | "few" | "many";
const OPTIONS = ["React", "Vue", "Svelte", "Solid", "Angular", "Qwik", "Astro", "Remix"];
export function MultiSelect({ state = "few" }: { state?: State }) {
const init =
state === "empty"
? []
: state === "many"
? ["React", "Vue", "Svelte", "Solid", "Angular", "Qwik"]
: ["React", "Vue"];
const [picked, setPicked] = useState<string[]>(init);
useEffect(() => setPicked(init), [state]);
const visible = picked.slice(0, 3);
const extra = picked.length - visible.length;
return (
<div className="w-full max-w-md">
<div className="flex min-h-[40px] flex-wrap items-center gap-1 rounded-md border border-border bg-background/50 px-2 py-1.5">
{picked.length === 0 && (
<span className="px-1 text-xs text-muted-foreground">選擇框架⋯</span>
)}
{visible.map((p) => (
<span
key={p}
className="inline-flex items-center gap-1 rounded bg-lab-accent/15 px-1.5 py-0.5 text-[11px] text-lab-accent"
>
{p}
<button
onClick={() => setPicked((prev) => prev.filter((x) => x !== p))}
className="hover:text-foreground"
>
<X className="h-2.5 w-2.5" />
</button>
</span>
))}
{extra > 0 && (
<span className="rounded bg-muted px-1.5 py-0.5 font-mono text-[11px] text-muted-foreground">
+{extra}
</span>
)}
<ChevronDown className="ml-auto h-3 w-3 text-muted-foreground" />
</div>
<p className="mt-2 font-mono text-[11px] text-muted-foreground">
已選 {picked.length} 項
</p>
</div>
);
}何時用
- ✅ 篩選器(產品分類、tag、技術棧)
- ✅ 權限、角色多選
- ✅ 群組成員邀請
何時別用
- ❌ 最多選 2 個(用 checkbox group)
- ❌ 順序很重要(chip 不顯示順序,用 reorderable list)
- ❌ 選項超過 50 個(用搜尋型 combobox)
我踩過的坑
-
chip 過多沒折疊:選了 20 個,整個輸入框爆炸。> 3 個收成 +N 形式。
-
沒做 backspace 刪最後一個:使用者習慣按 backspace 刪 chip,沒做就很卡。
-
chip 顏色太多種:每個 tag 不同色看起來像彩虹。統一一個 accent 色就好。
相關模式
- PE01
- PA06