Copy/Move MenuOverlay Item to Main Header Toolbar

Product: PDFTron Webviewer

Product Version: 8.1.0

Please give a brief summary of your issue: How do I Copy/Move a MenuOverlay Item?

Please describe your issue and provide steps to reproduce it:
I’m trying to copy/move the MenuOverlay item for full screen functionality out to the main toolbar. I read documentation here regarding moving header items but found this did not work for a MenuOverlay item as expected. https://www.pdftron.com/documentation/web/guides/customizing-header/. Is it possible to do so?

image

Please provide a link to a minimal sample where the issue is reproducible:
N/A

Hello @iybar,

Currently there is no way to move these elements outside of the MenuOverlay. However, you can add new buttons to the main toolbar that copy the functionality of these items. Since these buttons are part of our open source UI, you can reference to the source code to get an idea of what to use for the onClick handlers as well as the icon names:

Let us know if you have any further questions.
Best Regards,

Armando Bollain
Software Developer
PDFTron Systems, Inc.
www.pdftron.com

@Armando_Bollain Thanks for your response. It’s helped me achieve something similar however I’ve pushed two buttons to the header (Single and Double page button) but I’ve found that the active className doesn’t get applied to it. How would I go about doing this so that when you click on the button, it has the active styles applied to it?

    const singlePageButton = {
      type: 'actionButton',
      img: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><defs><style>.cls-1{fill:#abb0c4;}</style></defs><title>icon - header - page manipulation - page layout - single page - line</title><path class="cls-1" d="M20,8.94a2,2,0,0,0,0-.26.36.36,0,0,0,0-.09,1.17,1.17,0,0,0-.19-.3l-6-6a1.17,1.17,0,0,0-.3-.19l-.09,0L13.06,2H6A2,2,0,0,0,4,4V20a2,2,0,0,0,2,2H18a2,2,0,0,0,2-2V9S20,9,20,8.94ZM6,20V4h6V9a1,1,0,0,0,1,1h5V20Z"/></svg>`,
      onClick: () => {
        instance.UI.setLayoutMode(instance.UI.LayoutMode.Single);
      },
      title: 'Single Page',

    };

    const doublePageButton = {
      type: 'actionButton',
      img: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><defs><style>.cls-1{fill:#abb0c4;}</style></defs><title>icon - header - page manipulation - page layout - double page - line</title><path class="cls-1" d="M11,10.13s0,0,0-.05a1,1,0,0,0-.11-.17L7.46,6.54a.57.57,0,0,0-.16-.11l-.06,0-.14,0h-4A1.12,1.12,0,0,0,2,7.5v9a1.12,1.12,0,0,0,1.13,1.12H9.88A1.12,1.12,0,0,0,11,16.5V10.28A.4.4,0,0,0,11,10.13ZM3.13,16.5v-9H6.5v2.81a.57.57,0,0,0,.56.57H9.88V16.5ZM22,10.28a.4.4,0,0,0,0-.15s0,0,0-.05a1,1,0,0,0-.11-.17L18.46,6.54a.57.57,0,0,0-.16-.11l-.06,0-.14,0h-4A1.12,1.12,0,0,0,13,7.5v9a1.12,1.12,0,0,0,1.13,1.12h6.74A1.12,1.12,0,0,0,22,16.5V10.28ZM14.13,16.5v-9H17.5v2.81a.57.57,0,0,0,.56.57h2.81V16.5Z"/></svg>`,
      onClick: () => {
        instance.UI.setLayoutMode(instance.UI.LayoutMode.Facing);
      },
      title: 'Double Page',
    };

    UI.setHeaderItems((header) => {
      header.push(singlePageButton, doublePageButton);
    });

Hi @user83,

What you want to use for this use case is a StatefulButton, not an ActionButton, as the former can have a state such as an “active” class. Here is an example of how you could get a Stateful button working for a SinglePage layout. You can do the same for the other layout modes. The key here is that you have two states acting as a toggle, and that you also have event listeners to update the button if something outside of the component changes its state.

  const { docViewer } = instance;

  const singlePageButton = {
    type: 'statefulButton',
    initialState: 'NotActive',
    states: {
      SingleActive: {
        img: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><defs><style>.cls-1{fill:#abb0c4;}</style></defs><title>icon - header - page manipulation - page layout - single page - line</title><path class="cls-1" d="M20,8.94a2,2,0,0,0,0-.26.36.36,0,0,0,0-.09,1.17,1.17,0,0,0-.19-.3l-6-6a1.17,1.17,0,0,0-.3-.19l-.09,0L13.06,2H6A2,2,0,0,0,4,4V20a2,2,0,0,0,2,2H18a2,2,0,0,0,2-2V9S20,9,20,8.94ZM6,20V4h6V9a1,1,0,0,0,1,1h5V20Z"/></svg>`,
        onClick: (update) => {
          instance.UI.setLayoutMode(instance.UI.LayoutMode.Single);
          update('SingleActive')
        },
        title: 'Single Page',
        className: 'active',
      },
      NotActive: {
        img: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><defs><style>.cls-1{fill:#abb0c4;}</style></defs><title>icon - header - page manipulation - page layout - single page - line</title><path class="cls-1" d="M20,8.94a2,2,0,0,0,0-.26.36.36,0,0,0,0-.09,1.17,1.17,0,0,0-.19-.3l-6-6a1.17,1.17,0,0,0-.3-.19l-.09,0L13.06,2H6A2,2,0,0,0,4,4V20a2,2,0,0,0,2,2H18a2,2,0,0,0,2-2V9S20,9,20,8.94ZM6,20V4h6V9a1,1,0,0,0,1,1h5V20Z"/></svg>`,
        onClick: (update) => {
          instance.UI.setLayoutMode(instance.UI.LayoutMode.Single);
          update('SingleActive')
        },
        title: 'Single Page',
      }
    },
    mount: (update) => {
      docViewer.addEventListener('displayModeUpdated.displayButton', () => {
        const layoutMode = instance.UI.getLayoutMode();
        if(layoutMode === 'Single') {
          update('SingleActive');
        } else {
          update('NotActive');
        }
      })
    },
    unmount: () => {
      docViewer.removeEventListener('displayModeUpdated.displayButton');
    }
  };

You can make your onclick a bit smarter to detect if it is already in SinglePage mode, but you get the gist of how it should be laid out.

Best Regards,

Armando Bollain
Software Developer
PDFTron Systems, Inc.

Here is an alternative as well with less code. In this sample we use the isActive prop, and only have one state:

  const { docViewer } = instance;

  const singlePageButton = {
    type: 'statefulButton',
    initialState: 'SingleActive',
    states: {
      SingleActive: {
        img: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><defs><style>.cls-1{fill:#abb0c4;}</style></defs><title>icon - header - page manipulation - page layout - single page - line</title><path class="cls-1" d="M20,8.94a2,2,0,0,0,0-.26.36.36,0,0,0,0-.09,1.17,1.17,0,0,0-.19-.3l-6-6a1.17,1.17,0,0,0-.3-.19l-.09,0L13.06,2H6A2,2,0,0,0,4,4V20a2,2,0,0,0,2,2H18a2,2,0,0,0,2-2V9S20,9,20,8.94ZM6,20V4h6V9a1,1,0,0,0,1,1h5V20Z"/></svg>`,
        onClick: (update) => {
          instance.UI.setLayoutMode(instance.UI.LayoutMode.Single);
          update()
        },
        title: 'Single Page',
        isActive: () => instance.UI.getLayoutMode() === 'Single',
      },
    },
    mount: (update) => {
      docViewer.addEventListener('displayModeUpdated.displayButton', update)
    },
    unmount: () => {
      docViewer.removeEventListener('displayModeUpdated.displayButton');
    }
  };
1 Like