Motion
Single-element presets
Component / Layout
Filter keyed collections without tearing focus away. Target counts update immediately, excluded cards retain their exits, and the remaining grid flows into place.
Single-element presets
Retained lifecycle
Keyboard navigation
Modal focus
Numeric feedback
Live notifications
Delivery contract
pnpm add easecraft@0.1.0The component imports stable APIs from easecraft.
Package usage
import { FilterGrid } from "easecraft";
<FilterGrid
items={projects}
filters={projectFilters}
getKey={(project) => project.id}
value={activeFilter}
onValueChange={setActiveFilter}
>
{(project) => <ProjectCard project={project} />}
</FilterGrid>Typed contract
| Prop | Type | Default | Purpose |
|---|---|---|---|
| items | readonly Item[] | required | Complete controlled item data |
| filters | readonly FilterGridFilter[] | required | Labels, values, and predicates |
| getKey | (item) => React.Key | required | Stable item identity |
| children | (item, state) => ReactNode | required | Grid item renderer |
| value | string | uncontrolled | Controlled active filter |
| defaultValue | string | first enabled | Initial uncontrolled filter |
| onValueChange | (value) => void | none | Filter selection callback |
| resultLabel | (count, filter) => ReactNode | count + result(s) | Live result text |
| empty | ReactNode | default message | Zero-result content |
| duration | duration token | number | "normal" | Entry and reflow duration |
| exitDuration | duration token | number | "fast" | Filtered-item exit duration |
| interval | stagger token | number | "normal" | Entry/exit sequence interval |
| maxDelay | duration token | number | "slow" | Maximum stagger span |
| distance | distance token | number | "medium" | Entry and exit travel |
| as | HTML tag | "div" | Polymorphic host element |
Release requirement