Filter Bar

A collapsible, horizontally scrolling container for filter chips with a dialog-like trigger pattern.

A compound component for toggling and displaying filter chips. Works like a dialog — FilterBar provides state, FilterBarTrigger toggles visibility, and FilterBarContent renders a horizontally scrolling row with spring-animated collapse/expand.

Basic

Default (closed)

Default open

Usage

import {
  FilterBar,
  FilterBarTrigger,
  FilterBarContent,
  FilterChip,
  Button,
  BarsFilterIcon,
} from "@delphi/ui";

export function PageHeader() {
  return (
    <FilterBar>
      <header className="flex items-center gap-2">
        <h1>Members</h1>
        <FilterBarTrigger asChild>
          <Button variant="ghost" size="icon">
            <BarsFilterIcon className="size-4" />
          </Button>
        </FilterBarTrigger>
      </header>
      <FilterBarContent>
        <FilterChip label="Status" active values={["Active"]} />
        <FilterChip label="Tags" />
        <FilterChip label="Date" />
      </FilterBarContent>
    </FilterBar>
  );
}

Controlled

import { useState } from "react";
import {
  FilterBar,
  FilterBarTrigger,
  FilterBarContent,
  FilterChip,
  Button,
} from "@delphi/ui";

export function ControlledExample() {
  const [open, setOpen] = useState(false);

  return (
    <FilterBar open={open} onOpenChange={setOpen}>
      <FilterBarTrigger asChild>
        <Button>Toggle</Button>
      </FilterBarTrigger>
      <FilterBarContent>
        <FilterChip label="Active" />
        <FilterChip label="Pending" />
      </FilterBarContent>
    </FilterBar>
  );
}

Customizing Content

Use className for the outer container (borders, margins) and contentClassName for the inner scrollable row (padding, gap).

<FilterBarContent
  className="-mt-px border-b border-sand-6"
  contentClassName="gap-2 px-3 py-2"
>
  <FilterChip label="Medium" />
  <FilterChip label="Date" />
</FilterBarContent>

API Reference

FilterBar (Root)

PropTypeDefaultDescription
defaultOpenbooleanfalseInitial open state (uncontrolled)
openboolean-Controlled open state
onOpenChange(open: boolean) => void-Callback when state changes

FilterBarTrigger

PropTypeDefaultDescription
asChildbooleanfalseMerge props onto child element instead of rendering a button

Renders data-state="open" or data-state="closed" for styling.

FilterBarContent

PropTypeDefaultDescription
classNamestring-Classes for the outer animated container
contentClassNamestring-Classes for the inner scrollable row

The content animates height with a spring transition and scrolls horizontally when chips overflow. Children automatically get flex: none to prevent shrinking.

Use asChild on FilterBarTrigger to compose with your own button component
Place FilterBarContent below the header/toolbar so it expands downward
Use className on FilterBarContent for borders and margins
Use justify-end on contentClassName — it pushes overflow to the left edge where horizontal scroll can't reach
Wrap FilterBarContent children in extra containers — children should be direct FilterChip elements
ESC
No results found