

<Preview name="ToolbarDefaultExample" />

## Overview [#overview]

`Toolbar` provides consistent shell spacing for dense UI surfaces without
owning the controls inside it. Compose it with `Button`, `Input`,
`SearchExpand`, `ToggleGroup`, `Menu`, `Breadcrumb`, and other components.

`size` scales toolbar-owned gaps, separators, title text, count text, and the
title trigger. Pass the same size to the controls you compose inside the
toolbar so the full row follows one density.

Use `Toolbar.TitleTrigger` next to `Toolbar.Title` for a title-adjacent
selection label, such as `Attach Files`. It moves from muted text to foreground
text on hover and while its menu is open.

Use `Toolbar.Breadcrumb` when the heading becomes a path. It styles the
primitive breadcrumb slots for toolbar heading scale while leaving links,
overflow menus, route state, and folder data with the consumer. Use text
separators such as `/` for path-like toolbar headings. Collapse states are
explicit composition: render `BreadcrumbIcon`, `BreadcrumbLabel`,
`BreadcrumbOverflowMenu`, and tooltips from consumer-owned path data.

## Usage [#usage]

```tsx
import { Toolbar } from "@tilt-legal/cubitt-components/toolbar";

<Toolbar size="md">
  <Toolbar.Heading>
    <Toolbar.Title>Files</Toolbar.Title>
    <Toolbar.Count>18</Toolbar.Count>
  </Toolbar.Heading>
  <Toolbar.Actions>{actions}</Toolbar.Actions>
</Toolbar>;
```

## Examples [#examples]

### Sizes [#sizes]

<Tabs className="bg-transparent border-none rounded-none" items="[&#x22;Preview&#x22;, &#x22;Code&#x22;]">
  <Tab value="Preview" className="p-0">
    <Preview name="ToolbarSizesExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import { Button } from "@tilt-legal/cubitt-components/button";
    import {
      ToggleGroup,
      ToggleGroupItem,
    } from "@tilt-legal/cubitt-components/toggle-group";
    import { Toolbar } from "@tilt-legal/cubitt-components/toolbar";
    import { Grid, Menu, SortArrows } from "@tilt-legal/cubitt-icons/ui/outline";

    {(["sm", "md", "lg"] as const).map((size) => (
      <Toolbar key={size} size={size}>
        <Toolbar.Heading>
          <Toolbar.Title>{size.toUpperCase()} toolbar</Toolbar.Title>
          <Toolbar.Count>12</Toolbar.Count>
        </Toolbar.Heading>
        <Toolbar.Actions>
          <Button aria-label="Sort files" mode="icon" size={size} variant="secondary">
            <SortArrows />
          </Button>
          <ToggleGroup
            aria-label="View options"
            groupVariant="segmented"
            multiple={false}
            size={size}
            value={view}
            onValueChange={setView}
          >
            <ToggleGroupItem aria-label="Grid view" mode="icon" value="grid">
              <Grid />
            </ToggleGroupItem>
            <ToggleGroupItem aria-label="List view" mode="icon" value="list">
              <Menu />
            </ToggleGroupItem>
          </ToggleGroup>
          <Toolbar.Separator />
          <Button size={size}>Action</Button>
        </Toolbar.Actions>
      </Toolbar>
    ))}
    ```
  </Tab>
</Tabs>

### With Search [#with-search]

<Tabs className="bg-transparent border-none rounded-none" items="[&#x22;Preview&#x22;, &#x22;Code&#x22;]">
  <Tab value="Preview" className="p-0">
    <Preview name="ToolbarWithSearchExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import { Button } from "@tilt-legal/cubitt-components/button";
    import { Input } from "@tilt-legal/cubitt-components/input";
    import { SearchExpand } from "@tilt-legal/cubitt-components/search-expand";
    import {
      ToggleGroup,
      ToggleGroupItem,
    } from "@tilt-legal/cubitt-components/toggle-group";
    import { Toolbar } from "@tilt-legal/cubitt-components/toolbar";
    import { Grid, Menu, Plus, Xmark } from "@tilt-legal/cubitt-icons/ui/outline";

    <Toolbar size="md">
      <Toolbar.Heading>
        <Toolbar.Title>Documents</Toolbar.Title>
        <Toolbar.Count>42</Toolbar.Count>
      </Toolbar.Heading>
      <Toolbar.Actions>
        <SearchExpand collapseOnBlurWhenEmpty size="md">
          <Input
            aria-label="Search files"
            placeholder="Search files"
            size="md"
            value={query}
            onChange={(event) => setQuery(event.currentTarget.value)}
          />
          <Button
            className="-me-2"
            disabled={!query}
            mode="icon"
            onClick={() => setQuery("")}
            size="md"
            type="button"
            variant="link"
          >
            {query ? <Xmark /> : null}
          </Button>
        </SearchExpand>
        <ToggleGroup
          aria-label="View options"
          groupVariant="segmented"
          multiple={false}
          size="md"
          value={view}
          onValueChange={setView}
        >
          <ToggleGroupItem aria-label="Grid view" mode="icon" value="grid">
            <Grid />
          </ToggleGroupItem>
          <ToggleGroupItem aria-label="List view" mode="icon" value="list">
            <Menu />
          </ToggleGroupItem>
        </ToggleGroup>
        <Toolbar.Separator />
        <Button size="md" variant="secondary">
          <Plus />
          Add
        </Button>
      </Toolbar.Actions>
    </Toolbar>
    ```
  </Tab>
</Tabs>

### Breadcrumb [#breadcrumb]

<Tabs className="bg-transparent border-none rounded-none" items="[&#x22;Preview&#x22;, &#x22;Code&#x22;]">
  <Tab value="Preview" className="p-0">
    <Preview name="ToolbarBreadcrumbExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import {
      BreadcrumbIcon,
      BreadcrumbItem,
      BreadcrumbLabel,
      BreadcrumbLink,
      BreadcrumbList,
      BreadcrumbOverflowItem,
      BreadcrumbOverflowMenu,
      BreadcrumbPage,
      BreadcrumbSeparator,
    } from "@tilt-legal/cubitt-components/breadcrumb";
    import { Button } from "@tilt-legal/cubitt-components/button";
    import { Toolbar } from "@tilt-legal/cubitt-components/toolbar";
    import {
      Tooltip,
      TooltipContent,
      TooltipTrigger,
    } from "@tilt-legal/cubitt-components/tooltip";
    import { FilesFolderIcon } from "@tilt-legal/cubitt-components/files";

    const hiddenFolders = [
      { id: "matter", label: "Matter" },
      { id: "disclosure", label: "Disclosure" },
    ];
    const widthClassName = "w-[28rem]";

    <Toolbar>
      <Toolbar.Heading className={widthClassName}>
        <Toolbar.Breadcrumb className="@container w-full">
          <BreadcrumbList>
            <BreadcrumbItem className="shrink-0">
              <BreadcrumbLink href="/">
                <BreadcrumbLabel className="shrink-0">Files</BreadcrumbLabel>
              </BreadcrumbLink>
            </BreadcrumbItem>
            <BreadcrumbSeparator>/</BreadcrumbSeparator>
            <BreadcrumbItem className="hidden @max-[24rem]:inline-flex">
              <BreadcrumbOverflowMenu>
                {hiddenFolders.map((folder) => (
                  <BreadcrumbOverflowItem key={folder.id}>
                    <FilesFolderIcon />
                    {folder.label}
                  </BreadcrumbOverflowItem>
                ))}
              </BreadcrumbOverflowMenu>
            </BreadcrumbItem>
            <BreadcrumbSeparator className="hidden @max-[24rem]:inline-flex">
              /
            </BreadcrumbSeparator>
            <BreadcrumbItem className="shrink-0 @max-[24rem]:hidden">
              <Tooltip delay={400}>
                <TooltipTrigger
                  render={
                    <BreadcrumbLink href="/">
                      <BreadcrumbIcon>
                        <FilesFolderIcon />
                      </BreadcrumbIcon>
                      <BreadcrumbLabel className="shrink-0 @max-[34rem]:sr-only">
                        Matter
                      </BreadcrumbLabel>
                    </BreadcrumbLink>
                  }
                />
                <TooltipContent side="bottom">Matter</TooltipContent>
              </Tooltip>
            </BreadcrumbItem>
            <BreadcrumbSeparator className="@max-[24rem]:hidden">/</BreadcrumbSeparator>
            <BreadcrumbItem className="shrink-0 @max-[24rem]:hidden">
              <BreadcrumbLink href="/">
                <BreadcrumbIcon>
                  <FilesFolderIcon />
                </BreadcrumbIcon>
                <BreadcrumbLabel className="shrink-0">Disclosure</BreadcrumbLabel>
              </BreadcrumbLink>
            </BreadcrumbItem>
            <BreadcrumbSeparator className="@max-[24rem]:hidden">/</BreadcrumbSeparator>
            <BreadcrumbItem className="shrink-0">
              <BreadcrumbPage>
                <BreadcrumbIcon>
                  <FilesFolderIcon />
                </BreadcrumbIcon>
                <BreadcrumbLabel className="shrink-0">Closing Set</BreadcrumbLabel>
              </BreadcrumbPage>
            </BreadcrumbItem>
          </BreadcrumbList>
        </Toolbar.Breadcrumb>
      </Toolbar.Heading>
      <Toolbar.Actions>
        <Button>Upload</Button>
      </Toolbar.Actions>
    </Toolbar>
    ```
  </Tab>
</Tabs>

### Title Trigger [#title-trigger]

<Tabs className="bg-transparent border-none rounded-none" items="[&#x22;Preview&#x22;, &#x22;Code&#x22;]">
  <Tab value="Preview" className="p-0">
    <Preview name="ToolbarTitleTriggerExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import { Button } from "@tilt-legal/cubitt-components/button";
    import {
      Menu,
      MenuContent,
      MenuRadioGroup,
      MenuRadioItem,
      MenuTrigger,
    } from "@tilt-legal/cubitt-components/menu";
    import { Toolbar } from "@tilt-legal/cubitt-components/toolbar";

    const activeLabel =
      panels.find((panel) => panel.id === activePanel)?.label ?? "";

    <Toolbar>
      <Toolbar.Heading>
        <Toolbar.Title>Attach</Toolbar.Title>
        <Menu>
          <MenuTrigger
            render={<Toolbar.TitleTrigger>{activeLabel}</Toolbar.TitleTrigger>}
          />
          <MenuContent align="start">
            <MenuRadioGroup onValueChange={setActivePanel} value={activePanel}>
              {panels.map((panel) => (
                <MenuRadioItem closeOnClick key={panel.id} value={panel.id}>
                  {panel.label}
                </MenuRadioItem>
              ))}
            </MenuRadioGroup>
          </MenuContent>
        </Menu>
      </Toolbar.Heading>
      <Toolbar.Actions>
        <Button>Attach</Button>
      </Toolbar.Actions>
    </Toolbar>
    ```
  </Tab>
</Tabs>

## API Reference [#api-reference]

### Toolbar [#toolbar]

| Prop        | Type                   | Default | Description                                                                                                                               |
| ----------- | ---------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `size`      | `"sm" \| "md" \| "lg"` | `"md"`  | Scales toolbar-owned spacing, separator height, title text, count text, and title trigger text. Pass matching sizes to composed controls. |
| `wrap`      | `boolean`              | `false` | Allows toolbar contents to wrap when horizontal space is constrained.                                                                     |
| `className` | `string`               | -       | Overrides or extends root toolbar styles.                                                                                                 |
| `children`  | `ReactNode`            | -       | Toolbar content.                                                                                                                          |

Also accepts standard `div` props.

### Toolbar.Heading [#toolbarheading]

| Prop        | Type        | Default | Description                                                           |
| ----------- | ----------- | ------- | --------------------------------------------------------------------- |
| `className` | `string`    | -       | Overrides or extends the heading region.                              |
| `children`  | `ReactNode` | -       | Usually `Toolbar.Title`, `Toolbar.TitleTrigger`, and `Toolbar.Count`. |

Also accepts standard `div` props.

### Toolbar.Title [#toolbartitle]

| Prop        | Type        | Default | Description                                                         |
| ----------- | ----------- | ------- | ------------------------------------------------------------------- |
| `className` | `string`    | -       | Overrides or extends title text styles, including size when needed. |
| `children`  | `ReactNode` | -       | Title content.                                                      |

Also accepts standard `div` props.

### Toolbar.Breadcrumb [#toolbarbreadcrumb]

| Prop        | Type        | Default | Description                                                                     |
| ----------- | ----------- | ------- | ------------------------------------------------------------------------------- |
| `className` | `string`    | -       | Overrides or extends toolbar breadcrumb styles.                                 |
| `children`  | `ReactNode` | -       | Primitive breadcrumb composition, usually `BreadcrumbList` and its child slots. |

Also accepts primitive `Breadcrumb` props.

### Toolbar.TitleTrigger [#toolbartitletrigger]

| Prop          | Type        | Default           | Description                                    |
| ------------- | ----------- | ----------------- | ---------------------------------------------- |
| `showChevron` | `boolean`   | `true`            | Shows the trailing chevron.                    |
| `chevron`     | `ReactNode` | `<ChevronDown />` | Custom trailing indicator.                     |
| `className`   | `string`    | -                 | Overrides or extends the title trigger styles. |
| `children`    | `ReactNode` | -                 | Active adjacent label.                         |

Also accepts `Button` props.

### Toolbar.Count [#toolbarcount]

| Prop        | Type        | Default | Description                             |
| ----------- | ----------- | ------- | --------------------------------------- |
| `className` | `string`    | -       | Overrides or extends count text styles. |
| `children`  | `ReactNode` | -       | Count content.                          |

Also accepts standard `span` props.

### Toolbar.Group And Toolbar.Actions [#toolbargroup-and-toolbaractions]

| Prop        | Type        | Default | Description                             |
| ----------- | ----------- | ------- | --------------------------------------- |
| `className` | `string`    | -       | Overrides or extends the control group. |
| `children`  | `ReactNode` | -       | Grouped controls.                       |

Both accept standard `div` props.

### Toolbar.Spacer [#toolbarspacer]

| Prop        | Type     | Default | Description                               |
| ----------- | -------- | ------- | ----------------------------------------- |
| `className` | `string` | -       | Overrides or extends the flexible spacer. |

Also accepts standard `div` props.

### Toolbar.Separator [#toolbarseparator]

| Prop          | Type                         | Default      | Description                                                         |
| ------------- | ---------------------------- | ------------ | ------------------------------------------------------------------- |
| `orientation` | `"horizontal" \| "vertical"` | `"vertical"` | Separator direction. Vertical separators get toolbar-sized heights. |
| `className`   | `string`                     | -            | Overrides or extends separator styles.                              |

Also accepts primitive `Separator` props.
