Filter Composer Bar
Linear 式過濾器組合列:點「加入條件」挑欄位,膠囊 chip 以 spring 彈入;chip 內可原地展開選單換值,移除時其餘 chip 以 FLIP 收攏補位。
載入預覽⋯
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
<FilterComposerBar />
安裝
npx shadcn@latest add https://webberui.com/r/filter-composer-bar.json或在 components.json 設定 registries 後,改用 @webberui/filter-composer-bar 安裝。
安裝依賴後,從 registry JSON(/r/filter-composer-bar.json 的 files[0].content)複製 filter-composer-bar.tsx 原始碼到你的 components/ui/ 目錄:
npm install motion lucide-react clsx tailwind-merge使用
import { FilterComposerBar } from "@/components/ui/filter-composer-bar";
<FilterComposerBar
fields={[
{
key: "status",
label: "狀態",
options: [
{ value: "active", label: "進行中" },
{ value: "done", label: "已完成" },
],
},
{
key: "priority",
label: "優先級",
options: [
{ value: "high", label: "高" },
{ value: "low", label: "低" },
],
},
]}
onChange={(conditions) => console.log(conditions)}
/>未提供 value 時由元件內部管理狀態(非受控);提供 value 搭配 onChange 則為受控模式。onChange 在新增、換值、移除時都會帶入最新的 FilterCondition[]。
Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
fields | FilterField[] | — | 可用欄位清單,每項為 { key, label, options: { value, label }[] },每個欄位同時最多一個條件 |
value | FilterCondition[] | — | 受控條件陣列,每項為 { key, value };未提供時由元件內部管理 |
onChange | (conditions: FilterCondition[]) => void | — | 條件變更時觸發(新增、換值、移除),帶入最新條件陣列 |
addLabel | string | "加入條件" | 「加入條件」按鈕的文字 |
className | string | — | 附加到最外層容器的 class |
細節
- 三段式 chip:欄位名(靜態)/值(可點擊)/移除 ×,以細分隔線切成一顆膠囊,仿 Linear 的過濾器語彙
- 彈入進場:選定欄位後,chip 以 scale + y 的 spring 從下方彈入排列,新增條件預設取該欄位第一個選項
- 原地換值:點 chip 的值段,小選單以縮放淡入展開並錨定於該 chip 下方,選取後即時更新值文字,不需離開組合列
- FLIP 收攏:點 × 時該 chip 縮小退場(
AnimatePresence mode="popLayout"先脫離文件流),其餘 chip 與「加入條件」按鈕同時以 layout FLIP 平滑補位;多條件時以 flex-wrap 自動換行 - 點外關閉:popover 以絕對定位錨定,掛載
document的 pointerdown 監聽點擊外部即關閉(unmount 時清理);同一時間只會有一個選單開啟 - 每個欄位同時最多一個條件;欄位全部用完時「加入條件」按鈕停用
可及性
- 使用者系統開啟「減少動態效果」時,彈入、FLIP 與選單縮放全部停用,狀態直接切換(DOM 結構與 SSR 一致)
- chip 各段皆為原生
<button>,可 Tab 循序聚焦;值段與「加入條件」按鈕帶aria-haspopup/aria-expanded標示選單狀態 - 值選單項目為
menuitemradio並以aria-checked標示目前值;移除按鈕帶「移除某欄位條件」的aria-label - 按 Esc 關閉選單並把焦點還給觸發按鈕;
focus-visible時顯示外框