UnflowUI
Components

Toolbar & Panels

The composable-parts family behind DataTable's default toolbar — Toolbar, ToolbarButton, QuickFilter, ColumnsPanel, and FilterPanel — usable standalone or fully custom-composed.

Overview

This is a headless-style component family: behavior and accessibility live in each part, visuals are fully swappable via a render prop. DataTable's showToolbar mounts a default assembly of these same parts wired to its own state — reach for these directly when you want a fully custom toolbar (slots.toolbar on DataTable) or want to mount column/filter management somewhere other than a popover (e.g. a sidebar).

Import

import { Toolbar } from '@unflowio/ui/components/Toolbar';
import { ToolbarButton } from '@unflowio/ui/components/ToolbarButton';

Toolbar

role="toolbar" container with real roving-tabindex keyboard navigation: Tab/Shift+Tab enter or exit the whole toolbar as one stop; Left/Right move between items; Home/End jump to the first/last. Scans one focusable element per direct child — a child that opens its own popover (like ColumnsPanelTrigger) contributes only its own trigger to the roving set, not the popover's internal buttons.

ToolbarButton

A plain styled button — the element trigger components below render as, via their own render prop (e.g. <ColumnsPanelTrigger render={<ToolbarButton />}>). Props: icon, children, plus standard button props.

QuickFilter

A context-coordinated, expandable search box: QuickFilter (provider) + QuickFilterTrigger + QuickFilterControl + QuickFilterClear. Escape clears the value first, then collapses on a second press. The control's onChange is debounced (debounceMs, default 200) before propagating.

QuickFilter's own root renders one bordered pill around all three children (matching ButtonGroup's "border on the container, borderless children" convention) — growing to fill the available toolbar width once expanded, rather than each child bringing its own separate border. QuickFilterTrigger/QuickFilterClear render borderless by default for exactly this reason; only wrap them in render={<ToolbarButton />} if you're using them standalone, outside a QuickFilter pill.

<QuickFilter value={quickFilterValue} onValueChange={setQuickFilterValue}>
  <QuickFilterTrigger />
  <QuickFilterControl />
  <QuickFilterClear />
</QuickFilter>
ComponentKey props
QuickFiltervalue/defaultValue/onValueChange, expanded/defaultExpanded/onExpandedChange
QuickFilterTriggerrender — toggles expanded, focuses the control on expand
QuickFilterControldebounceMs — the text input, only rendered while expanded
QuickFilterClearrender — clears the value, hidden while empty/collapsed

Columns Panel

Full column-visibility management content — search, per-column toggle, show/hide-all, reset, and (when columnOrder/onColumnOrderChange are given) drag-and-drop reordering via a grip handle, plus move-up/move-down buttons as the keyboard-operable fallback.

ColumnsPanelTrigger composes the panel behind a button + popover:

PropTypeDescription
columns{ field, headerName?, hideable? }[]
visibilityModel / onVisibilityModelChangeRecord<string, boolean>
disableSearch?boolean
columnOrder? / onColumnOrderChange?string[]Enables reordering — native HTML5 drag via each row's grip handle, plus move-up/down buttons as the keyboard-operable fallback.

Filter Panel

Full filter-editing content — column select, operator select, value input, an AND/OR switch between rows, add/remove.

FilterPanelTrigger composes the panel behind a button + popover (with an active-filter-count badge):

PropTypeDescription
columns{ field, headerName?, filterable?, operators? }[]operators? overrides the built-in contains/equals/isEmpty/isNotEmpty set.
filterModel / onFilterModelChangeFilterModelSame model DataTable itself uses.

QuickFilterField

An always-visible, single-field alternative to the Filter Panel — one button per field, opening a popover whose body is one of three fixed layouts depending on filterType. Unlike everything else on this page, it isn't wired to FilterModel itself (that translation is DataTable's own inlineFilters — see Inline filters); each type commits through its own plain callback, so it stays reusable outside DataTable too.

PropTypeDescription
label / iconstring / ReactNodeThe trigger button's content.
filterType'select' | 'range' | 'date'Picks the popover body.
activebooleanShows the trigger's active-state dot/border. Defaults to inferring from the current value (non-empty selection/range/date).
options / selectedValues / onSelectedValuesChange{ value, label, icon?, render? }[] / string[] / (values) => voidfilterType: 'select' — checkbox list, search, and an "All" toggle. render swaps the default icon+label row for any node (e.g. a colored Tag matching the value's own cell rendering).
unit / rangeValue / onRangeValueChangestring / { min?, max? } / (value) => voidfilterType: 'range' — two numeric inputs, committed on every change (no separate apply step).
rangeBounds{ min, max }filterType: 'range' — the slider's overall domain. A dual-handle range slider renders above the inputs only once this is given.
currencyOptions / currencyValue / onCurrencyValueChange{ value, label }[] / string / (value) => voidfilterType: 'range' — an optional currency/unit-code select shown on both numeric inputs (one shared value drives both sides).
dateValue / onDateValueChange / dateShortcutsRangeDateValue / (value) => void / { label, value }[]filterType: 'date' — a real DatePickerDropdown in range mode.

Accessibility

  • Toolbar implements the WAI-ARIA toolbar pattern (roving tabindex, one Tab stop).
  • All popovers (ColumnsPanelTrigger/FilterPanelTrigger/QuickFilterField) trap focus and restore it on close, via the shared Popper primitive (the 'date' type instead reuses DatePickerDropdown's own popover).
  • FilterPanelTrigger's badge count is exposed to assistive tech via the trigger's own accessible name, not color alone.