---
title: "Create custom toolbar in JavaScript PDF viewer | Nutrient"
canonical_url: "https://www.nutrient.io/guides/web/user-interface/create-a-toolbar/"
md_url: "https://www.nutrient.io/guides/web/user-interface/create-a-toolbar.md"
last_updated: "2026-06-11T12:46:37.013Z"
description: "Build a custom toolbar around Nutrient Web SDK that can be positioned anywhere on the page, including host-app controls for keyboard-accessible review actions such as save, export, and annotation commands."
---

# Create a custom toolbar in our JavaScript PDF viewer

With Nutrient Web SDK, you can replace the default toolbar with a custom toolbar that can be positioned anywhere on the page.

If you’re building keyboard-accessible review controls in your host application, also refer to the [keyboard-accessible review workflow](https://www.nutrient.io/guides/web/viewer/accessibility/keyboard-review-workflow.md) guide for focus management, `aria-live` status updates, and save/export semantics.

The first step is to hide the default toolbar using our [ViewState API](https://www.nutrient.io/api/web/classes/NutrientViewer.ViewState.html#showtoolbar), which is a snapshot representation of the current state of the PDF viewer. It can be updated using the [`Instance#setViewState`](https://www.nutrient.io/api/web/classes/NutrientViewer.Instance.html#setviewstate) method:

```js

const viewState = instance.viewState;
instance.setViewState(viewState.set("showToolbar", false));

```

You can read more about this in our [view state](https://www.nutrient.io/guides/web/customizing-the-interface/viewstate.md) guide.

There are two ways to implement a custom toolbar:

- Independent of the Nutrient instance

- By rendering custom document object model (DOM) nodes inside the PDF page content itself with our [custom overlay feature](https://www.nutrient.io/guides/web/customizing-the-interface/creating-custom-overlay-items.md)

## Implementing a custom toolbar independent of the Nutrient instance

You can implement a custom toolbar using a pure HTML solution. In the following example, you’ll create a custom toolbar with one button that creates a text annotation when clicked:

```html

<!DOCTYPE html>
<html>
  <head>
    <title>Nutrient Web SDK | Custom Toolbar Testcase</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <div>
      <!-- custom toolbar element-->

      <div id="customToolbar">
        <button id="createAnnotation">Create Annotation</button>
      </div>
      <!-- element where we display PSPDFKit instance-->

      <div id="container" style="width: 100%; height: 100vh;"></div>
    </div>
    <script src="https://de.stable.our.services.nutrient-powered.io/pspdfkit.js"></script>
    <script src="./index.js"></script>
  </body>
</html>

```

Use the following JavaScript to load the viewer, hide the default toolbar, and wire the custom button to create an annotation:

```js

NutrientViewer.load({
  container: "#container",

  document: "./assets/test.pdf",
}).then(async (instance) => {
    // Hides the Nutrient default toolbar.
    const viewState = instance.viewState;
    instance.setViewState(viewState.set("showToolbar", false));

    // Adds a text annotation to the document when the button in the custom toolbar is clicked.
    const btn = document.getElementById("createAnnotation");
    btn.onclick = function (event) {
      const annotation = new NutrientViewer.Annotations.TextAnnotation({
        pageIndex: 0,
        text: {
          format: "plain",
          value: "Welcome to\nPSPDFKit",
        },
        font: "Helvetica",
        isBold: true,
        horizontalAlign: "center",
        boundingBox: new NutrientViewer.Geometry.Rect({
          left: 100,
          top: 200,
          width: 100,
          height: 80
        }),
        fontColor: NutrientViewer.Color.BLACK
      });
      instance.create(annotation);
    };
  }).catch(function (error) {
    console.error(error.message);
  });

```

Another way to achieve the HTML structure above is to create a custom component that returns it:

```js

export const CustomComponent = () => {
  return (
    <div>
      <!-- custom toolbar element-->

      <div id="customToolbar">
        <button id="createAnnotation">
            Create Annotation
        </button>
      </div>
      <!-- element where we display PSPDFKit instance-->

      <div id="container" style="width: 100%; height: 100vh;"></div>
    </div>
  );
}

```

## Rendering a custom DOM node with custom overlays

As described in our [custom overlay](https://www.nutrient.io/guides/web/customizing-the-interface/creating-custom-overlay-items.md) guide, custom overlay items are user-generated DOM nodes that are rendered in a page at a given position and add custom functionality to Nutrient Web SDK. For example, they can be used to add images, videos, or complex widgets written either in plain JavaScript or with your framework of choice.

Custom overlay items aren’t part of the PDF specification, and are therefore never persisted in a PDF document or database by Nutrient Web SDK.

A custom overlay item is a simple instance of [`NutrientViewer.CustomOverlayItem`](https://www.nutrient.io/api/web/classes/NutrientViewer.CustomOverlayItem.html). To create this instance, build your item in JavaScript first:

```js

const customToolbar = document.createElement("div");
customToolbar.innerHTML = `
      <div id="customToolbar">
        <button id="createAnnotation">
          Create Annotation
        </button>
       </div>
    `;
const btn = customToolbar.querySelector("#createAnnotation");

btn.onclick = function (event) {
  const annotation = new NutrientViewer.Annotations.TextAnnotation({
    pageIndex: 0,
    text: {
      format: "plain",
      value: "Welcome to\nPSPDFKit"
    },
    font: "Helvetica",
    isBold: true,
    horizontalAlign: "center",
    boundingBox: new NutrientViewer.Geometry.Rect({
      left: 100,
      top: 200,
      width: 100,
      height: 80
    }),
    fontColor: NutrientViewer.Color.BLACK
  });
  instance.create(annotation);
};

```

Once you have your DOM node, you can create the item:

```js

const item = new NutrientViewer.CustomOverlayItem({
  id: "custom-toolbar",
  node: customToolbar,
  pageIndex: 0,
  position: new NutrientViewer.Geometry.Point({ x: 0, y: 0 })
});

```

Finally, insert the item into the PDF document using the [`Instance#setCustomOverlayItem`](https://www.nutrient.io/api/web/classes/NutrientViewer.Instance.html#setcustomoverlayitem) method:

```js

instance.setCustomOverlayItem(item);

```
---

## Related pages

- [Form Designer: Create and edit PDF form fields using JavaScript](/guides/web/user-interface/form-designer.md)
- [PDF form field date and time picker](/guides/web/user-interface/date-and-time-picker.md)
- [Localization: Updating languages in our JavaScript PDF viewer](/guides/web/features/localization.md)
- [Custom overlays in our viewer](/guides/web/customizing-the-interface/creating-custom-overlay-items.md)
- [Right-to-left](/guides/web/user-interface/rtl-languages.md)
- [User interface customization in our JavaScript PDF viewer](/guides/web/user-interface.md)
- [Customizing the search UI in our PDF viewer toolbar](/guides/web/user-interface/search.md)
- [Create and customize redactions in our PDF viewer](/guides/web/user-interface/redaction.md)
- [User interface troubleshooting](/guides/web/user-interface/troubleshooting.md)
- [View state in our JavaScript PDF viewer](/guides/web/customizing-the-interface/viewstate.md)

