Cal.comdesign-system

Data Table Filters

App-local data-table provider, toolbar, typed filter chips, search, and saved segments.

App-owned list filtering system used across org members, bookings, and other web tables. Callers own column definitions and queries; the App module owns URL state, segment tRPC wiring, and the stock toolbar composition.

Ownership

App — not @coss/ui/shared. Lives under apps/web/modules/data-table because it depends on nuqs URL keys, Zustand table state, and trpc.viewer.filterSegments.* for saved segments. Filter type serializers live in packages/features/data-table; UI orchestration stays App-local.

Presentational Shared shells — FilterChipShell, FilterAddMenu, FilterBarActions, ColumnVisibilityMenu — are reused inside App wrappers. Do not relocate the store-bound system into Coss.

Architecture

Use when

  • A web list needs URL-synced filters, search, column visibility, and/or saved segments.
  • You can pass a TanStack table instance into the stock toolbar or compose App filter pieces yourself.

Prefer DataTableToolbar for the stock bar. Custom toolbars (bookings) still use App FilterAddMenu / ActiveFilters / segments — not Shared filter shells alone.

Canonical usage

Org members table is the stock composition — provider + default toolbar + wrapper:

apps/web/modules/users/components/UserTable/UserListTable.tsx
apps/web/modules/users/components/UserTable/UserListTable.tsx

DataTableToolbar defaults (showColumnVisibility, showSavedSegments, showSearch all true) compose SearchField → column visibility → FilterAddMenu → saved-segment combobox → ActiveFilters. Pass only table for the stock bar.

Custom toolbar (bookings)

Bookings skips DataTableToolbar and composes App pieces next to status tabs / view toggle — see BookingListContainer.tsx (FilterAddMenu, FilterSegmentSavedCombobox, conditional ActiveFilters). Same store; different chrome.

Filter types

Also: SearchField, ColumnVisibilityButton, FilterAddMenu, ActiveFilters, FilterSegmentSavedCombobox under ~/data-table/components/....

Date range: App column filter ≠ Shared invoice widget

Do not substitute one for the other.

Why App-local

  • URL state via nuqs (activeFilters, q, segment, cols, pagination).
  • Saved segments via web tRPC.
  • Table identity (tableIdentifier) and column metadata are page-specific.

Reuse Shared shells for chrome; keep store/URL/segment wiring in apps/web/modules/data-table.

Call sites

Example URLs

Not exhaustive — a few places you can open locally (e.g. http://localhost:3000) to see this in product.

Source