crucıble

Sift

Structured filter bar for any list or table: a + Filter popover that slides property → operator → value (type-ahead fields, per-type operators, checkbox listbox, number range, and a range-selecting month calendar with presets), spring-in chips you edit in place part by part, an and/or toggle, saved views that crossfade chip sets with inline Save view, Clear all, and a result count rolling on Tally drums. Controlled or uncontrolled, keyboard-first (F, arrows, Backspace), with a pure applyFilters() helper to drive your rows.

motionfree

Installation

CLI

npx shadcn@latest add @crucible/sift

Manual — install dependencies, then copy the source

npm install motion

Props

PropTypeDefaultDescription
fieldsSiftField[]issue-tracker sample fields (Status, Priority, Assignee, Title, Estimate, Updated, Failing checks)Filterable properties.
valueSiftFilter[]Controlled filters. Omit for uncontrolled use.
defaultValueSiftFilter[]the "Active work" sample view when fields is omitted, otherwise noneInitial filters (uncontrolled).
onChange(filters: SiftFilter[]) => voidFires with the full next filter list on every add, edit, removal, clear or view switch.
conjunctionSiftConjunctionControlled conjunction.
defaultConjunctionSiftConjunction"and"Initial conjunction (uncontrolled).
onConjunctionChange(conjunction: SiftConjunction) => voidFires when the and / or toggle between chips flips.
viewsSiftView[]sample views (All issues, Active work, My open, Failing this week, Urgent & high) when fields is omittedSaved views in the views menu. Pass [] to hide the menu.
defaultViewstring"active" for the sample views, else the first viewId of the view selected initially.
onViewChange(view: SiftView) => voidFires when a view is picked from the menu.
onSaveView(view: SiftView) => void | Promise<unknown>Called when a view is saved from "Save view". Return a Promise to show a pending state; rejecting keeps the name field open with the error. The view is added to the menu on success. Omit to hide "Save view".
countnumberResult count shown at the right; rolls on Tally drums when it changes.
totalnumberOptional total, shown as "24 of 40".
noun{ one: string; other: string }{ one: "result", other: "results" }Result noun.
todaystring | Datethe viewer's local today"Today" for date presets and the calendar (YYYY-MM-DD or Date).
accentColorstring"#e4e4e7"Accent for focus rings, the active chip, values and the Apply button.
refReact.Ref<SiftHandle>Imperative handle (open(fieldKey?), close(), clear(), replay()). React 19 ref-as-prop.
classNamestringExtra classes for the root.
Also accepts all props of Omit<React.ComponentPropsWithoutRef<"div">, "onChange" | "defaultValue" | "children"> — they pass through to the underlying element.

Honors prefers-reduced-motion with a designed static fallback, and passes className through.