Skip to content

Accessing Viewer Elements

React PDF provides data-rp attributes to access specific elements so that you can customize the viewer easily.

Attributedescription
data-rp="moreOptionsDropdown"The dropdown container of the More Options menu
data-rp="page-{pageNumber}"Page element
Remark: ReplacepageNumber with a specific value (e.g., data-rp="page-21")
data-rp="page-{pageNumber}-canvas"Page canvas element
Remark: ReplacepageNumber with a specific value (e.g., data-rp="page-21-canvas")
data-rp="page-{pageNumber}-textLayer"Page text layer element
Remark: ReplacepageNumber with a specific value (e.g., data-rp="page-21-textLayer")
data-rp="pages"Page container element
data-rp="sidebar"Sidebar container
data-rp="thumbnailSidebar"Thumbnail sidebar container
data-rp="topBar"The top bar container which consists of 3 sections (i.e. left, center and right)
data-rp="topBarCenter"The middle section of the top bar container which consists of the zoom feature
data-rp="topBarLeft"The left section of the top bar container which consists of search and page navigation
data-rp="topBarRight"The right section of the top bar container which consists of the rest of the features, including those in the More Options

Remark: If you would like to access other elements, please submit a request on GitHub.

Example: Accessing topBarRight Element to Prepend a Button

  1. Create a button element

    const buttonElement = useMemo(() => {
    const button = document.createElement('button')
    button.innerHTML = 'N'
    return button
    }, [])
  2. Get the element of the right section of the top bar container

    const topBarRight = ref.current?.querySelector('[data-rp="topBarRight"]')
  3. Add a button element to the element

    topBarRight?.prepend(buttonElement)
  4. Remove the button element when the component is cleaned up

    const cleanupOnLoaded = useCallback(() => {
    if (buttonElement) {
    buttonElement.remove()
    }
    }, [buttonElement])

    Remark: Use this function for dev mode due to the useEffect’s caveats

Putting everything together

import { useRef, useCallback, useMemo } from 'react'
import { RPConfig, RPProvider, RPDefaultLayout, RPPages } from '@pdf-viewer/react'
export const AppPdfViewer = () => {
const ref = useRef(null)
// Create the button element.
const buttonElement = useMemo(() => {
const button = document.createElement('button')
button.innerHTML = 'N'
return button
}, [])
const handleLoaded = useCallback(() => {
// Get the element of React PDF.
const topBarRight = ref.current?.querySelector('[data-rp="topBarRight"]')
// Add the button element to the top bar.
topBarRight?.prepend(buttonElement)
}, [buttonElement])
// Remove the button element when the component is cleaned up.
const cleanupOnLoaded = useCallback(() => {
if (buttonElement) {
buttonElement.remove()
}
}, [buttonElement])
return (
<RPConfig licenseKey="YOUR_LICENSE_KEY">
<RPProvider src="https://cdn.codewithmosh.com/image/upload/v1721763853/guides/web-roadmap.pdf">
<RPDefaultLayout ref={ref} onLoaded={handleLoaded} cleanupOnLoaded={cleanupOnLoaded}>
<RPPages />
</RPDefaultLayout>
</RPProvider>
</RPConfig>
)
}
An image of how React PDF displays with customized topRightBar element

Select moreOptionsDropdown Element

Because More Options dropdown is not visible by default, you will need to use MutationObserver API to monitor changes of a specific DOM element.

An example: Accessing moreOptionsDropdown Element to Prepend a Button

  1. Define Mutation Observer Configuration

    const config = {
    attributes: false,
    childList: true,
    subtree: false
    }
    let observer
  2. Attach a Button to the Dropdown using Observer

    const handleMoreOptionsMount = useCallback(
    (elemContainer) => {
    const observerCallback = () => {
    const moreOptions = elemContainer.querySelector('[data-rp="moreOptionsDropdown"]')
    if (moreOptions) {
    moreOptions?.prepend(buttonElement)
    }
    }
    observer = new MutationObserver(observerCallback)
    observer.observe(elemContainer, config)
    },
    [buttonElement]
    )
  3. Cleanup the Observer on Unmount

    useEffect(() => {
    return () => observer?.disconnect()
    }, [])

Putting everything together

import { useRef, useCallback, useMemo, useEffect } from 'react'
import { RPConfig, RPProvider, RPDefaultLayout, RPPages } from '@pdf-viewer/react'
// Options for the Observer
const config = {
attributes: false,
childList: true,
subtree: false
}
let observer
export const AppPdfViewer = () => {
const ref = useRef(null)
// Create the button element
const buttonElement = useMemo(() => {
const button = document.createElement('button')
button.innerHTML = 'N'
return button
}, [])
const handleMoreOptionsMount = useCallback(
(elemContainer) => {
const observerCallback = () => {
const moreOptions = elemContainer.querySelector('[data-rp="moreOptionsDropdown"]')
if (moreOptions) {
moreOptions?.prepend(buttonElement)
}
}
observer = new MutationObserver(observerCallback)
observer.observe(elemContainer, config)
},
[buttonElement]
)
const handleLoaded = useCallback(() => {
const elemContainer = ref.current?.querySelector('[data-rp="container"]')
if (elemContainer) {
handleMoreOptionsMount(elemContainer)
}
}, [handleMoreOptionsMount])
// Remove the button element when the component is cleaned up
const cleanupOnLoaded = useCallback(() => {
if (buttonElement) {
buttonElement.remove()
}
}, [buttonElement])
// Cleanup the Observer on Unmount
useEffect(() => {
return () => observer?.disconnect()
}, [])
return (
<RPConfig licenseKey="YOUR_LICENSE_KEY">
<RPProvider src="https://cdn.codewithmosh.com/image/upload/v1721763853/guides/web-roadmap.pdf">
<RPDefaultLayout ref={ref} onLoaded={handleLoaded} cleanupOnLoaded={cleanupOnLoaded}>
<RPPages />
</RPDefaultLayout>
</RPProvider>
</RPConfig>
)
}
An image of how React PDF displays with customized moreOptionsDropdown element