Customizing the Sidebar Component in Our JavaScript PDF Viewer

PSPDFKit for Web enables you to fully customize the sidebar component. This is possible thanks to the UI customization API.

This API allows you to override or customize specific parts of the sidebar UI when rendering.

You can provide a PSPDFKit.CustomUIConfiguration object in the configuration with callback functions that return a DOM element to be rendered either instead of the UI element or inside it.

UI customization can be finetuned for different states of a UI element. In the case of the sidebar, different callbacks can be provided for the different sidebar modes, including the CUSTOM sidebar mode.

For example, a callback function used to customize the annotations sidebar should be located under PSPDFKit.Configuration.customUI[PSPDFKit.UIElement.Sidebar][PSPDFKit.SidebarMode.ANNOTATIONS]. This callback must return a PSPDFKit.UIRendererConfiguration object.

You can register a custom sidebar callback function when initializing PSPDFKit:

PSPDFKit.load({
  customUI:{
	// Currently, we only support customization of the sidebar.
	[PSPDFKit.UIElement.Sidebar]: {
		[PSPDFKit.SidebarMode.ANNOTATIONS]({ containerNode }) {
	    	const textNode = document.createTextNode("Some text appended at the end of the sidebar");
	    	return {
	      	node: textNode
	    	}
	  	}
	}
})

You can also add your changes at runtime using `PSPDFKit.Instance#setCustomUIConfiguration:

instance.setCustomUIConfiguration((customUiConfiguration) => ({
  ...customUIConfiguration,
  [PSPDFKit.UIElement.Sidebar]: {
    [PSPDFKit.SidebarMode.CUSTOM]({ containerNode }) {
      containerNode.append("Some text in a custom sidebar.");

      return {
        node: containerNode
      };
    }
  }
}));

Whenever the element is updated due to changes in the application state — such as new annotations being added while the user has the annotation sidebar selected — this callback is called.

You can perform any desired modification in the callback, either by modifying the provided DOM node, or by returning a new one to be appended.

In other words, the callback you passed to Configuration.customUI.Sidebar#[PSPDFKit.SidebarMode] will be called when the application state related to the sidebar changes: in the annotation sidebar, when annotations change; in the bookmarks sidebar, when bookmarks change; and so on. The CUSTOM sidebar callback will only be called either on mount, or when the customer code calls instance.setCustomUIConfiguration().

The callback will return additional or replacement DOM content for either the entire sidebar UI or specific parts of it.

Next, let’s look at some examples of how to use this API.

Replacing the Sidebar with a Custom One

The following example shows how to replace the sidebar with a custom one by returning the full DOM element:

PSPDFKit.load({
  customUI: {
    [PSPDFKit.UIElement.Sidebar]: {
      [PSPDFKit.SidebarMode.CUSTOM]({ containerNode }) {
        // `ReactDOM.createPortal()` can be used as well.
        // Or Vue portals, or any other framework API that allows appending components
        // to arbitrary DOM nodes.
        // Using vanilla JavaScript, you can append a node to `parentNode`.
        const div = document.createElement("div");
        div.append("My custom sidebar");
        containerNode.appendChild(div);
        return {
          // By returning the same node that was provided, you opt out of having the node
          // appended. If you return a different node, it'll be appended to the provided node.
          node: containerNode
        };
      }
    }
  }
});

Partial Sidebar Customization

If you want to reuse one of the built-in sidebars with partial modifications, you can do so by adding your desired customization to portions of the sidebar UI. For example, here’s how you can customize the appearance of our annotations sidebar:

PSPDFKit.load({
  customUI: {
    [PSPDFKit.UIElement.Sidebar]: {
      [PSPDFKit.SidebarMode.ANNOTATIONS]({ containerNode }) {
        containerNode.style.padding = "0.5rem";
        if (!containerNode.querySelector(".MyCustomSidebarComponentHeader")) {
          const header = document.createElement("div");
          header.classList.add("MyCustomSidebarComponentHeader");
          containerNode.prepend(header);
        }
        return {
          node: containerNode,
          onRenderItem({ itemContainerNode, item: annotation }) {
            const footerAuthor = itemContainerNode.querySelector(".PSPDFKit-Sidebar-Annotations-Footer span");
            // Change the format of the footer text by prefixing it with `Creator:` and removing the date.
            footerAuthor.textContent = `Creator: ${annotation.creatorName}
            // Add the aria label to the annotation icon.
            const annotationIcon = itemContainerNode.querySelector(".PSPDFKit-Icon");
            annotationIcon.setAttribute("aria-label", `Icon for an annotation created by ${annotation.creatorName}.`);
          }
        }
      }
    }
  }
})

More Information

Refer to our public API documentation to read more technical details about our customization feature and learn how to use it in your implementation.

We also recommend having a look at the Customized Sidebar example available in our public demo.