FilterListItem

Toggle button for a predefined filter preset, designed to be used inside a <FilterList>.

Installation

pnpm dlx shadcn@latest add @shadmin/filter-list-item

Usage

Render <FilterListItem> elements as children of <FilterList>. Clicking on an item merges the given value into the current list filter. Clicking again removes it.

import { Card } from "@/components/ui/card";
import { Mail } from "lucide-react";
import { FilterList, FilterListItem } from "@/components/admin";
 
const FilterSidebar = () => (
  <Card className="p-4">
    <FilterList
      label="Subscribed to newsletter"
      icon={<Mail className="size-4" />}
    >
      <FilterListItem label="Yes" value={{ has_newsletter: true }} />
      <FilterListItem label="No" value={{ has_newsletter: false }} />
    </FilterList>
  </Card>
);

The value prop can contain multiple keys, useful to represent date ranges or complex filter presets:

import { endOfYesterday, startOfWeek, subWeeks } from "date-fns";
import { Clock } from "lucide-react";
import { FilterList, FilterListItem } from "@/components/admin";
 
const LastVisitedFilter = () => (
  <FilterList label="Last visited" icon={<Clock className="size-4" />}>
    <FilterListItem
      label="Today"
      value={{
        last_seen_gte: endOfYesterday().toISOString(),
        last_seen_lte: undefined,
      }}
    />
    <FilterListItem
      label="This week"
      value={{
        last_seen_gte: startOfWeek(new Date()).toISOString(),
        last_seen_lte: undefined,
      }}
    />
    <FilterListItem
      label="Last week"
      value={{
        last_seen_gte: subWeeks(startOfWeek(new Date()), 1).toISOString(),
        last_seen_lte: startOfWeek(new Date()).toISOString(),
      }}
    />
  </FilterList>
);

Props

PropRequiredTypeDefaultDescription
labelRequiredReactNode-Text or React element displayed in the item; strings are translated
valueRequiredobject-Filter values toggled on click
iconOptionalReactNode-Icon displayed before the label
isSelectedOptional(value, filters) => booleanshallow matchCustom selection predicate
toggleFilterOptional(value, filters) => objectshallow toggleCustom toggle function
classNameOptionalstring-Extra Tailwind classes appended to the root element

isSelected

By default, <FilterListItem> considers itself selected when every key/value pair in value matches the current filters. Override isSelected to provide custom logic:

<FilterListItem
  label="High priority"
  value={{ priority: "high" }}
  isSelected={(value, filters) => filters.priority === value.priority}
/>

toggleFilter

The default toggle merges value into the current filters when activating and removes the same keys when deactivating. Override toggleFilter for non-trivial behavior:

<FilterListItem label="Reset all" value={{}} toggleFilter={() => ({})} />