FilterList
A comprehensive guide for using the FilterList component from @osdk/react-components.
Prerequisites
Before using FilterList, make sure you have completed the library setup described in the README, including:
- Installing the required dependencies
- Wrapping your app with
OsdkProvider - Adding the CSS imports
Table of Contents
Import
import { FilterList } from "@osdk/react-components/experimental/filter-list";
Basic Usage
@my/osdk and ./client@my/osdk is a placeholder for your generated SDK package (e.g. @your-app/sdk). ./client is the file in your app where you exported the OSDK client returned by createClient(...). Replace both with the actual paths in your project.
The simplest way to use FilterList is with an objectSet and a few filter definitions:
import { Employee } from "@my/osdk";
import { FilterList } from "@osdk/react-components/experimental/filter-list";
import client from "./client";
function EmployeeFilters() {
return (
<FilterList
objectSet={client(Employee)}
filterDefinitions={[
{
type: "PROPERTY",
key: "department",
filterComponent: "LISTOGRAM",
},
{
type: "PROPERTY",
key: "jobTitle",
filterComponent: "LISTOGRAM",
},
]}
/>
);
}
Props Reference
Type parameters: Q extends ObjectTypeDefinition
| Name | Type | Description |
|---|---|---|
objectType | Q | Required. The object type definition for the objects being filtered. Used for metadata resolution (property types, display names). |
objectSet | ObjectSet<Q> | Optional object set to scope aggregation queries. When omitted, aggregations run against the full object type. |
filterClause | WhereClause<Q> | The current where clause to filter the objectSet. If provided, the filter clause is controlled. LINKED_PROPERTY filters are not included; use onEffectiveObjectSet. |
onFilterClauseChanged | (newClause: WhereClause<Q>) => void | Called when the filter clause changes. Required in controlled mode. |
title | ReactNode | Optional title to display in the filter list header |
titleIcon | React.ReactNode | Optional icon to display next to the title |
filterDefinitions | Array<FilterDefinitionUnion<Q>> | The definition for all supported filter items in the list If not supplied, all filterable properties will be available |
onFilterStateChanged | (definition: FilterDefinitionUnion<Q>, newState: FilterStateType) => void | Called when filter state changes |
onEffectiveObjectSet | (objectSet: ObjectSet<Q>) => void | Called with the narrowed ObjectSet whenever filters change. Requires objectSet to be set.A linked filter only narrows the set when its definition has reverseLinkName. Linked filters without it are skipped here; read their state from onFilterStateChanged instead. |
showFilteredOutValues | boolean | When true, facets render greyed-out count=0 rows for values present in the unfiltered data but excluded by other active filters. Defaults to false. |
addFilterMode | "controlled" | "uncontrolled" | Controls how filter visibility (add/remove) is managed. - "uncontrolled" (default): FilterList manages visibility internally. An "Add filter" popover is rendered for filters with isVisible: false, and each visible filter shows a remove button. - "controlled": The consumer manages which filters are visible via filterDefinitions. Filters with isVisible: false are excluded from the rendered list. Defaults to "uncontrolled". |
onFilterAdded | (filterKey: FilterKey<Q>, newDefinitions: Array<FilterDefinitionUnion<Q>>) => void | Called when a filter is added (shown). In uncontrolled mode, this fires when a user selects a hidden filter from the "Add filter" popover. |
onFilterRemoved | (filterKey: FilterKey<Q>) => void | Called when a filter is removed (hidden). In uncontrolled mode, this fires as a notification after the filter is hidden internally. |
onFilterVisibilityChange | (newStates: Array<{ filterKey: FilterKey<Q>; isVisible: boolean; }>) => void | Called when filter visibility or ordering changes, i.e. when filters are reordered, or (in uncontrolled mode) added or removed via the built-in show/remove controls. |
enableSorting | boolean | Enable drag-and-drop reordering of filters. When true, drag handles are rendered and filters can be reordered. Reorder state is managed internally; consumers who need to track order should use controlled filterDefinitions. |
collapsed | boolean | Whether the filter list panel is collapsed |
onCollapsedChange | (collapsed: boolean) => void | Called when the collapsed state changes |
initialFilterStates | Map<string, FilterStateType> | Initial filter states for hydrating from external storage. These states are merged over definition defaults on mount. Use onFilterStateChanged to persist state changes externally. |
showResetButton | boolean | Show reset filters button in header |
onReset | () => void | Called when reset button is clicked |
showActiveFilterCount | boolean | Show count of active filters in header |
className | string | Additional CSS class name |
renderAddFilterButton | () => React.ReactNode | Custom render function for the "Add filter" button. - In uncontrolled mode: customizes the trigger element for the built-in add-filter popover. The popover behavior is handled automatically. - In controlled mode: replaces the entire add-filter button area. The consumer is responsible for all add-filter behavior. |
Filter Definitions
Filter Definition Types
| Type | Description |
|---|---|
PROPERTY | Filter on a direct property of the object type |
KEYWORD_SEARCH | Full-text keyword search across objects |
CUSTOM | Custom filter with user-provided render function |
HAS_LINK | Toggle filter for whether a link exists |
LINKED_PROPERTY | Filter on a property of a linked object type |
STATIC_VALUES | Filter on a fixed list of values (no OSDK fetching) |
Each filter definition type's fields are documented below.
Property Filter Definition
When using type: "PROPERTY", the definition supports:
Type parameters: Q extends ObjectTypeDefinition, K extends PropertyKeys<Q> = PropertyKeys<Q>, C extends ValidComponentsForPropertyType<PropertyTypeFromKey<Q, K>> = ValidComponentsForPropertyType<PropertyTypeFromKey<Q, K>>
| Name | Type | Description |
|---|---|---|
searchField | boolean | When false, the header monocle (search-values icon) is hidden even for filter components that ordinarily support in-filter search. Useful for MULTI_SELECT, which already has its own inline search field. Defaults to true. |
type | "PROPERTY" | Required. Discriminator for filter definition type |
id | string | Optional unique identifier for stable keying across filter reorders. |
key | K | Required. The property key to filter on |
label | string | Display label for the filter |
filterComponent | C | Required. The filter component type to render Must be compatible with the property type derived from the key, see ValidComponentsForPropertyType |
filterState | FilterStateByComponentType[C] | Required. The current state of the filter. If provided, the filter is controlled. |
colorMap | Record<string, string> | Maps filter values to colors for visual differentiation. Used by LISTOGRAM (per-row bar colors). |
listogramConfig | { displayMode?: "full" | "count" | "minimal"; maxVisibleItems?: number; } | Configuration for LISTOGRAM display mode. Only applies when filterComponent is "LISTOGRAM". |
renderValue | (value: string) => ReactNode | Custom display function for filter values. Replaces the default string display in dropdown items, chips, and listogram rows. When the function returns a string, that string is also used for search matching within filter dropdowns. When it returns a non-string ReactNode, search falls back to the raw value. |
showCount | boolean | Show aggregation counts next to filter option values. Applies to LISTOGRAM, SINGLE_SELECT, and MULTI_SELECT components. Defaults to true for LISTOGRAM and MULTI_SELECT, false for SINGLE_SELECT. |
clickToFilter | boolean | When true, clicking a bar in the histogram replaces the filter range with that bucket's [min, max]. Only applies to histogram-rendering filter components (NUMBER_RANGE and DATE_RANGE); ignored on other component types.Click replaces the current range — clicking a second bar discards the previous selection. Multi-bucket selection / shift+click union is NOT supported in v1. Defaults to false. |
isVisible | boolean | Controls whether this filter is rendered. When false, the filter is hidden but its state is preserved. Defaults to true. |
Listogram Configuration
| Field | Type | Default | Description |
|---|---|---|---|
displayMode | "full" | "count" | "minimal" | "full" | full: bar + count, count: count only, minimal: label only |
maxVisibleItems | number | 5 | Number of items shown before "View all" link appears |
Keyword Search Filter Definition
When using type: "KEYWORD_SEARCH", the definition supports:
Type parameters: Q extends ObjectTypeDefinition, K extends StringPropertyKeys<Q> = StringPropertyKeys<Q>
| Name | Type | Description |
|---|---|---|
searchField | boolean | When false, the header monocle (search-values icon) is hidden even for filter components that ordinarily support in-filter search. Useful for MULTI_SELECT, which already has its own inline search field. Defaults to true. |
type | "KEYWORD_SEARCH" | Required. |
id | string | Optional unique identifier for stable keying across filter reorders. |
properties | "all" | K[] | Required. Properties to search within - "all": Search all string properties - K[]: Search specific string properties |
label | string | |
filterState | KeywordSearchFilterState | Controlled state for the filter. When provided, the filter becomes controlled and changes should be handled via onFilterStateChanged callback. |
defaultFilterState | KeywordSearchFilterState | Default state for uncontrolled mode. Used when filterState is not provided. |
isVisible | boolean | Controls whether this filter is rendered. When false, the filter is hidden but its state is preserved. Defaults to true. |
Has-Link Filter Definition
When using type: "HAS_LINK", the definition supports:
Type parameters: Q extends ObjectTypeDefinition, L extends LinkNames<Q> = LinkNames<Q>
| Name | Type | Description |
|---|---|---|
searchField | boolean | When false, the header monocle (search-values icon) is hidden even for filter components that ordinarily support in-filter search. Useful for MULTI_SELECT, which already has its own inline search field. Defaults to true. |
type | "HAS_LINK" | Required. |
id | string | Optional unique identifier for stable keying across filter reorders. |
linkName | L | Required. |
label | string | |
filterState | HasLinkFilterState | Required. |
defaultFilterState | HasLinkFilterState | |
isVisible | boolean | Controls whether this filter is rendered. When false, the filter is hidden but its state is preserved. Defaults to true. |
Linked Property Filter Definition
When using type: "LINKED_PROPERTY", the definition supports:
Type parameters: Q extends ObjectTypeDefinition, L extends LinkNames<Q>, LinkedQ extends ObjectTypeDefinition = LinkedType<Q, L>, LinkedK extends PropertyKeys<LinkedQ> = PropertyKeys<LinkedQ>, LinkedC extends ValidComponentsForPropertyType<PropertyTypeFromKey<LinkedQ, LinkedK>> = ValidComponentsForPropertyType<PropertyTypeFromKey<LinkedQ, LinkedK>>
| Name | Type | Description |
|---|---|---|
searchField | boolean | When false, the header monocle (search-values icon) is hidden even for filter components that ordinarily support in-filter search. Useful for MULTI_SELECT, which already has its own inline search field. Defaults to true. |
type | "LINKED_PROPERTY" | Required. |
id | string | Optional unique identifier for stable keying across filter reorders. |
linkName | L | Required. |
reverseLinkName | LinkNames<LinkedQ> | Set this to make the filter narrow objectSet; the result is emitted via onEffectiveObjectSet. The value names the link on the linked object type that points back to Q (the inverse of linkName).Leave unset to keep the filter UI-only. It still renders and fires onFilterStateChanged, but FilterList won't narrow on it. |
linkedPropertyKey | LinkedK | Required. |
linkedFilterComponent | LinkedC | Required. |
linkedFilterState | FilterStateByComponentType[LinkedC] | Required. |
defaultLinkedFilterState | FilterStateByComponentType[LinkedC] | |
filterState | LinkedPropertyFilterState<FilterStateByComponentType[LinkedC]> | Required. |
label | string | |
showCount | boolean | Show aggregation counts next to filter option values. Applies to LISTOGRAM, SINGLE_SELECT, and MULTI_SELECT linked components. Defaults to true for LISTOGRAM and MULTI_SELECT, false for SINGLE_SELECT. |
renderValue | (value: string) => ReactNode | Custom display function for filter values. Replaces the default string display in dropdown items, chips, and listogram rows. When the function returns a string, that string is also used for search matching within filter dropdowns. When it returns a non-string ReactNode, search falls back to the raw value. |
isVisible | boolean | Controls whether this filter is rendered. When false, the filter is hidden but its state is preserved. Defaults to true. |
Two modes for LINKED_PROPERTY
Auto-narrowing — set reverseLinkName. FilterList composes pivotTo(linkName).where(...).pivotTo(reverseLinkName) and emits the narrowed set via onEffectiveObjectSet:
{
type: "LINKED_PROPERTY",
linkName: "manager", // Employee → Manager
reverseLinkName: "directReports", // Manager → Employee (back-link)
linkedPropertyKey: "fullName",
linkedFilterComponent: "MULTI_SELECT",
linkedFilterState: { type: "SELECT", selectedValues: [] },
filterState: { type: "linkedProperty", linkedFilterState: { type: "SELECT", selectedValues: [] } },
}
UI-only — omit reverseLinkName. The filter still renders and fires onFilterStateChanged; downstream narrowing is up to the consumer:
{
type: "LINKED_PROPERTY",
linkName: "manager",
// no reverseLinkName — FilterList won't narrow objectSet on this filter
linkedPropertyKey: "fullName",
linkedFilterComponent: "MULTI_SELECT",
linkedFilterState: { type: "SELECT", selectedValues: [] },
filterState: { type: "linkedProperty", linkedFilterState: { type: "SELECT", selectedValues: [] } },
}
Custom Filter Definition
When using type: "CUSTOM", the definition supports:
Type parameters: Q extends ObjectTypeDefinition, State extends BaseFilterState = CustomFilterState
| Name | Type | Description |
|---|---|---|
searchField | boolean | When false, the header monocle (search-values icon) is hidden even for filter components that ordinarily support in-filter search. Useful for MULTI_SELECT, which already has its own inline search field. Defaults to true. |
type | "CUSTOM" | Required. |
id | string | Optional unique identifier for stable keying across filter reorders. If provided, takes precedence over key for state keying. |
key | string | Required. Unique key for this custom filter |
label | string | |
filterComponent | "CUSTOM" | Required. |
filterState | State | Required. |
defaultFilterState | State | |
renderInput | (props: CustomFilterInputRendererProps<Q, State>) => ReactNode | Render the input portion of the filter Used when rendering within a filter item wrapper |
renderItem | (props: CustomFilterItemRendererProps<Q, State>) => ReactNode | Render the complete filter item Used when you need full control over the item appearance |
toWhereClause | (state: State) => WhereClause<Q> | undefined | Required. Convert filter state to a WhereClause for filtering Required for the filter to affect the object set |
isVisible | boolean | Controls whether this filter is rendered. When false, the filter is hidden but its state is preserved. Defaults to true. |
Static Values Filter Definition
When using type: "STATIC_VALUES", the definition supports:
Type parameters: Q extends ObjectTypeDefinition, C extends StaticValuesComponentType = StaticValuesComponentType
| Name | Type | Description |
|---|---|---|
searchField | boolean | When false, the header monocle (search-values icon) is hidden even for filter components that ordinarily support in-filter search. Useful for MULTI_SELECT, which already has its own inline search field. Defaults to true. |
type | "STATIC_VALUES" | Required. |
id | string | Optional unique identifier for stable keying across filter reorders. If provided, takes precedence over key for state keying. |
key | string | Required. Key used for state management and auto WHERE clause generation. When toWhereClause is not provided, this is used as the property key in the generated WHERE clause. |
label | string | Display label for the filter |
filterComponent | C | Required. The filter component type to render |
filterState | FilterStateByComponentType[C] | Required. The current state of the filter |
values | string[] | Required. The static list of values to display in the filter component. These are rendered directly without OSDK aggregation. |
renderValue | (value: string) => ReactNode | Custom display function for filter values. Replaces the default string display in dropdown items, chips, and listogram rows. When the function returns a string, that string is also used for search matching within filter dropdowns. When it returns a non-string ReactNode, search falls back to the raw value. |
showCount | boolean | Show aggregation counts next to filter option values. Applies to LISTOGRAM, SINGLE_SELECT, and MULTI_SELECT components. Defaults to true for LISTOGRAM and MULTI_SELECT, false for SINGLE_SELECT. |
colorMap | Record<string, string> | Maps filter values to colors for visual differentiation. Used by LISTOGRAM (per-row bar colors). |
listogramConfig | { displayMode?: "full" | "count" | "minimal"; maxVisibleItems?: number; } | Configuration for LISTOGRAM display mode. Only applies when filterComponent is "LISTOGRAM". |
toWhereClause | (state: FilterState) => WhereClause<Q> | undefined | Optional custom WHERE clause generator. When provided, this is used instead of auto-generating a WHERE clause from the key and filter state. |
isVisible | boolean | Controls whether this filter is rendered. When false, the filter is hidden but its state is preserved. Defaults to true. |
Filter Components
When using type: "PROPERTY" or type: "LINKED_PROPERTY", specify a filterComponent:
| Component | Best For | State Type |
|---|---|---|
LISTOGRAM | Categorical data with bar chart | EXACT_MATCH |
SINGLE_SELECT | Single value dropdown | SELECT |
MULTI_SELECT | Multi-select dropdown with search | SELECT |
TEXT_TAGS | Tag-based input with suggestions | EXACT_MATCH |
CONTAINS_TEXT | Free-text search on a property | CONTAINS_TEXT |
NUMBER_RANGE | Min/max range slider for numbers | NUMBER_RANGE |
DATE_RANGE | Date range picker | DATE_RANGE |
TOGGLE | Boolean on/off toggle | TOGGLE |
SINGLE_DATE | Single date picker | SELECT |
MULTI_DATE | Multiple date picker | SELECT |
TIMELINE | Date range with start/end | TIMELINE |
Examples
Combining with ObjectTable
Use controlled filterClause to connect FilterList and ObjectTable:
import { Employee } from "@my/osdk";
import type { WhereClause } from "@osdk/api";
import { FilterList } from "@osdk/react-components/experimental/filter-list";
import { ObjectTable } from "@osdk/react-components/experimental/object-table";
import { useMemo, useState } from "react";
import client from "./client";
function EmployeeDashboard() {
const [filterClause, setFilterClause] = useState<
WhereClause<typeof Employee>
>({});
const objectSet = useMemo(() => client(Employee), []);
return (
<div style={{ display: "flex", gap: 16, height: 600 }}>
<div style={{ width: 320, flexShrink: 0 }}>
<FilterList
objectSet={objectSet}
filterDefinitions={[
{
type: "PROPERTY",
key: "department",
filterComponent: "LISTOGRAM",
},
{ type: "PROPERTY", key: "team", filterComponent: "LISTOGRAM" },
{
type: "PROPERTY",
key: "fullName",
filterComponent: "CONTAINS_TEXT",
},
]}
title="Employee Filters"
showResetButton={true}
showActiveFilterCount={true}
enableSorting={true}
filterClause={filterClause}
onFilterClauseChanged={setFilterClause}
/>
</div>
<div style={{ flex: 1 }}>
<ObjectTable objectType={Employee} filter={filterClause} />
</div>
</div>
);
}
Add/Remove Filters (Uncontrolled Mode)
Use addFilterMode="uncontrolled" with isVisible: false on some filters to let users add and remove filters dynamically:
const filterDefinitions = [
{
type: "PROPERTY",
key: "department",
label: "Department",
filterComponent: "LISTOGRAM",
filterState: { type: "EXACT_MATCH", values: [] },
},
{
type: "PROPERTY",
key: "team",
label: "Team",
filterComponent: "LISTOGRAM",
filterState: { type: "EXACT_MATCH", values: [] },
},
{
type: "PROPERTY",
key: "fullName",
label: "Full Name",
filterComponent: "CONTAINS_TEXT",
filterState: { type: "CONTAINS_TEXT" },
isVisible: false,
},
{
type: "PROPERTY",
key: "startDate",
label: "Start Date",
filterComponent: "DATE_RANGE",
filterState: { type: "DATE_RANGE" },
isVisible: false,
},
];
<FilterList
objectSet={client(Employee)}
filterDefinitions={filterDefinitions}
addFilterMode="uncontrolled"
showResetButton={true}
/>;
Filters marked isVisible: false appear in the "Add filter" popover. Users can add them to the list and remove visible filters via the close button. Reset restores the original visibility.
Removable Filters (Controlled Mode)
When addFilterMode="controlled" and onFilterRemoved is provided, each filter shows a remove button on hover. The consumer manages the definitions array:
const [definitions, setDefinitions] = useState(filterDefinitions);
const handleFilterRemoved = (filterKey) => {
setDefinitions(prev => prev.filter(def => def.key !== filterKey));
};
<FilterList
objectSet={client(Employee)}
filterDefinitions={definitions}
addFilterMode="controlled"
onFilterRemoved={handleFilterRemoved}
title="Removable Filters"
/>;
Prefiltered ObjectSet
Pass a .where() objectSet to scope filter dropdown values. For example, to only show Engineering employees:
import { Employee } from "@my/osdk";
import { FilterList } from "@osdk/react-components/experimental/filter-list";
import { useMemo } from "react";
import client from "./client";
function EngineeringFilters() {
const engineeringSet = useMemo(
() => client(Employee).where({ department: "Engineering" }),
[],
);
return (
<FilterList
objectSet={engineeringSet}
filterDefinitions={[
{ type: "PROPERTY", key: "jobTitle", filterComponent: "LISTOGRAM" },
{ type: "PROPERTY", key: "location", filterComponent: "LISTOGRAM" },
]}
/>
);
}
The filter dropdowns will only show job titles and locations that exist within the Engineering department.
Keyword Search Filter
Add a full-text search filter that searches across multiple properties:
const filterDefinitions = [
{
type: "KEYWORD_SEARCH",
properties: ["fullName", "department", "jobTitle", "locationCity"],
label: "Search",
},
{ type: "PROPERTY", key: "department", filterComponent: "LISTOGRAM" },
{ type: "PROPERTY", key: "locationCity", filterComponent: "LISTOGRAM" },
];
<FilterList
objectSet={client(Employee)}
filterDefinitions={filterDefinitions}
/>;
Custom Listogram Colors
Assign colors to specific values in a listogram:
<FilterList
objectSet={client(Employee)}
filterDefinitions={[
{
type: "PROPERTY",
key: "department",
filterComponent: "LISTOGRAM",
colorMap: {
Engineering: "#3b82f6",
Marketing: "#f59e0b",
Sales: "#10b981",
Design: "#8b5cf6",
},
},
]}
/>;
Custom Value Rendering
Use renderValue to customize how filter values are displayed and searched. The returned string replaces the raw value for both display and search matching. This is useful for showing human-readable names instead of IDs:
const USER_NAMES: Record<string, string> = {
"abc-123": "Alice Smith",
"def-456": "Bob Jones",
};
<FilterList
objectSet={client(Task)}
filterDefinitions={[
{
type: "PROPERTY",
key: "assigneeUserId",
filterComponent: "LISTOGRAM",
renderValue: (userId) => USER_NAMES[userId] ?? userId,
},
]}
/>;
renderValue works with LISTOGRAM, SINGLE_SELECT, and MULTI_SELECT filter components. For MULTI_SELECT, it applies to both dropdown items and selected chips. Searching within a filter dropdown matches against the renderValue output.
For best performance, memoize renderValue with useCallback to avoid unnecessary re-renders:
Listogram Display Modes
Control how much detail each listogram row shows:
// "full" (default): checkbox + label + colored bar + count number
// "count": checkbox + label + count number (no bar)
// "minimal": checkbox + label only
<FilterList
objectSet={client(Employee)}
filterDefinitions={[
{
type: "PROPERTY",
key: "department",
filterComponent: "LISTOGRAM",
listogramConfig: { displayMode: "count" },
},
]}
/>;
Limiting Visible Items
By default, LISTOGRAM filters show at most 5 items with a "View all" link. Override with maxVisibleItems:
<FilterList
objectSet={client(Employee)}
filterDefinitions={[
{
type: "PROPERTY",
key: "department",
filterComponent: "LISTOGRAM",
listogramConfig: { maxVisibleItems: 10 },
},
]}
/>;
Collapsible Panel
Make the filter list collapsible:
import { useState } from "react";
function CollapsibleFilters() {
const [collapsed, setCollapsed] = useState(false);
return (
<FilterList
objectSet={client(Employee)}
title="Filters"
collapsed={collapsed}
onCollapsedChange={setCollapsed}
showActiveFilterCount={true}
filterDefinitions={[
{ type: "PROPERTY", key: "department", filterComponent: "LISTOGRAM" },
]}
/>
);
}
Drag-and-Drop Sorting
Enable reordering of filters via drag and drop:
<FilterList
objectSet={client(Employee)}
filterDefinitions={filterDefinitions}
enableSorting={true}
/>;
Exclude Toggle
LISTOGRAM and TEXT_TAGS filters support an exclude/include toggle. Hover a filter item and click the three-dot menu to toggle between "Keeping" and "Excluding" modes. When excluding, selected values are excluded from results and appear with a strikethrough.
// Exclude mode is built into LISTOGRAM filters automatically.
// Users access it via the overflow menu (three dots) on each filter item.
<FilterList
objectSet={client(Employee)}
filterDefinitions={[
{
type: "PROPERTY",
key: "department",
filterComponent: "LISTOGRAM",
filterState: { type: "EXACT_MATCH", values: [] },
},
]}
/>;
Styling
FilterList uses CSS custom properties included in @osdk/react-components/styles.css for theming. Override --osdk-* tokens to customize FilterList without affecting other components, or override --bp-* tokens for global theming.
@layer osdk.styles, user.theme;
@import "@osdk/react-components/styles.css" layer(osdk.styles);
@layer user.theme {
:root {
--osdk-intent-primary-rest: #2563eb;
--osdk-intent-primary-hover: #1d4ed8;
}
}
Use the className prop for scoped styling:
<FilterList
objectSet={client(Employee)}
className="my-custom-filters"
filterDefinitions={[...]}
/>
For a full reference of CSS tokens, see the CSS Variables documentation.
Best Practices
- Memoize filterDefinitions -- define the array outside the component or wrap in
useMemoto avoid unnecessary re-renders - Use controlled mode for persistence -- provide
filterClauseandonFilterClauseChangedto persist filter state across navigation - Use objectSet constraints to scope filter values -- pass a prefiltered objectSet (e.g.
client(Employee).where(...)) so filter dropdowns only show relevant values - Keep filter lists focused -- show 3-8 filters; too many filters overwhelm users
- Use
addFilterMode="uncontrolled"for progressive disclosure -- start with a few visible filters and let users add more as needed