<!-- Protocore Design System — FilterBar -->
# FilterBar

- **Category:** Inputs (`inputs`)
- **Slug:** `inputs/filter-bar`
- **Status:** stable
- **Platforms:** web
- **Import:** `import { FilterBar } from "@protocore/pds";`
- **Docs:** https://pds.protocore.io/components/inputs/filter-bar

> A wrapping row of filter chips above a grid or list; selects one value or many, with an optional mono eyebrow.

## When to use it

Use a **FilterBar** to **filter a collection** — a card grid, a listing, a table — where the options are short facets worth showing all at once. It's built on **Chip**, so reach for a single **Chip** when you need one standalone toggle rather than a managed set. Use **SegmentedControl** when you're switching a *mode* (one of a few), not filtering: a segmented control always keeps one active and reads as a view switch, while a FilterBar can clear to 'none' and supports multi-select. When facets grow long or need grouping, graduate to a **Select** (single) or a checklist in a popover.

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `className` | `string` | no | — | — |
| `defaultValue` | `string` | no | — | Uncontrolled initial value. |
| `defaultValues` | `string[]` | no | — | Uncontrolled initial values. |
| `divider` | `boolean` | no | — | Draw a hairline under the bar. Default false. |
| `label` | `ReactNode` | no | — | Optional mono eyebrow rendered before the chip row. |
| `mode` | `enum` | no | — | Selection mode. `single` (default) keeps exactly one chip active. Selection mode. `multiple` toggles any number of chips. |
| `onValueChange` | `((value: string) => void)` | no | — | Fires with the newly selected value. |
| `onValuesChange` | `((values: string[]) => void)` | no | — | Fires with the next set of selected values. |
| `options` | `FilterOption[]` | yes | — | The filter options. |
| `style` | `CSSProperties` | no | — | — |
| `value` | `string` | no | — | Controlled selected value. Pair with `onValueChange`. |
| `values` | `string[]` | no | — | Controlled selected values. Pair with `onValuesChange`. |

## Examples

### Basics

Default `single` mode keeps exactly one chip active. Pass bare strings as `options` and control the selection via `value` / `onValueChange`.

```tsx
import { useState } from "react";
import { FilterBar } from "@protocore/pds";

const CATEGORIES = ["All", "Compute", "Storage", "Networking", "Identity"];

export default function Demo() {
  const [category, setCategory] = useState("All");

  return (
    <FilterBar
      label="Filter services"
      options={CATEGORIES}
      value={category}
      onValueChange={setCategory}
    />
  );
}
```

### Multiple selection

Set `mode="multiple"` to toggle any number of chips. Options can be `{ value, label }` objects; the selection is a `string[]` driven by `values` / `onValuesChange`.

```tsx
import { useState } from "react";
import { FilterBar, Text } from "@protocore/pds";

const STATUSES = [
  { value: "healthy", label: "Healthy" },
  { value: "degraded", label: "Degraded" },
  { value: "down", label: "Down" },
  { value: "paused", label: "Paused" },
];

export default function Demo() {
  const [values, setValues] = useState<string[]>(["degraded", "down"]);

  return (
    <div style={{ display: "grid", gap: 12 }}>
      <FilterBar
        mode="multiple"
        label="Status"
        options={STATUSES}
        values={values}
        onValuesChange={setValues}
      />
      <Text size="sm" color="muted">
        {values.length
          ? `Showing ${values.length} status${values.length > 1 ? "es" : ""}`
          : "Showing all"}
      </Text>
    </div>
  );
}
```

## Do & don't

**Do**

- Use it directly above the collection it filters so the relationship is obvious.
- Include an 'All' option in `single` mode so users can clear the filter.
- Switch to `mode="multiple"` when facets are additive (status, tags, regions).
- Keep chip labels short — they're facets, not sentences.

**Don't**

- Don't use a FilterBar to pick a form value — that's a Select or RadioGroup.
- Don't overflow the row with dozens of chips; move long facet sets into a Select.
- Don't mix `single`-mode props (`value`) with `multiple`-mode props (`values`).
- Don't use it to switch view modes — a SegmentedControl signals that better.

## Accessibility

**Keyboard**

| Keys | Action |
| --- | --- |
| `Tab` | Move focus to the next chip. |
| `Space / Enter` | Toggle the focused chip's selected state. |

**Notes**

- The bar is a `role="group"`; each chip is a real button reflecting its pressed state.
- Selection is signalled by the inverted fill plus state, not colour alone.
- Give the bar meaning with the `label` eyebrow or an ambient heading so the filter set is named.

## Related

`chip`, `segmented-control`, `checkbox`, `search-input`

---

© Protocore. All rights reserved. Use of the Protocore Design System requires prior written authorization from Protocore (contact@protocore.io). These machine-readable materials must not be ingested into ML-training datasets or derivative design systems. See https://pds.protocore.io/legal/
