# Toolbar

> Package `@umriss-ui/table`, version 0.40.0. Demo page: <https://romanhaendler.github.io/umriss-ui/table/toolbar/>. Every page in one line: [llms.txt](https://romanhaendler.github.io/umriss-ui/table/llms.txt); every page in full: [llms-full.txt](https://romanhaendler.github.io/umriss-ui/table/llms-full.txt).

The bar above the table that holds its search, column menu and export, shows how many rows match, and carries the bulk actions while rows are ticked (also called a table header bar).

```ts
import { Toolbar } from "@umriss-ui/table";
```

Demo page: https://romanhaendler.github.io/umriss-ui/table/toolbar/

It stands above the table wherever it stands in the JSX. On the left go the parts you put into it, then the conditions of the column filters; on the right the count of matches and “Reset” while something restricts, and the selection with its bulk actions while rows are ticked.

A table with a search or a column filter puts up a toolbar of its own when none stands. Outside the table, pass `of` to the toolbar and to each part in it, and place it before the table – after it, it registers only after the first paint.

## Examples

### Search, arrange and export

Put the parts into a `Toolbar` inside the table; tick rows and the bulk actions and the selection count join it on the right.

```tsx
import { useState } from "react";
import { Stack, Text } from "@umriss-ui/core";
import { ColumnMenu, Export, Search, Toolbar, useTable } from "@umriss-ui/table";

interface Incident {
  id: string;
  title: string;
  service: string;
  severity: "SEV1" | "SEV2" | "SEV3";
}

const INCIDENTS: Incident[] = [
  { id: "INC-1048", title: "Checkout slow, card payments time out", service: "Checkout", severity: "SEV1" },
  { id: "INC-1047", title: "Webhook deliveries delayed", service: "Webhooks", severity: "SEV3" },
  { id: "INC-1046", title: "Thumbnails missing for new uploads", service: "Image service", severity: "SEV2" },
  { id: "INC-1045", title: "Sign-in codes arrive late", service: "Sign-in", severity: "SEV2" },
];

export default function SearchArrangeAndExport() {
  const [last, setLast] = useState("Nothing closed yet.");
  const { Table, Column, RowActions, Action } = useTable(INCIDENTS, { rowKey: (i) => i.id });

  return (
    <Stack gap={3}>
      <Table selectable ariaLabel="Incidents">
        <Toolbar>
          <Search placeholder="Search incidents" />
          <ColumnMenu />
          <Export filename="incidents.csv" />
        </Toolbar>
        <Column value="id" label="Incident" rowHeader />
        <Column value="title" label="Title" />
        <Column value="service" label="Service" />
        <Column value="severity" label="Severity" />
        <RowActions>
          <Action bulk onSelect={(list) => setLast(`Closed: ${list.map((i) => i.id).join(", ")}`)}>
            Close
          </Action>
        </RowActions>
      </Table>
      <Text size="sm" tone="secondary" role="status">
        {last}
      </Text>
    </Stack>
  );
}
```

### Place it outside the table

Keep what [`useTable`](https://romanhaendler.github.io/umriss-ui/table/api/#useTable) returns and pass it as `of` to the toolbar and to each part in it; put the toolbar before the table.

```tsx
import { Stack } from "@umriss-ui/core";
import { Export, Search, Toolbar, useTable } from "@umriss-ui/table";

interface Incident {
  id: string;
  title: string;
}

const INCIDENTS: Incident[] = [
  { id: "INC-1048", title: "Checkout slow, card payments time out" },
  { id: "INC-1047", title: "Webhook deliveries delayed" },
  { id: "INC-1046", title: "Thumbnails missing for new uploads" },
];

export default function PlaceItOutside() {
  const t = useTable(INCIDENTS, { rowKey: (i) => i.id });
  const { Table, Column } = t;

  return (
    <Stack gap={3}>
      <Toolbar of={t}>
        <Search of={t} placeholder="Search incidents" />
        <Export of={t} filename="incidents.csv" />
      </Toolbar>
      <Table ariaLabel="Incidents">
        <Column value="id" label="Incident" rowHeader />
        <Column value="title" label="Title" />
      </Table>
    </Stack>
  );
}
```

### Parts outside a toolbar

Each part takes the table as `of` and stands where you put it: here in a card header at `size="md"`, the card's height, with the pager above the rows.

```tsx
import { Card, CardBody, CardHeader, Stack } from "@umriss-ui/core";
import { ColumnMenu, Export, Pagination, Search, useTable } from "@umriss-ui/table";

/* Outside a toolbar a part is `sm` unless it says otherwise. The pager stands
   before the table: placed after it, it registers only after the first frame. */

interface Incident {
  id: string;
  title: string;
  service: string;
}

const INCIDENTS: Incident[] = [
  { id: "INC-1048", title: "Checkout slow, card payments time out", service: "Checkout" },
  { id: "INC-1047", title: "Webhook deliveries delayed", service: "Webhooks" },
  { id: "INC-1046", title: "Thumbnails missing for new uploads", service: "Images" },
  { id: "INC-1045", title: "Search returns stale prices", service: "Search" },
  { id: "INC-1044", title: "Password reset mails late", service: "Identity" },
  { id: "INC-1043", title: "Nightly report missing a day", service: "Reporting" },
];

export default function PartsOutsideAToolbar() {
  const t = useTable(INCIDENTS, { rowKey: (i) => i.id, pageSize: 4 });
  const { Table, Column } = t;

  return (
    <Card>
      <CardHeader
        divider
        title="Incidents"
        actions={
          <Stack direction="row" gap={2} align="center" wrap>
            <Search of={t} size="md" placeholder="Search incidents" />
            <ColumnMenu of={t} size="md" />
            <Export of={t} size="md" filename="incidents.csv" />
          </Stack>
        }
      />
      <CardBody>
        <Stack gap={2}>
          <Pagination of={t} pageSizes={[4, 10]} />
          <Table ariaLabel="Incidents">
            <Column value="id" label="Incident" rowHeader />
            <Column value="title" label="Title" />
            <Column value="service" label="Service" />
          </Table>
        </Stack>
      </CardBody>
    </Card>
  );
}
```

## Keyboard

The keys of [First table](https://romanhaendler.github.io/umriss-ui/table/first-table/#keyboard-first-table), [Input](https://romanhaendler.github.io/umriss-ui/core/input/#keyboard-input), [ColumnMenu](https://romanhaendler.github.io/umriss-ui/table/columnmenu/#keyboard-columnmenu), [RowActions](https://romanhaendler.github.io/umriss-ui/table/rowactions/#keyboard-rowactions), [Button](https://romanhaendler.github.io/umriss-ui/core/button/#keyboard-button) and [Checkbox](https://romanhaendler.github.io/umriss-ui/core/checkbox/#keyboard-checkbox) apply here.

## Accessibility

The count of matches is a status region. It stays empty while nothing restricts the rows, and a screen reader hears “3 of 12” when a search or a filter narrows them, and the new count on every change after.

The parts the table puts in name themselves: the search field “Search table” unless its `aria-label` says otherwise, “Columns”, “Export”. A control of your own in the bar needs a label of its own, as anywhere.

## API

### `ToolbarProps`

| Prop | Type | Default | Description |
|---|---|---|---|
| `children` | `ReactNode` | — | Search, column menu, export – on the left in the table toolbar, before the conditions.<br>Shown in: [Search, arrange and export](https://romanhaendler.github.io/umriss-ui/table/toolbar/#search-arrange-and-export), [Place it outside the table](https://romanhaendler.github.io/umriss-ui/table/toolbar/#place-it-outside), [Set wording and formats once (Provider)](https://romanhaendler.github.io/umriss-ui/table/provider/#provider) and 37 more |
| `size` | [`ToolbarSize`](https://romanhaendler.github.io/umriss-ui/table/toolbar/#type-ToolbarSize)<br>`"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.<br>Shown in: [A larger toolbar (Toolbar controls)](https://romanhaendler.github.io/umriss-ui/table/toolbar-controls/#a-larger-toolbar), [A dispatcher's bar (Toolbar controls)](https://romanhaendler.github.io/umriss-ui/table/toolbar-controls/#a-dispatcher-s-bar) |
| `of` | [`TableRef`](https://romanhaendler.github.io/umriss-ui/table/toolbar/#type-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.<br>Shown in: [Place it outside the table](https://romanhaendler.github.io/umriss-ui/table/toolbar/#place-it-outside), [Review cost centres against budget (Scenarios)](https://romanhaendler.github.io/umriss-ui/table/#review-cost-centres) |

#### Styling

| Prop | Type | Default | Description |
|---|---|---|---|
| `className` | `string` | — | Classes on the table toolbar. |

### Types on this page

#### `ToolbarSize`

The size of a toolbar's controls.

```ts
type ToolbarSize = "sm" | "md";
```

#### `TableRef`

What a part without a row type needs from a table – for `of`.

```ts
type TableRef = Omit<TableSnapshot<unknown>, "setFilter" | "conditionOf"> & {
  readonly Table: unknown;
  /** Without a row kind: any id, any condition. */
  setFilter(column: string, condition: unknown): void;
};
```
