OPERATOR

FilterBar

Single select

Multiple select

value, defaultValue, and onValueChange use a string, or string[] with multiple (filters, value and defaultValue also take readonly arrays). The callback receives the complete selection. Clear with "" (single) or [] (multiple).

import { useState } from "react";
 
const [active, setActive] = useState<string[]>(["FRIENDLY"]);
 
<FilterBar
  filters={["FRIENDLY", "HOSTILE", "NEUTRAL"]}
  multiple
  value={active}
  onValueChange={setActive}
  ariaLabel="Track classes"
/>;

Use disabled to block both keyboard and pointer changes without discarding the selected filters.

Native div attributes reach the group element: id, data-*, title, tabIndex, focus, blur and key handlers, and the rest. Handlers run before React Aria's own, so arrow-key movement keeps working. Three are not applied: role and aria-orientation, because the group is a radio group (single) or a toolbar (multiple) whose filters wrap, and dangerouslySetInnerHTML, because the filters come from filters; in development a structured PROP_NOT_APPLIED error says so.

Layout

When the filters do not fit, they wrap onto more rows and the bar grows taller, so every filter stays visible and the bar never widens its container. A long label wraps inside its filter, which grows to hold it, and an unbroken one breaks anywhere. Each label in filters is shown once.

A selection the list does not offer

A selected value that is not in filters (a retired class, a saved view restored from a link, a list built from the data loaded now) shows at the end of the bar as a selected filter marked Unavailable, so the bar never hides an active filter. In multiple mode the operator clears it like any other filter; in single mode choosing another filter replaces it. When it goes, keyboard focus moves to the filter in its place. In development a structured UNKNOWN_FILTER_VALUE error names the value; add it to filters if it is still offered. In multiple mode an empty string in the selection (an empty query parameter split on commas gives [""]) is such a value too: it shows as a dash, "—", marked Unavailable, and is reported the same way. In single mode "" still means no selection.

<FilterBar
  filters={["FRIENDLY", "HOSTILE", "NEUTRAL"]}
  multiple
  value={["FRIENDLY", "RETIRED"]}
  onValueChange={setActive}
  ariaLabel="Track classes"
/>
// FRIENDLY and RETIRED (Unavailable) are selected; pressing RETIRED reports ["FRIENDLY"].

Props

PROPTYPEDEFAULTREQUIRED
filters

Readonly string[] of filter labels, each shown once, in order.

array—yes
value

Controlled selection: string in single mode; readonly string[] when multiple=true. Use an empty string or array to clear the corresponding mode. A selected value that is not in filters shows at the end of the bar as a selected filter marked unavailable, which the operator can remove.

string | array—no
defaultValue

Initial uncontrolled selection: string in single mode; readonly string[] when multiple=true.

string | array—no
multiple

When true, value, defaultValue, and onValueChange use string[] and a selected filter can be cleared; otherwise they use string and the filters are radios, so the active filter stays selected until another is chosen.

booleanfalseno
ariaLabel

Accessible name for the group.

string"Filters"no
disabled

Disable pointer and keyboard selection while retaining the active filters.

booleanfalseno
onValueChange

Receives the active string in single mode or the complete string[] selection when multiple=true.

function—no
classNamestring—no

Accessibility

  • Name the group with ariaLabel. Single selection uses radiogroup / radio; multiple selection uses toggle buttons.
  • Arrow keys move focus. Space or Enter selects a filter. In single mode the filters are radios: the active filter stays selected until another is chosen. In multiple mode Space or Enter also clears a selected filter.
  • Selection adds data-selected, accent fill, and aria-checked (single) or aria-pressed (multiple). Unselected filters have the control outline. Filters have visible focus rings.
  • In forced-colors (high contrast) mode the selected filter is drawn in the system highlight color, a disabled selected one in the system's disabled color, and focus as an outline.
  • An unavailable value carries the written cue "Unavailable" and its accessible name is RETIRED, Unavailable for a value RETIRED.

Manifest entry

<FilterBar filters={["ALL","FRIENDLY","HOSTILE","NEUTRAL","UNKNOWN"]} defaultValue="ALL" />
View agent manifest
{
  "description": "Toggle-button filters for a view, wrapping onto more rows when they do not fit. Single-select by default; set multiple for multi-select.",
  "props": {
    "filters": {
      "type": "array",
      "required": true,
      "description": "Readonly string[] of filter labels, each shown once, in order."
    },
    "value": {
      "type": "union",
      "types": [
        "string",
        "array"
      ],
      "description": "Controlled selection: string in single mode; readonly string[] when multiple=true. Use an empty string or array to clear the corresponding mode. A selected value that is not in filters shows at the end of the bar as a selected filter marked unavailable, which the operator can remove."
    },
    "defaultValue": {
      "type": "union",
      "types": [
        "string",
        "array"
      ],
      "description": "Initial uncontrolled selection: string in single mode; readonly string[] when multiple=true."
    },
    "multiple": {
      "type": "boolean",
      "default": false,
      "description": "When true, value, defaultValue, and onValueChange use string[] and a selected filter can be cleared; otherwise they use string and the filters are radios, so the active filter stays selected until another is chosen."
    },
    "ariaLabel": {
      "type": "string",
      "default": "Filters",
      "description": "Accessible name for the group."
    },
    "disabled": {
      "type": "boolean",
      "default": false,
      "description": "Disable pointer and keyboard selection while retaining the active filters."
    },
    "onValueChange": {
      "type": "function",
      "description": "Receives the active string in single mode or the complete string[] selection when multiple=true."
    },
    "className": {
      "type": "string"
    }
  },
  "composable_with": [
    "Card"
  ],
  "never_inside": [
    "Button",
    "Badge"
  ],
  "example": "<FilterBar filters={[\"ALL\",\"FRIENDLY\",\"HOSTILE\",\"NEUTRAL\",\"UNKNOWN\"]} defaultValue=\"ALL\" />"
}

On this page