Skip to content
Compositions

PageToolbar

A page's filter and view bar. It sits beneath the page header and holds to the top of the window, under the app's header, while the page scrolls: the filters on one side, scrolling sideways when there are more than fit, and the sort and view controls on the other. At rest it reads as part of the page; once it is holding, a hairline separates it from the content passing beneath. Import from "@instruments/materia-ui/compositions/page-toolbar".

Usage

import { PageToolbar, PageToolbarActions, PageToolbarActionsProps, PageToolbarApplied, PageToolbarAppliedProps, PageToolbarFilter, PageToolbarFilterProps, PageToolbarFilters, PageToolbarFiltersButton, PageToolbarFiltersButtonProps, PageToolbarFiltersProps, PageToolbarProps, PageToolbarSort, PageToolbarSortDirection, PageToolbarSortOption, PageToolbarSortProps, PageToolbarTableFilters, PageToolbarTableFiltersProps, PageToolbarTableSort, PageToolbarTableSortProps } from "@instruments/materia-ui/compositions/page-toolbar";

Best practices

  • Place it straight after the PageHeader, in the column that holds the page's content; the title scrolls away and the toolbar stays.

  • Order the leading side the same on every page: PageToolbarFiltersButton first, in the button slot so it holds still carrying the applied count; then PageToolbarApplied, the filters in force with Clear all; then the suggestions.

  • Applied filters always lead, so they never scroll out of view behind suggestions. Pressing a suggestion moves it into the applied group; it is never shown twice.

  • When a filter rail holds the facets, the toolbar still shows what the rail has applied, with no suggestions after it (separator={false}).

  • Each facet appears once. A SegmentedControl when the facet splits the set and one part is viewed at a time (its counts sum to the total); PageToolbarFilter chips when several combine. Never both for the same facet.

  • Keep the actions to PageToolbarSort, which names the current order, and a view toggle. Page actions such as export belong in the PageHeader.

Props

PageToolbar

PropTypeDefaultDescription
aria-label(required)string

Names the toolbar's region, such as "Filters".

gutterbooleantrue

Reach across the page gutter, so the bar's fill and rule meet the column's edges and nothing shows past it as the page scrolls beneath. Set false when the column it sits in has no gutter.

alignLayoutResponsiveValue<FlexAlign>"stretch"

Cross-axis alignment. Accepts a per-breakpoint responsive object.

as"div" | "article" | "aside" | "figcaption" | "figure" | "footer" | "header" | "li" | "main" | "nav" | "ol" | "section" | "span" | "ul"

Render as a different host element from the closed layout vocabulary ({@link LayoutElement}). The set is deliberately closed: as="button" is a type error, because the design-system answer is the Button component. Event handlers and the ref accept any host element. as and render are mutually exclusive; if both are passed, render wins (a dev-only warning fires).

directionLayoutResponsiveValue<FlexDirection>"row"

Main-axis direction. Accepts a per-breakpoint responsive object.

gapLayoutResponsiveValue<"base" | "none" | "2xs" | "xs" | "sm" | "lg" | "xl" | "2xl" | "3xl" | "3xs">

Gap between items, from the spacing scale. Accepts a per-breakpoint responsive object.

guidelinesbooleanfalse

Show dashed outline guidelines during development.

inlinebooleanfalse

Render as inline-flex instead of flex.

justifyLayoutResponsiveValue<FlexJustify>"flex-start"

Main-axis distribution. Accepts a per-breakpoint responsive object.

responsiveModeResponsiveMode"screen"

Whether responsive values resolve against the viewport ("screen") or nearest container ("container").

wrapLayoutResponsiveValue<FlexWrap>"nowrap"

Wrap behaviour. Accepts a per-breakpoint responsive object.

refLayoutRef | undefined

Ref to the rendered host, whichever element as selects.

PageToolbarActions

PropTypeDefaultDescription
alignLayoutResponsiveValue<FlexAlign>"stretch"

Cross-axis alignment. Accepts a per-breakpoint responsive object.

as"div" | "article" | "aside" | "figcaption" | "figure" | "footer" | "header" | "li" | "main" | "nav" | "ol" | "section" | "span" | "ul"

Render as a different host element from the closed layout vocabulary ({@link LayoutElement}). The set is deliberately closed: as="button" is a type error, because the design-system answer is the Button component. Event handlers and the ref accept any host element. as and render are mutually exclusive; if both are passed, render wins (a dev-only warning fires).

directionLayoutResponsiveValue<FlexDirection>"row"

Main-axis direction. Accepts a per-breakpoint responsive object.

gapLayoutResponsiveValue<"base" | "none" | "2xs" | "xs" | "sm" | "lg" | "xl" | "2xl" | "3xl" | "3xs">

Gap between items, from the spacing scale. Accepts a per-breakpoint responsive object.

guidelinesbooleanfalse

Show dashed outline guidelines during development.

inlinebooleanfalse

Render as inline-flex instead of flex.

justifyLayoutResponsiveValue<FlexJustify>"flex-start"

Main-axis distribution. Accepts a per-breakpoint responsive object.

responsiveModeResponsiveMode"screen"

Whether responsive values resolve against the viewport ("screen") or nearest container ("container").

wrapLayoutResponsiveValue<FlexWrap>"nowrap"

Wrap behaviour. Accepts a per-breakpoint responsive object.

refLayoutRef | undefined

Ref to the rendered host, whichever element as selects.

PageToolbarApplied

PropTypeDefaultDescription
childrenReactNode

The applied filters, each a pressed PageToolbarFilter.

onClear(required)() => void

Removes every applied filter.

clearLabelstring"Clear all"
separatorbooleantrue

Draw a short rule after the group, before the suggestions that follow. Set false when nothing follows.

alignLayoutResponsiveValue<FlexAlign>"stretch"

Cross-axis alignment. Accepts a per-breakpoint responsive object.

as"div" | "article" | "aside" | "figcaption" | "figure" | "footer" | "header" | "li" | "main" | "nav" | "ol" | "section" | "span" | "ul"

Render as a different host element from the closed layout vocabulary ({@link LayoutElement}). The set is deliberately closed: as="button" is a type error, because the design-system answer is the Button component. Event handlers and the ref accept any host element. as and render are mutually exclusive; if both are passed, render wins (a dev-only warning fires).

directionLayoutResponsiveValue<FlexDirection>"row"

Main-axis direction. Accepts a per-breakpoint responsive object.

gapLayoutResponsiveValue<"base" | "none" | "2xs" | "xs" | "sm" | "lg" | "xl" | "2xl" | "3xl" | "3xs">

Gap between items, from the spacing scale. Accepts a per-breakpoint responsive object.

guidelinesbooleanfalse

Show dashed outline guidelines during development.

inlinebooleanfalse

Render as inline-flex instead of flex.

justifyLayoutResponsiveValue<FlexJustify>"flex-start"

Main-axis distribution. Accepts a per-breakpoint responsive object.

responsiveModeResponsiveMode"screen"

Whether responsive values resolve against the viewport ("screen") or nearest container ("container").

wrapLayoutResponsiveValue<FlexWrap>"nowrap"

Wrap behaviour. Accepts a per-breakpoint responsive object.

refLayoutRef | undefined

Ref to the rendered host, whichever element as selects.

PageToolbarFilter

PropTypeDefaultDescription
children(required)ReactNode

The filter's name.

countnumber

How many results it would leave, shown muted after the name.

variant"default" | "secondary" | null | undefined
sizeResponsiveValue<ToggleSize>"base"

Toggle size - a single token or a per-breakpoint object like { base: "sm", md: "lg" }. Icon-only sizing follows the base breakpoint.

PageToolbarFilters

PropTypeDefaultDescription
buttonReactNode

The PageToolbarFiltersButton. It holds still while the filters after it scroll, so its applied count stays in view.

alignLayoutResponsiveValue<FlexAlign>"stretch"

Cross-axis alignment. Accepts a per-breakpoint responsive object.

as"div" | "article" | "aside" | "figcaption" | "figure" | "footer" | "header" | "li" | "main" | "nav" | "ol" | "section" | "span" | "ul"

Render as a different host element from the closed layout vocabulary ({@link LayoutElement}). The set is deliberately closed: as="button" is a type error, because the design-system answer is the Button component. Event handlers and the ref accept any host element. as and render are mutually exclusive; if both are passed, render wins (a dev-only warning fires).

directionLayoutResponsiveValue<FlexDirection>"row"

Main-axis direction. Accepts a per-breakpoint responsive object.

gapLayoutResponsiveValue<"base" | "none" | "2xs" | "xs" | "sm" | "lg" | "xl" | "2xl" | "3xl" | "3xs">

Gap between items, from the spacing scale. Accepts a per-breakpoint responsive object.

guidelinesbooleanfalse

Show dashed outline guidelines during development.

inlinebooleanfalse

Render as inline-flex instead of flex.

justifyLayoutResponsiveValue<FlexJustify>"flex-start"

Main-axis distribution. Accepts a per-breakpoint responsive object.

responsiveModeResponsiveMode"screen"

Whether responsive values resolve against the viewport ("screen") or nearest container ("container").

wrapLayoutResponsiveValue<FlexWrap>"nowrap"

Wrap behaviour. Accepts a per-breakpoint responsive object.

refLayoutRef | undefined

Ref to the rendered host, whichever element as selects.

PageToolbarFiltersButton

PropTypeDefaultDescription
countnumber

How many filters are applied, shown muted after the label.

childrenReactNode"Filters"
renderuseRender.RenderProp<Record<string, unknown>> | undefined

Replace the rendered <button> with another element or component (e.g. <Link href="…" />); styling, decorations and props are applied to it.

radius"rounded" | "square" | "full" | null | undefined
sizeButtonSizeProp"base"

Size token; icon-* variants produce a square icon-only button. Also accepts a responsive object keyed by viewport breakpoints and/or @-prefixed container queries - e.g. { base: "sm", md: "base", "@sm": "lg" }.

dotstring | undefined

CSS colour for a status dot; empty/undefined renders no dot.

loadingboolean | undefinedfalse

Show a spinner and block presses. The button stays focusable (it is aria-disabled, not natively disabled) so keyboard focus is kept.

squareboolean | null | undefined
asInputboolean | null | undefined
align"center" | "end" | "start" | null | undefined
pressedboolean | null | undefined
testIdstring
suffixIconIconComponent | undefined

Trailing icon (Lucide or SVG component) rendered at the end.

expandableboolean | undefinedfalse

Icon-only at rest; expands on hover/focus-visible to reveal the label to the right of the icon. Collapsed geometry equals the matching icon-* size, expanded equals the text button of that size - so pass a text size (sm/base/lg) OR its icon twin (icon-sm …); both resolve identically. Requires both icon and children; ignored with square. The label stays in the DOM in both states (stable accessible name).

focusedboolean | undefined

Force the focus ring on - for documentation/testing only.

hoveredboolean | undefined

Force the hover state on - for documentation/testing only.

loadingLabelstring | undefined

Label shown in place of children while loading.

iconClassNamestring | undefined

Extra classes for the leading icon.

suffixIconClassNamestring | undefined

Extra classes for the trailing icon.

dotPlacement"end" | "start" | undefined"start"

Dot position relative to content.

PageToolbarSort

PropTypeDefaultDescription
directionPageToolbarSortDirection | undefined

The order's direction. Set it, with onDirectionChange, when the options are fields that sort either way, such as a table's columns.

labelstring"Sort"

Names the control for assistive technology.

onDirectionChange(direction: PageToolbarSortDirection) => void
onValueChange(required)(value: string) => void
options(required)readonly PageToolbarSortOption[]
value(required)string

The current order's value; one matching no option reads as unsorted.

PageToolbarTableFilters

PropTypeDefaultDescription
childrenReactNode

Suggestions to follow the applied filters, if any.

table(required)Table<TData>

The DataGrid's table, from useDataGridTable.

PageToolbarTableSort

PropTypeDefaultDescription
table(required)Table<TData>

The DataGrid's table, from useDataGridTable.

Also exports

  • typePageToolbarActionsProps
  • interfacePageToolbarAppliedProps
  • interfacePageToolbarFilterProps
  • interfacePageToolbarFiltersButtonProps
  • interfacePageToolbarFiltersProps
  • interfacePageToolbarProps
  • typePageToolbarSortDirection
  • interfacePageToolbarSortOption
  • interfacePageToolbarSortProps
  • interfacePageToolbarTableFiltersProps
  • interfacePageToolbarTableSortProps