Put controls of your own into the toolbar - a multiselect, a select, a combobox - and let them stand level with the table's: one size for the whole bar, and a row filter behind each control.
import { Toolbar, rowFilter } from "@umriss-ui/table";
Toolbar takes size, sm or md, and the parts the table puts into it follow: search, column menu, export, “Reset” and the bulk actions. A part says its own size with its own size. A control from @umriss-ui/core that you put in takes the toolbar's size as well, without a word - the toolbar is a ControlSizeProvider, as @umriss-ui/core's Sizes page shows - and keeps its own size if it says one.
No widths to set: a field from @umriss-ui/core is its natural width in the bar - a count of characters of its type, or its chars - and never what it shows, so choosing in a multiselect moves nothing beside it.
A control of your own restricts the table through a row filter: it sets the condition with t.setFilter(filter, condition) and reads it with t.conditionOf(filter), so “Reset”, the count of matches and the view include it.
The toolbar is sm unless it says otherwise, and a control from @umriss-ui/core put into it takes that size without a word - level with the search, at its natural width, whatever it shows. Behind each control a row filter.
import { MultiSelect, Select } from "@umriss-ui/core";
import { Pagination, Search, Toolbar, rowFilter, useTable } from "@umriss-ui/table";
/* Data from the logistics world, written out here so the example runs on its own. */
/** A small LCG - the same numbers on every computer. */
function random(seed: number): () => number {
let s = seed >>> 0;
return () => {
s = (Math.imul(s, 1664525) + 1013904223) >>> 0;
return s / 4294967296;
};
}
const at = (hours: number, minutes = 0) => new Date(2026, 2, 17, hours, minutes).getTime();
const MINUTE = 60_000;
/** Tuesday, 17 March 2026, 10:30 - the moment the screens are read at. */
const NOW = at(10, 30);
interface Vehicle {
id: string;
plate: string;
type: "van" | "e-van" | "truck";
/** Payload, in kg. */
capacity: number;
depot: string;
}
const VEHICLES: readonly Vehicle[] = [
{ id: "v1", plate: "FP 214 K", type: "van", capacity: 1200, depot: "north" },
{ id: "v2", plate: "FP 377 K", type: "e-van", capacity: 900, depot: "north" },
{ id: "v3", plate: "FP 118 R", type: "truck", capacity: 7500, depot: "north" },
{ id: "v4", plate: "FP 402 R", type: "van", capacity: 1200, depot: "river" },
{ id: "v5", plate: "FP 455 R", type: "e-van", capacity: 900, depot: "river" },
{ id: "v6", plate: "FP 290 E", type: "van", capacity: 1200, depot: "east" },
{ id: "v7", plate: "FP 311 E", type: "e-van", capacity: 900, depot: "east" },
{ id: "v8", plate: "FP 520 E", type: "truck", capacity: 7500, depot: "east" },
];
const DRIVERS = [
{ id: "d1", name: "Martin Hale", depot: "north" },
{ id: "d2", name: "Nadia Petrova", depot: "north" },
{ id: "d3", name: "Owen Carter", depot: "north" },
{ id: "d4", name: "Lucia Romero", depot: "river" },
{ id: "d5", name: "Ben Adeyemi", depot: "river" },
{ id: "d6", name: "Hanna Berg", depot: "east" },
{ id: "d7", name: "Yusuf Demir", depot: "east" },
{ id: "d8", name: "Clara Wendt", depot: "east" },
] as const;
const CUSTOMERS = [
"Holloway Garden Supplies",
"Marlow & Finch Books",
"Oakridge Pharmacy",
"Brixley Cycles",
"Tamsin's Bakery",
"Northfold Office",
"Pellham Hardware",
"Greywick Studio",
"Juniper Lane Florist",
"Ashcombe Dental",
] as const;
interface Stop {
id: string;
shipment: string;
customer: string;
/** The window the customer was promised, `[from, to]`. */
window: readonly [number, number];
/** When the tour plans to be there. */
arrival: number;
}
interface Tour {
id: string;
vehicle: string;
driver: string;
depot: string;
/** Leaves the depot, loaded; back at the depot. */
from: number;
to: number;
/** Minutes of loading before `from`. */
loading: number;
km: number;
stops: readonly Stop[];
}
/** One tour per vehicle. Stops every half hour or so, each with a two-hour
window; every seventh arrival misses its window - the late ones a
dispatcher looks for. */
function tour(index: number): Tour {
const r = random(700 + index);
const vehicle = VEHICLES[index]!;
const truck = vehicle.type === "truck";
const from = at(truck ? 6 : 7, index % 2 === 0 ? 0 : 30);
const count = truck ? 5 : 8 + Math.floor(r() * 4);
const stops: Stop[] = [];
let arrival = from + (20 + Math.floor(r() * 15)) * MINUTE;
for (let i = 0; i < count; i++) {
const n = index * 20 + i;
const slot = Math.floor((arrival - at(0)) / (2 * 60 * MINUTE)) * 2;
/* A late stop's window closed half an hour or more before the arrival. */
const late = i >= 2 && n % 7 === 3;
const halfHour = 30 * MINUTE;
const windowFrom = late ? Math.floor(arrival / halfHour) * halfHour - 5 * halfHour : at(slot);
stops.push({
id: `s-${index + 1}-${i + 1}`,
shipment: `FP-${(1_004_210 + n * 13).toString()}`,
customer: CUSTOMERS[(n * 3) % CUSTOMERS.length]!,
window: [windowFrom, windowFrom + 2 * 60 * MINUTE],
arrival,
});
arrival += (truck ? 45 : 22) * MINUTE + Math.floor(r() * 18) * MINUTE;
}
return {
id: `T-${String(index + 1).padStart(2, "0")}`,
vehicle: vehicle.id,
driver: DRIVERS[index]!.id,
depot: vehicle.depot,
from,
to: arrival + 30 * MINUTE,
loading: truck ? 45 : 30,
km: Math.round((truck ? 140 : 70) + r() * 40),
stops,
};
}
const TOURS: readonly Tour[] = VEHICLES.map((_, index) => tour(index));
interface Shipment {
id: string;
customer: string;
/** In kg. */
weight: number;
status: "delivered" | "out for delivery" | "failed attempt";
window: readonly [number, number];
tour: string;
}
/** One shipment per stop. Before now, delivered - or a failed attempt, where
nobody was in; after now, out for delivery. */
const SHIPMENTS: readonly Shipment[] = TOURS.flatMap((one) =>
one.stops.map((stop) => {
const n = Number(stop.shipment.slice(3));
return {
id: stop.shipment,
customer: stop.customer,
weight: Math.round((VEHICLES.find((v) => v.id === one.vehicle)!.type === "truck" ? 180 : 2) + ((n * 7919) % 230) / 10),
status: stop.arrival > NOW ? "out for delivery" : n % 11 === 0 ? "failed attempt" : "delivered",
window: stop.window,
tour: one.id,
} satisfies Shipment;
}),
);
type Status = Shipment["status"];
const tours = rowFilter({
id: "tours",
label: "Tours",
matches: (shipment: Shipment, chosen: readonly string[]) => chosen.includes(shipment.tour),
});
const status = rowFilter({
id: "status",
label: "Status",
matches: (shipment: Shipment, wanted: Status) => shipment.status === wanted,
});
const TOUR_OPTIONS = [...new Set(SHIPMENTS.map((s) => s.tour))].map((tour) => ({ value: tour, label: tour }));
export default function ControlsAtTheToolbarsSize() {
const t = useTable(SHIPMENTS, { rowKey: (s) => s.id, rowFilters: [tours, status] });
const { Table, Column } = t;
return (
<Table ariaLabel="Shipments">
<Toolbar>
<Search placeholder="Shipment or customer" />
<MultiSelect
aria-label="Tours"
placeholder="All tours"
options={TOUR_OPTIONS}
value={t.conditionOf(tours) ?? []}
onChange={(next) => t.setFilter(tours, next.length > 0 ? next : null)}
/>
<Select
aria-label="Status"
value={t.conditionOf(status) ?? ""}
onChange={(event) => t.setFilter(status, event.target.value === "" ? null : (event.target.value as Status))}
>
<option value="">Every status</option>
<option value="out for delivery">Out for delivery</option>
<option value="failed attempt">Failed attempt</option>
<option value="delivered">Delivered</option>
</Select>
</Toolbar>
<Column value="id" label="Shipment" rowHeader />
<Column value="customer" label="Customer" />
<Column value="tour" label="Tour" />
<Column value="status" label="Status" />
<Pagination />
</Table>
);
}
size="md" on the toolbar, and search, column menu, export, “Reset” and the multiselect of one's own follow. One size for the whole bar, said once.
import { MultiSelect } from "@umriss-ui/core";
import { ColumnMenu, Export, Pagination, Search, Toolbar, rowFilter, useTable } from "@umriss-ui/table";
/* Data from the logistics world, written out here so the example runs on its own. */
/** A small LCG - the same numbers on every computer. */
function random(seed: number): () => number {
let s = seed >>> 0;
return () => {
s = (Math.imul(s, 1664525) + 1013904223) >>> 0;
return s / 4294967296;
};
}
const at = (hours: number, minutes = 0) => new Date(2026, 2, 17, hours, minutes).getTime();
const MINUTE = 60_000;
/** Tuesday, 17 March 2026, 10:30 - the moment the screens are read at. */
const NOW = at(10, 30);
interface Vehicle {
id: string;
plate: string;
type: "van" | "e-van" | "truck";
/** Payload, in kg. */
capacity: number;
depot: string;
}
const VEHICLES: readonly Vehicle[] = [
{ id: "v1", plate: "FP 214 K", type: "van", capacity: 1200, depot: "north" },
{ id: "v2", plate: "FP 377 K", type: "e-van", capacity: 900, depot: "north" },
{ id: "v3", plate: "FP 118 R", type: "truck", capacity: 7500, depot: "north" },
{ id: "v4", plate: "FP 402 R", type: "van", capacity: 1200, depot: "river" },
{ id: "v5", plate: "FP 455 R", type: "e-van", capacity: 900, depot: "river" },
{ id: "v6", plate: "FP 290 E", type: "van", capacity: 1200, depot: "east" },
{ id: "v7", plate: "FP 311 E", type: "e-van", capacity: 900, depot: "east" },
{ id: "v8", plate: "FP 520 E", type: "truck", capacity: 7500, depot: "east" },
];
const DRIVERS = [
{ id: "d1", name: "Martin Hale", depot: "north" },
{ id: "d2", name: "Nadia Petrova", depot: "north" },
{ id: "d3", name: "Owen Carter", depot: "north" },
{ id: "d4", name: "Lucia Romero", depot: "river" },
{ id: "d5", name: "Ben Adeyemi", depot: "river" },
{ id: "d6", name: "Hanna Berg", depot: "east" },
{ id: "d7", name: "Yusuf Demir", depot: "east" },
{ id: "d8", name: "Clara Wendt", depot: "east" },
] as const;
const CUSTOMERS = [
"Holloway Garden Supplies",
"Marlow & Finch Books",
"Oakridge Pharmacy",
"Brixley Cycles",
"Tamsin's Bakery",
"Northfold Office",
"Pellham Hardware",
"Greywick Studio",
"Juniper Lane Florist",
"Ashcombe Dental",
] as const;
interface Stop {
id: string;
shipment: string;
customer: string;
/** The window the customer was promised, `[from, to]`. */
window: readonly [number, number];
/** When the tour plans to be there. */
arrival: number;
}
interface Tour {
id: string;
vehicle: string;
driver: string;
depot: string;
/** Leaves the depot, loaded; back at the depot. */
from: number;
to: number;
/** Minutes of loading before `from`. */
loading: number;
km: number;
stops: readonly Stop[];
}
/** One tour per vehicle. Stops every half hour or so, each with a two-hour
window; every seventh arrival misses its window - the late ones a
dispatcher looks for. */
function tour(index: number): Tour {
const r = random(700 + index);
const vehicle = VEHICLES[index]!;
const truck = vehicle.type === "truck";
const from = at(truck ? 6 : 7, index % 2 === 0 ? 0 : 30);
const count = truck ? 5 : 8 + Math.floor(r() * 4);
const stops: Stop[] = [];
let arrival = from + (20 + Math.floor(r() * 15)) * MINUTE;
for (let i = 0; i < count; i++) {
const n = index * 20 + i;
const slot = Math.floor((arrival - at(0)) / (2 * 60 * MINUTE)) * 2;
/* A late stop's window closed half an hour or more before the arrival. */
const late = i >= 2 && n % 7 === 3;
const halfHour = 30 * MINUTE;
const windowFrom = late ? Math.floor(arrival / halfHour) * halfHour - 5 * halfHour : at(slot);
stops.push({
id: `s-${index + 1}-${i + 1}`,
shipment: `FP-${(1_004_210 + n * 13).toString()}`,
customer: CUSTOMERS[(n * 3) % CUSTOMERS.length]!,
window: [windowFrom, windowFrom + 2 * 60 * MINUTE],
arrival,
});
arrival += (truck ? 45 : 22) * MINUTE + Math.floor(r() * 18) * MINUTE;
}
return {
id: `T-${String(index + 1).padStart(2, "0")}`,
vehicle: vehicle.id,
driver: DRIVERS[index]!.id,
depot: vehicle.depot,
from,
to: arrival + 30 * MINUTE,
loading: truck ? 45 : 30,
km: Math.round((truck ? 140 : 70) + r() * 40),
stops,
};
}
const TOURS: readonly Tour[] = VEHICLES.map((_, index) => tour(index));
interface Shipment {
id: string;
customer: string;
/** In kg. */
weight: number;
status: "delivered" | "out for delivery" | "failed attempt";
window: readonly [number, number];
tour: string;
}
/** One shipment per stop. Before now, delivered - or a failed attempt, where
nobody was in; after now, out for delivery. */
const SHIPMENTS: readonly Shipment[] = TOURS.flatMap((one) =>
one.stops.map((stop) => {
const n = Number(stop.shipment.slice(3));
return {
id: stop.shipment,
customer: stop.customer,
weight: Math.round((VEHICLES.find((v) => v.id === one.vehicle)!.type === "truck" ? 180 : 2) + ((n * 7919) % 230) / 10),
status: stop.arrival > NOW ? "out for delivery" : n % 11 === 0 ? "failed attempt" : "delivered",
window: stop.window,
tour: one.id,
} satisfies Shipment;
}),
);
const tours = rowFilter({
id: "tours",
label: "Tours",
matches: (shipment: Shipment, chosen: readonly string[]) => chosen.includes(shipment.tour),
});
const TOUR_OPTIONS = [...new Set(SHIPMENTS.map((s) => s.tour))].map((tour) => ({ value: tour, label: tour }));
export default function ALargerToolbar() {
const t = useTable(SHIPMENTS, { rowKey: (s) => s.id, rowFilters: [tours] });
const { Table, Column } = t;
return (
<Table ariaLabel="Shipments">
<Toolbar size="md">
<Search placeholder="Shipment or customer" />
<MultiSelect
aria-label="Tours"
placeholder="All tours"
options={TOUR_OPTIONS}
value={t.conditionOf(tours) ?? []}
onChange={(next) => t.setFilter(tours, next.length > 0 ? next : null)}
/>
<ColumnMenu />
<Export />
</Toolbar>
<Column value="id" label="Shipment" rowHeader />
<Column value="customer" label="Customer" />
<Column value="tour" label="Tour" />
<Column value="weight" label="Weight (kg)" />
<Pagination />
</Table>
);
}
Three controls of one's own and the table's parts in one md bar, a quick filter beside the table - and every condition counted, reset and kept in the view alike. Only the one set from outside describes itself as a chip: the others show in their control.
import { Button, Combobox, MultiSelect, Select, Stack } from "@umriss-ui/core";
import { ColumnMenu, Export, Pagination, Search, Toolbar, rowFilter, useTable } from "@umriss-ui/table";
/* Data from the logistics world, written out here so the example runs on its own. */
/** A small LCG - the same numbers on every computer. */
function random(seed: number): () => number {
let s = seed >>> 0;
return () => {
s = (Math.imul(s, 1664525) + 1013904223) >>> 0;
return s / 4294967296;
};
}
const at = (hours: number, minutes = 0) => new Date(2026, 2, 17, hours, minutes).getTime();
const MINUTE = 60_000;
/** Tuesday, 17 March 2026, 10:30 - the moment the screens are read at. */
const NOW = at(10, 30);
interface Vehicle {
id: string;
plate: string;
type: "van" | "e-van" | "truck";
/** Payload, in kg. */
capacity: number;
depot: string;
}
const VEHICLES: readonly Vehicle[] = [
{ id: "v1", plate: "FP 214 K", type: "van", capacity: 1200, depot: "north" },
{ id: "v2", plate: "FP 377 K", type: "e-van", capacity: 900, depot: "north" },
{ id: "v3", plate: "FP 118 R", type: "truck", capacity: 7500, depot: "north" },
{ id: "v4", plate: "FP 402 R", type: "van", capacity: 1200, depot: "river" },
{ id: "v5", plate: "FP 455 R", type: "e-van", capacity: 900, depot: "river" },
{ id: "v6", plate: "FP 290 E", type: "van", capacity: 1200, depot: "east" },
{ id: "v7", plate: "FP 311 E", type: "e-van", capacity: 900, depot: "east" },
{ id: "v8", plate: "FP 520 E", type: "truck", capacity: 7500, depot: "east" },
];
const DRIVERS = [
{ id: "d1", name: "Martin Hale", depot: "north" },
{ id: "d2", name: "Nadia Petrova", depot: "north" },
{ id: "d3", name: "Owen Carter", depot: "north" },
{ id: "d4", name: "Lucia Romero", depot: "river" },
{ id: "d5", name: "Ben Adeyemi", depot: "river" },
{ id: "d6", name: "Hanna Berg", depot: "east" },
{ id: "d7", name: "Yusuf Demir", depot: "east" },
{ id: "d8", name: "Clara Wendt", depot: "east" },
] as const;
const CUSTOMERS = [
"Holloway Garden Supplies",
"Marlow & Finch Books",
"Oakridge Pharmacy",
"Brixley Cycles",
"Tamsin's Bakery",
"Northfold Office",
"Pellham Hardware",
"Greywick Studio",
"Juniper Lane Florist",
"Ashcombe Dental",
] as const;
interface Stop {
id: string;
shipment: string;
customer: string;
/** The window the customer was promised, `[from, to]`. */
window: readonly [number, number];
/** When the tour plans to be there. */
arrival: number;
}
interface Tour {
id: string;
vehicle: string;
driver: string;
depot: string;
/** Leaves the depot, loaded; back at the depot. */
from: number;
to: number;
/** Minutes of loading before `from`. */
loading: number;
km: number;
stops: readonly Stop[];
}
/** One tour per vehicle. Stops every half hour or so, each with a two-hour
window; every seventh arrival misses its window - the late ones a
dispatcher looks for. */
function tour(index: number): Tour {
const r = random(700 + index);
const vehicle = VEHICLES[index]!;
const truck = vehicle.type === "truck";
const from = at(truck ? 6 : 7, index % 2 === 0 ? 0 : 30);
const count = truck ? 5 : 8 + Math.floor(r() * 4);
const stops: Stop[] = [];
let arrival = from + (20 + Math.floor(r() * 15)) * MINUTE;
for (let i = 0; i < count; i++) {
const n = index * 20 + i;
const slot = Math.floor((arrival - at(0)) / (2 * 60 * MINUTE)) * 2;
/* A late stop's window closed half an hour or more before the arrival. */
const late = i >= 2 && n % 7 === 3;
const halfHour = 30 * MINUTE;
const windowFrom = late ? Math.floor(arrival / halfHour) * halfHour - 5 * halfHour : at(slot);
stops.push({
id: `s-${index + 1}-${i + 1}`,
shipment: `FP-${(1_004_210 + n * 13).toString()}`,
customer: CUSTOMERS[(n * 3) % CUSTOMERS.length]!,
window: [windowFrom, windowFrom + 2 * 60 * MINUTE],
arrival,
});
arrival += (truck ? 45 : 22) * MINUTE + Math.floor(r() * 18) * MINUTE;
}
return {
id: `T-${String(index + 1).padStart(2, "0")}`,
vehicle: vehicle.id,
driver: DRIVERS[index]!.id,
depot: vehicle.depot,
from,
to: arrival + 30 * MINUTE,
loading: truck ? 45 : 30,
km: Math.round((truck ? 140 : 70) + r() * 40),
stops,
};
}
const TOURS: readonly Tour[] = VEHICLES.map((_, index) => tour(index));
interface Shipment {
id: string;
customer: string;
/** In kg. */
weight: number;
status: "delivered" | "out for delivery" | "failed attempt";
window: readonly [number, number];
tour: string;
}
/** One shipment per stop. Before now, delivered - or a failed attempt, where
nobody was in; after now, out for delivery. */
const SHIPMENTS: readonly Shipment[] = TOURS.flatMap((one) =>
one.stops.map((stop) => {
const n = Number(stop.shipment.slice(3));
return {
id: stop.shipment,
customer: stop.customer,
weight: Math.round((VEHICLES.find((v) => v.id === one.vehicle)!.type === "truck" ? 180 : 2) + ((n * 7919) % 230) / 10),
status: stop.arrival > NOW ? "out for delivery" : n % 11 === 0 ? "failed attempt" : "delivered",
window: stop.window,
tour: one.id,
} satisfies Shipment;
}),
);
type Status = Shipment["status"];
const tours = rowFilter({
id: "tours",
label: "Tours",
matches: (shipment: Shipment, chosen: readonly string[]) => chosen.includes(shipment.tour),
});
const status = rowFilter({
id: "status",
label: "Status",
matches: (shipment: Shipment, wanted: Status) => shipment.status === wanted,
});
const customer = rowFilter({
id: "customer",
label: "Customer",
matches: (shipment: Shipment, name: string) => shipment.customer === name,
});
/* Set from a button beside the table, not from a control in the bar - so it
says itself in the toolbar, where its cross lifts it. */
const heavy = rowFilter({
id: "heavy",
label: "Weight",
matches: (shipment: Shipment, atLeast: number) => shipment.weight >= atLeast,
describe: (atLeast) => `from ${atLeast} kg`,
});
const TOUR_OPTIONS = [...new Set(SHIPMENTS.map((s) => s.tour))].map((tour) => ({ value: tour, label: tour }));
const CUSTOMER_OPTIONS = [...new Set(SHIPMENTS.map((s) => s.customer))]
.sort()
.map((name) => ({ value: name, label: name }));
export default function ADispatchersBar() {
const t = useTable(SHIPMENTS, {
rowKey: (s) => s.id,
rowFilters: [tours, status, customer, heavy],
initialView: { conditions: { heavy: 20 } },
});
const { Table, Column } = t;
return (
<Stack gap={3}>
<Stack direction="row" gap={2}>
<Button size="sm" onClick={() => t.setFilter(heavy, 20)}>
Heavy parcels
</Button>
</Stack>
<Table ariaLabel="Shipments of the day">
<Toolbar size="md">
<Search placeholder="Shipment" />
<MultiSelect
aria-label="Tours"
placeholder="All tours"
options={TOUR_OPTIONS}
value={t.conditionOf(tours) ?? []}
onChange={(next) => t.setFilter(tours, next.length > 0 ? next : null)}
/>
<Select
aria-label="Status"
value={t.conditionOf(status) ?? ""}
onChange={(event) => t.setFilter(status, event.target.value === "" ? null : (event.target.value as Status))}
>
<option value="">Every status</option>
<option value="out for delivery">Out for delivery</option>
<option value="failed attempt">Failed attempt</option>
<option value="delivered">Delivered</option>
</Select>
<Combobox
aria-label="Customer"
placeholder="Any customer"
options={CUSTOMER_OPTIONS}
value={t.conditionOf(customer)}
onChange={(name) => t.setFilter(customer, name)}
/>
<ColumnMenu />
<Export />
</Toolbar>
<Column value="id" label="Shipment" rowHeader />
<Column value="customer" label="Customer" />
<Column value="tour" label="Tour" />
<Column value="status" label="Status" />
<Column value="weight" label="Weight (kg)" />
<Pagination />
</Table>
</Stack>
);
}
The keys of First table, Input, ColumnMenu, Select, MultiSelect, Combobox and Button apply here.
ToolbarProps| Name | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | Search, column menu, export – on the left in the table toolbar, before the conditions. Shown in: Controls of your own at the toolbar's size, A larger toolbar, A dispatcher's bar and 37 more |
size | ToolbarSize"sm" | "md" | "sm" | The size of every control the table puts into it - search, column menu,
export, "reset", the bulk actions -: sm or md. A
control of one's own takes the same size by its own prop.Shown in: A larger toolbar, A dispatcher's bar |
of | TableRef | — | The table, when the table toolbar does not stand inside it. If it then
stands behind the table in the tree, it registers only after the first
frame – until then a table with a search or a column filter shows its own
toolbar. Placed before the table, there is no such change. Shown in: Place it outside the table (Toolbar), Review cost centres against budget (Scenarios) |
| Name | Type | Default | Description |
|---|---|---|---|
className | string | — | Classes on the table toolbar. |
RowFilter<Z, B>| Name | Type | Default | Description |
|---|---|---|---|
idrequired | string | — | Its name in t.view.conditions and in what server mode reports - the one
place the filter is spelled. Not the id of a column of the same table.Shown in: Controls of your own at the toolbar's size, A larger toolbar, A dispatcher's bar and 3 more |
labelrequired | string | — | What it is called: before the text of its chip, and in the chip's
accessible names. Shown in: Controls of your own at the toolbar's size, A larger toolbar, A dispatcher's bar and 3 more |
matchesrequired | (row: Z, condition: B) => boolean | — | Whether the row satisfies the condition. Any question over the whole row;
whatever varies belongs in the condition - the table cannot see a change
in a closure. Shown in: Controls of your own at the toolbar's size, A larger toolbar, A dispatcher's bar and 3 more |
describe | (condition: B) => string | — | The text of the condition in the table toolbar, behind the label. Without
it the condition has no chip: the application's control shows it. Shown in: A dispatcher's bar, Ask a question over several fields (Filter) |
ToolbarSizeThe size of a toolbar's controls.
type ToolbarSize = "sm" | "md";TableRefWhat a part without a row type needs from a table – for of.
type TableRef = Omit<TableSnapshot<unknown>, "setFilter" | "conditionOf"> & {
readonly Table: unknown;
/** Without a row kind: any id, any condition. */
setFilter(column: string, condition: unknown): void;
};