Documentation Index
Fetch the complete documentation index at: https://anvil.servicetitan.com/llms.txt
Use this file to discover all available pages before exploring further.
This guide covers changes to the beta FilterBar component. These APIs may
continue to evolve before the stable release.
Overview
FilterBar’ssingleSelect and multiSelect filter types have been reworked to use the platform’s existing select components rather than FilterBar’s own narrower implementation:
singleSelectfilters now renderSelectMenuSyncin the toolbar andSelectFieldSyncin the drawer.multiSelectfilters now renderMultiSelectMenuSyncin the toolbar andMultiSelectFieldSyncin the drawer.
SelectMenuSyncProps / MultiSelectMenuSyncProps. Any feature those components support is available on the filter.
Design Rationale
Why adopt SelectMenu / MultiSelectMenu?
Three coordinate wins:- One aligned API. The filter’s prop surface is now
SelectMenuSyncProps/MultiSelectMenuSyncProps. Anyone familiar with the platform’s select components already knows how the filter behaves, and the documentation, types, and examples for those components apply directly. Async filters (asyncSelect/asyncMultiSelect) already adoptSelectMenu/MultiSelectMenu; the static-options variants now match their lazy siblings. - One implementation to maintain. Previously FilterBar carried its own popover bodies built on
Combobox,Listbox, andListView, with the toolbar and drawer using different UIs that needed separate tests and drifted independently. Bug fixes and feature work on the platform’s select components didn’t reach the filter. The filter now composes one component shared with everything else in the system. - Access to the full select feature set. Grouping, pinned options, virtualization, adaptive dialog-on-mobile, “Select All” / “Select Filtered”, search-text-vs-display-label distinctions, avatar / icon / chip content rows, “Add new item” affordances, customizable client-side filtering via match-sorter — none of that existed in FilterBar’s bespoke implementation. All of it is available on the filter now without per-filter glue code.
Why drop the Item generic?
The old filter types were generic over a consumer-defined Item extending { id, label }. The platform’s select components use a fixed SelectMenuOption shape:
extra and read it back from selectedOption.extra in their onFilterChange handler.
Reference
Field renames
| Old field | New field | Notes |
|---|---|---|
items | options | Now SelectMenuOption[] (single) / MultiSelectMenuOption[] (multi) |
selectedItem | selectedOption | singleSelect |
selectedItems | selectedOptions | multiSelect |
Removed fields
| Removed field | Why it’s gone |
|---|---|
hasSearch | The search field is part of SelectMenuSync’s UI and shown by default. Set disableSearch: true to hide it. |
onSearch | SelectMenuSync filters client-side via match-sorter. For custom behavior, pass a filter function or MatchSorterOptions. |
onSearchClear | Not applicable — search state lives inside SelectMenuSync. |
searchValue | Not applicable — search state lives inside SelectMenuSync. |
Newly available capabilities
These all come fromSelectMenuSync / MultiSelectMenuSync and didn’t exist on the old filter API:
| Prop | Type | Description |
|---|---|---|
filter | SyncFilterFn | MatchSorterOptions<…> | Override the default client-side filter (match-sorter over label and searchText). |
selectAll | boolean | { label } | (multiSelect) “Select All” checkbox shown when search is empty. Click and check state managed automatically. |
selectFiltered | boolean | ((searchValue: string) => { label }) | (multiSelect) “Select Filtered” checkbox shown when a search term is active. Replaces selectAll. |
disableSearch | boolean | Hide the search field inside the popover. |
pinned | SelectMenuPinnedOptions | Pin options to the top of the list. |
virtualize | boolean | Virtualize the list for large option sets. |
displayMenuAs | "auto" | "popover" | "dialog" | Override the adaptive popover/dialog rendering (auto = popover on desktop, dialog on mobile). |
groupSorter | (a, b) => number | Custom group ordering when options have group. |
groupToString | (group) => string | Format group values as headers. |
popoverWidth | "reference" | number | string | Override the popover width (defaults to 320; "reference" matches the trigger width). |
addItemLabel + onAddNewItem | … | Render an “Add new item” affordance below the option list. |
SelectMenuSyncProps / MultiSelectMenuSyncProps — see the SelectMenu and MultiSelectMenu docs for the full surface.
Option shape
Migration Guide
Basic single select
Basic multi select
Filters that previously wired hasSearch
hasSearch, onSearch, onSearchClear, and searchValue are removed. SelectMenuSync includes a search field by default and filters its own options via match-sorter. Drop the callbacks and the state they fed.
Custom filtering behavior
If the default match-sorter behavior isn’t what you want, pass afilter function or a MatchSorterOptions config — the same prop SelectMenuSync accepts:
selectAll and selectFiltered (multi-select only)
Not previously available on the old API — these are MultiSelectMenuSync features now exposed on the filter. Pass true for the default labels or { label } to customize:
unchecked / indeterminate / checked) are managed automatically against the current selectedOptions.
Custom option shapes (the Item generic)
If your old filter used a custom Item shape, move the extra fields into extra:
selectedOption.extra in your onFilterChange handler.
Server-backed options
If you were usingonSearch to fetch options from a server, switch to asyncSelect or asyncMultiSelect:
SelectMenu / MultiSelectMenu (rather than their *Sync siblings) and support eager loading plus three lazy modes (page, offset, group). See the Async Select and Async Multi Select sections in the main FilterBar docs.
Breaking Changes
- Field renames:
items→options,selectedItem→selectedOption,selectedItems→selectedOptions. hasSearch,onSearch,onSearchClear,searchValueremoved. The search field is part ofSelectMenuSyncand shown by default; filtering happens client-side via match-sorter. Hide the search field withdisableSearch: trueor override the filter behavior with the newfilterprop.- The
Itemgeneric is removed. Options use theSelectMenuOptionshape; custom domain data goes inextra.
Why Breaking?
Beta APIs can change without a deprecation cycle. The change replaces FilterBar’s parallel select implementation with the platform’sSelectMenu family — aligning the filter API with components consumers already use elsewhere, reducing FilterBar to one shared implementation instead of three, and exposing the full select feature set (grouping, virtualization, pinned options, “Select All” / “Select Filtered”, dialog mode on mobile, rich option content, etc.) on the filter. The shape change is mechanical; the gain is significant.