# Toolbar

Controls the top toolbar appearance and action buttons: which toolbar renders, which tool groups it shows, the built-in Print, Download, Undo and Redo buttons, the "You are offline" strip, your own action buttons and icon overrides. Three toolbars ship — the bar, the ribbon and the rail — and they always agree about which tools exist and which group a tool belongs to.

- Interface: `ToolbarConfig`
- Config path: `config.toolbar`

## Example

```ts
toolbar: {
  layout: 'ribbon',
  groups: ['annotate', 'review'],
  print: true,
  download: false,
  actions: [{
    id: 'submit',
    label: 'Submit',
    icon: 'done',
    variant: 'primary',
    onClick: async () => { /* custom logic */ }
  }],
}
```

## Options (14)

### `enabled`

- Type: `boolean`
- Default: `true`
- Page: https://kernstra.com/docs/web-sdk/config/toolbar/enabled

Show or hide the entire toolbar. `layout: 'none'` and the older `enabled: false` both render no toolbar and are interchangeable. Prefer `layout`, which says _which_ toolbar rather than _whether_, and reads correctly alongside `'bar'` and `'ribbon'`.

```ts
// No toolbar at all
toolbar: { enabled: false }
```

### `layout`

- Type: `ToolbarLayout ('bar' | 'ribbon' | 'none' | 'rail')`
- Default: `'bar'`
- Page: https://kernstra.com/docs/web-sdk/config/toolbar/layout

Which toolbar to render. The trade is deliberate: the bar is shorter (64px against the ribbon's ~105px) but on a narrow container some tools end up behind **More**. The ribbon always costs a second row and always keeps every tool one tab away. None is correct for every host, which is why all three ship.

- `'bar'`: Default. One row of tools in labeled clusters. Under pressure it drops labels, then moves the lowest-priority tools into a **More** menu. Choose it when tools are used in short bursts and the document deserves the vertical space.
- `'ribbon'`: A tab per group; the selected group's tools sit on a second row. Under pressure the tab strip scrolls and labels drop — **a tool is never hidden**. Choose it when users work in one mode at a time (mark up a document, then fill a form), or you cannot accept a tool becoming unreachable.
- `'rail'`: The bar's tools down the left edge and the active tool's options down the right, the pages between; the top bar keeps the chrome. What a tablet gets by default (see [`layout.tablet`](https://kernstra.com/docs/web-sdk/config/layout/tablet)). Choose it when you want this arrangement on every screen but a phone.
- `'none'`: No toolbar at all. The nav bar, panels and page area render as usual. For hosts building their own chrome and driving the SDK through the viewer API.

```ts
new PDFViewer(container, doc, {
  toolbar: { layout: 'ribbon' },
});
```

### `groups`

- Type: `string[]`
- Default: `[] (all)`
- Page: https://kernstra.com/docs/web-sdk/config/toolbar/groups

The group ids you want. A group you leave out is dropped with its tools — how a review product ships three tabs instead of six. Unknown ids are ignored. On the ribbon each group is a tab, in the order you list them. The bar arranges its tools its own way, so there the list only decides which tools appear. Dropped tools stay available to `viewer.activateTool()`, for hosts that draw their own buttons; use [`tools`](https://kernstra.com/docs/web-sdk/config/tools) to switch a tool off entirely. The six ids and their tools are in the table below.

A group whose every tool is disabled through `tools` renders no tab and no cluster — you will not be left with an empty **Annotate** tab.

```ts
// A review product: mark-up first, then reading. No text editing, pages or security.
toolbar: { layout: 'ribbon', groups: ['annotate', 'review'] }
```

### `print`

- Type: `boolean`
- Default: `true`
- Page: https://kernstra.com/docs/web-sdk/config/toolbar/print

Show the built-in Print button. The button needs the `print` license feature. [`print.ask`](https://kernstra.com/docs/web-sdk/config/print/ask) says whether it asks first; [`callbacks.onPrint`](https://kernstra.com/docs/web-sdk/config/callbacks/onprint) takes it over.

```ts
toolbar: { print: false }
```

### `download`

- Type: `boolean`
- Default: `true`
- Page: https://kernstra.com/docs/web-sdk/config/toolbar/download

Show the built-in Download button. The button needs the `export` license feature. [`export.askOnDownload`](https://kernstra.com/docs/web-sdk/config/export/askondownload) says whether it asks first; [`callbacks.onDownload`](https://kernstra.com/docs/web-sdk/config/callbacks/ondownload) takes it over.

```ts
toolbar: { download: false }
```

### `history`

- Type: `boolean`
- Default: `true`
- Page: https://kernstra.com/docs/web-sdk/config/toolbar/history

Show the Undo and Redo buttons. Off under a license that lets no change happen. `history: false` removes them from every layout; Ctrl / ⌘ + Z still undoes (turn every shortcut off with [`navigation.keyboardShortcuts`](https://kernstra.com/docs/web-sdk/config/navigation/keyboardshortcuts)), and `viewer.undo()` / `viewer.redo()` stay available for your own buttons.

```ts
toolbar: { history: false }
```

### `offlineNotice`

- Type: `boolean`
- Default: `true`
- Page: https://kernstra.com/docs/web-sdk/config/toolbar/offlinenotice

The "You are offline" strip above the pages. `offlineNotice: false` keeps the strip from appearing while the browser reports no connection. The strip follows the browser's own online state, which an intranet host reports as online; where a host's network makes the browser report offline, `false` keeps it away.

### `actions`

- Type: `ToolbarAction[]`
- Page: https://kernstra.com/docs/web-sdk/config/toolbar/actions

Your buttons. Bar: after Print/Download. Ribbon: before them. Give every action an icon. On a compact bar, labels are hidden on all but `primary` actions, and on a narrow or tiny bar on every action: the button shows only its icon (the label stays its tooltip and accessible name). A name such as `'done'` also picks up your `toolbar.icons` replacement for it. Actions are set when the viewer is built and cannot be disabled or relabeled later. A rejected promise from `onClick` is logged and reported through the [`error`](https://kernstra.com/docs/web-sdk/api/events#ev-error) event.

```ts
// Only a "Done" button that uploads to S3
toolbar: {
  print: false,
  download: false,
  actions: [{
    id: 'done',
    label: 'Done',
    icon: 'done',
    variant: 'primary',
    onClick: async () => {
      const exporter = viewer.createExporter();
      const res = await exporter.uploadTo(presignedUrl, { method: 'PUT' });
      // An HTTP error does not reject; a throw here reaches the `error` event.
      if (!res.ok) throw new Error('Upload failed: ' + res.status);
    }
  }]
}
```

#### `actions.id`

- Type: `string`
- Required
- Page: https://kernstra.com/docs/web-sdk/config/toolbar/actions-id

Your own name for the action; the SDK uses it only to name the action in an error report.

#### `actions.label`

- Type: `string`
- Required
- Page: https://kernstra.com/docs/web-sdk/config/toolbar/actions-label

Button text.

#### `actions.icon`

- Type: `string`
- Page: https://kernstra.com/docs/web-sdk/config/toolbar/actions-icon

An `IconName`, or raw SVG markup starting with `<svg`. An action icon that is neither a name nor markup starting with `<svg` draws nothing.

```ts
// Custom SVG icon for an action button
toolbar: {
  actions: [{
    id: 'share',
    label: 'Share',
    icon: '<svg viewBox="0 0 20 20">...</svg>',
    onClick: () => { /* share logic */ }
  }]
}
```

#### `actions.variant`

- Type: `'default' | 'primary'`
- Page: https://kernstra.com/docs/web-sdk/config/toolbar/actions-variant

`'primary'` = accent-colored.

- `'default'`: A regular toolbar button.
- `'primary'`: Accent-colored. On a compact bar it is the only action that keeps its label.

#### `actions.onClick`

- Type: `() => void | Promise<void>`
- Required
- Page: https://kernstra.com/docs/web-sdk/config/toolbar/actions-onclick

Called when the button is pressed. A rejected promise is logged and reported through the `error` event.

### `icons`

- Type: `Partial<Record<IconName, string>>`
- Page: https://kernstra.com/docs/web-sdk/config/toolbar/icons

Replace any icon the SDK draws, by name. Every icon has a name — the toolbar and ribbon, the navigation bar, the sidebar and its panels, search, the phone sheet, the tools' option bars, the selection bar, and the dialogs (signature, stamp, link, image, security, Manage Pages, the document states). Names you leave out keep the built-in; a replacement is drawn as given, so an empty string shows no icon. The keys are typed as `IconName`, so a misspelt name is a compile error. The same names work as a `ToolbarAction.icon`. Outside a viewer, `createDropZone`, `createPasswordPrompt` and `createLoadError` take the same map as `options.icons`. Icons that are part of the document — what a stamp or a note looks like in the saved file — are content, not chrome, and are not in this list.

**Security note:** icon values are injected into the toolbar as raw HTML. This is host-controlled configuration by design, but treat it accordingly: only pass trusted, static SVG markup — never user-supplied or remotely-fetched strings. A replacement can be any markup; it is inserted as given, not checked or cleaned. Use a single `<svg>` root with a `viewBox`: the SDK sizes the `svg` element with CSS (24px on the toolbar), so the `width` and `height` attributes do not decide its size. Leave out `<title>`: each button already has a name from the string table.

```ts
import { ICONS, type IconName } from '@kernstra/pdf-web-sdk';

const brandIcons: Partial<Record<IconName, string>> = {
  zoomIn: myZoomInSvg,
  close: myCloseSvg,
  securityShield: myShieldSvg,
};
new PDFViewer(container, doc, { toolbar: { icons: brandIcons } });

// Reuse a built-in in your own chrome:
exportButton.innerHTML = ICONS.download;
```

## Tool groups

| Id | Ribbon tab | Tools |
| --- | --- | --- |
| `review` | Review | `selectText`, `pan`, `search`, `undo`, `redo` |
| `annotate` | Annotate | `highlight`, `textHighlight`, `note`, `freeText`, `draw`, `rectangle`, `ellipse`, `line`, `arrow`, `polygon`, `polyline`, `check`, `cross`, `dot`, `erase` |
| `text` | Edit text | `editText`, `addText` |
| `insert` | Insert | `sign`, `image`, `stamp`, `link` |
| `pages` | Pages | `managePages` |
| `protect` | Protect | `security` |

## Every icon name, by the surfaces that draw it

| Surfaces | Names |
| --- | --- |
| Toolbar, ribbon, navigation bar, sidebar and panels, search, phone sheet | `more`, `close`, `thumbnails`, `outline`, `attachments`, `signatures`, `pan`, `selectText`, `undo`, `redo`, `addText`, `editText`, `sign`, `arrow`, `draw`, `line`, `rectangle`, `ellipse`, `polygon`, `polyline`, `erase`, `highlight`, `textHighlight`, `image`, `stamp`, `markCheck`, `markCross`, `markDot`, `marks`, `link`, `note`, `search`, `managePages`, `security`, `print`, `download`, `done`, `chevronLeft`, `chevronRight`, `chevronDoubleLeft`, `chevronDoubleRight`, `zoomIn`, `zoomOut`, `fitWidth`, `fitPage`, `menuCaret`, `sidebarCollapse`, `toolsFab`, `outlineToggle`, `outlineEmpty`, `outlineFilter`, `outlineFilterClear`, `comments`, `commentsEmpty`, `commentsSearch`, `commentsFilter`, `commentMore`, `attachmentsEmpty`, `attachmentDownload`, `attachmentRemove`, `thumbnailRotate`, `thumbnailMore`, `searchPrevious`, `searchNext`, `searchClose`, `shapes`, `freeText` |
| Shared widgets, document states, Manage Pages, security | `stateLock`, `stateBroken`, `stateOffline`, `dropZoneFile`, `chipCaret`, `eyedropper`, `securityLock`, `securityShield`, `securityCheck`, `securityBlocked`, `securityEye`, `securityWarning`, `pageRotateLeft`, `pageRotateRight`, `pageDuplicate`, `pageExtract`, `pageAdd`, `pageImport`, `pageDelete`, `pagesClose`, `pagesCheck`, `pageAddTile`, `pageGrip` |
| Annotation tools, selection bar, stamps, links, images, signatures | `selectUnderline`, `selectSquiggly`, `selectStrikethrough`, `selectCopy`, `selectNote`, `selectSearch`, `selectBlackOut`, `selectMore`, `selectCaret`, `notePerson`, `imageDrop`, `objectRotate`, `objectEdit`, `objectDuplicate`, `objectRotate90`, `objectColor`, `objectLayer`, `objectDelete`, `stampNew`, `stampFold`, `signatureUpload` |
| Add text, Edit text, drawing tools | `alignLeft`, `alignCenter`, `alignRight`, `editTextDelete`, `sheetClose` |

## Notes

**Icon design guidelines:** use a `24×24` viewBox for consistency with built-in icons; `stroke="currentColor"` so icons inherit the toolbar's text color; a `2px` stroke width, which is what the built-in set draws with, so a custom icon reads at the same weight as its neighbors; `stroke-linecap="round"` and `stroke-linejoin="round"`; and subtle `fill="currentColor" opacity="0.1"` accents for better recognition at small sizes.

The Insert tab disappears entirely with `tools: { sign: false, image: false, stamp: false, link: false }`: a group whose every tool is off renders no tab and no cluster.


Web page: https://kernstra.com/docs/web-sdk/config/toolbar
