Ship-It Designv0.0.20

GitHub

FilterPanel

Multi-facet checkbox filter panel. Pass a facets array describing each facet (label + options + optional collapsibility) and the panel renders a header with a reset action, then a labelled checkbox group per facet. Counts surface on the right as tabular pills.

Selections are emitted as Record<facetId, readonly string[]> and supported in both controlled (value + onValueChange) and uncontrolled (defaultValue) modes — mirroring Slider and NavBar.

The data shape#

You pass facets (the filter groups) and optionally a counts record mapping each option to a per-option pill count.

tsx
<FilterPanel
  facets={[
    {
      id: 'category',
      label: 'Category',
      options: [
        { value: 'food', label: 'Food' },
        { value: 'travel', label: 'Travel' },
      ],
    },
  ]}
  defaultValue={{ category: ['food'] }}
  counts={{ category: { food: 142, travel: 38 } }}
/>

The selection record is keyed by facet.id; the array under each key contains the selected option.value strings.

Default#

Three facets, two of them pre-selected. Counts illuminate the relative size of each option's match set; clicking Reset clears the selection and fires the optional onReset callback alongside onValueChange({}).

Loading…

Controlled#

When you need to drive the panel from URL state or another store, pass value + onValueChange. The shape matches the defaultValue above.

tsx
const [filters, setFilters] = useState<Record<string, readonly string[]>>({});
<FilterPanel facets={} value={filters} onValueChange={setFilters} />;

Facet (FilterFacet)#

Each entry in facets.

  • id: string (required) — stable identifier. The key under which this facet's selections appear in value / defaultValue.
  • label: ReactNode (required) — group heading rendered above the checkboxes.
  • options: ReadonlyArray<FilterFacetOption> (required) — the individual checkbox rows.
  • collapsible?: boolean — whether the group can fold. Default true. When false, the group is always open and the disclosure caret is suppressed.
  • defaultOpen?: boolean — initial open state for collapsible groups. Default true.

Facet option (FilterFacetOption)#

Each row inside a facet.

  • value: string (required) — the stable string committed to onValueChange and stored under the facet's array.
  • label: ReactNode (required) — visible row label.

Counts (counts)#

Per-option counts rendered as small tabular pills on the right of each row. Shape is { [facetId]: { [optionValue]: number } }. Pass 0 for known-empty rows; omit a value to skip the pill entirely.

Top-level props#

Props for FilterPanel
PropTypeDefaultDescription
facets *readonly FilterFacet[]
valueFilterPanelValue | undefinedControlled selection map keyed by facet id.
defaultValueFilterPanelValue | undefinedUncontrolled initial selection map. Default `{}`.
onValueChange((next: FilterPanelValue) => void) | undefinedFires whenever the selection changes — including reset.
onReset(() => void) | undefinedFired when the reset action is invoked, alongside `onValueChange({})`.
countsRecord<string, Record<string, number>> | undefinedOptional per-option counts shown in a trailing pill. Shape: `{ [facetId]: { [optionValue]: number } }`.
titleReactNodeFilterOverride the header title. Default `'Filter'`.
resetLabelReactNodeResetOverride the reset button label. Default `'Reset'`.