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)
| Prop | Type | Default | Description |
|---|---|---|---|
defaultOpen | boolean | false | Initial open state (uncontrolled) |
open | boolean | - | Controlled open state |
onOpenChange | (open: boolean) => void | - | Callback when state changes |
FilterBarTrigger
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | Merge props onto child element instead of rendering a button |
Renders data-state="open" or data-state="closed" for styling.
FilterBarContent
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Classes for the outer animated container |
contentClassName | string | - | 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 componentPlace
FilterBarContent below the header/toolbar so it expands downwardUse
className on FilterBarContent for borders and marginsUse
justify-end on contentClassName — it pushes overflow to the left edge where horizontal scroll can't reachWrap
FilterBarContent children in extra containers — children should be direct FilterChip elements