Creating a Custom Annotation Toolbar for Mobile Devices

You can have a separate UI for mobile devices to make sure you get the most from limited space.

Launch Demo

The built-in items are shown in two levels in the mobile view. The first level shows the icon for a particular tool item, and when you click on it, you get the full view of that item.

You can achieve something similar using the icon property of PSPDFKit.AnnotationToolbarItem:

const selectNode = document.createElement("select");

selectNode.innerHTML = `
	<option value="alice">Alice</option>
	<option value="Bob">Bob</option>
	<option value="carol">Carol</option>
	<option value="john">John</option>
`;

selectNode.addEventListener("change", (event) => {
  console.log(`Selected option: ${event.target.value}`);
});

const item = {
  type: "custom",
  id: "my-button",
  icon: `<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24" fill="none" viewBox="0 0 24 24" stroke="currentColor">
           <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4" />
         </svg>`,
  node: selectNode,
  onPress: (event) => {
    alert("hello from my button");
  }
};

instance.setAnnotationToolbarItems(
  (annotation, { defaultAnnotationToolbarItems }) => {
    return [...defaultAnnotationToolbarItems, item];
  }
);

If you use the above code, here’s what will happen.

  • On a desktop:

    • The node will be rendered in the annotation toolbar. If you haven’t passed node, we’ll render the icon.

  • For a mobile layout:

    • The icon will be rendered on the first level, and the node will be rendered when you click on that icon.

    • If you haven’t passed icon, the node will be rendered on the first level.

There might be situations where you want to pass different nodes based on whether the device has a mobile layout or not. You can use the hasDesktopLayout property passed in the callback to do that:

instance.setAnnotationToolbarItems(
  (annotation, { defaultAnnotationToolbarItems, hasDesktopLayout }) => {
    return hasDesktopLayout
      ? [...defaultAnnotationToolbarItems, item]
      : defaultAnnotationToolbarItems;
  }
);