Skip to content

Customize the UI ​

The viewer and the editor come with their whole UI: a toolbar and a ribbon, side panels, page controls and dialogs. You can choose which parts show and what people can do, restyle it to match your app, change its words, and add elements of your own over the pages.

Choose what shows ​

The options create takes decide which parts of the UI show:

ts
import { UDocViewer } from "@docmentis/udoc-viewer";

// A reading pane: the thumbnails open, the page controls in the status bar,
// and no search, comments, print, download or theme button.
const viewer = await UDocViewer.create(document.getElementById("udoc")!, {
    theme: "system",
    activePanel: "thumbnail",
    showRightPanel: false,
    showPrintButton: false,
    showDownloadButton: false,
    showThemeButton: false,
    viewControlsPlacement: "status-bar",
});
await viewer.open("https://example.com/report.pdf");
OptionWhat it shows
showToolbarThe toolbar, and the ribbon under it.
showLeftPanel, showRightPanelThe left side panel (thumbnails, outline, layers) and the right one (search, comments).
showThumbnailPanel, showOutlinePanel, showLayersPanel, showSearchPanel, showCommentsPanelOne panel each. A document shows only the panels its type has: the outline, layers and comments are a PDF's.
activePanelThe panel open at the start. openPanel() and closePanel() change it later.
showPrintButton, showDownloadButton, showThemeButton, showFullscreenButtonThe items of the toolbar's menu.
showDeveloperButtonA Developer item in the menu, with the performance counter. Off by default.
viewControlsPlacementWhere page navigation and zoom go: "floating" over the pages, "top-toolbar" or "status-bar". setViewControlsPlacement() moves them later.
showNotesPanelA deck's speaker notes, open under its slides at the start.
showFormulaBarA workbook's formula bar.
showLoadingOverlay, hideAttributionThe overlay that shows while a document opens, and the "Powered by docMentis" mark. Only a license can turn these off.

Every show… option is on by default except showDeveloperButton and showNotesPanel. The options without a call to change them, such as showToolbar, are fixed once the viewer is created. UDocOptions lists every option with its default.

Choose what people can do ​

OptionWhat it does
enableCopy: falseText can be selected, but not copied, in view mode.
enableAnnotation: falseA PDF's annotations and comments can be read but not added, changed or deleted, and the Annotate tab is gone. Your own calls, such as addPageAnnotation, still change them.
enableFormFilling: falseA PDF's form shows as it is filled in, and can't be changed.
onLinkClickReceives the URL of a link people click, in place of opening it in a new tab: to confirm it first, say, or open it elsewhere.

The editor adds options for its modes:

ts
import { UDocEditor } from "@docmentis/udoc-editor";

// Opens in view mode, with the switch to edit mode, and without the controls
// edit mode shows beside each page.
const editor = await UDocEditor.create(document.getElementById("udoc")!, {
    initialMode: "view",
    showPageControls: false,
});
await editor.open("https://example.com/report.docx");

initialMode is the mode it opens in, "edit" by default. allowedModes limits the modes people can switch between, and the mode switch shows only when there's more than one, unless showModeSwitch: false hides it. showPageControls: false drops the controls edit mode shows beside and between pages, and showRuler: false the ruler. UDocEditorOptions has them all.

Theme ​

The UI has a light and a dark theme. The theme option picks one, or "system" to follow the operating system's, and setTheme() changes it later. People can switch it themselves from the toolbar's menu, unless you set showThemeButton: false.

Colors ​

Every color the UI uses is a CSS variable. Set them on .udoc-ui-root, the element the UI puts in your container; the dark theme adds the class udoc-ui-dark to it. The defaults have no specificity, so your rules win whatever order the stylesheets load in.

The UI is neutral gray, with one hue: --udoc-color-primary, which colors focus rings, selected controls, switches and filled buttons. To give it your brand's, set it for each theme:

css
.udoc-ui-root {
    --udoc-color-primary: #4f46e5;
    --udoc-color-on-primary: #ffffff;
}

.udoc-ui-root.udoc-ui-dark {
    --udoc-color-primary: #a5b4fc;
    --udoc-color-on-primary: #1e1b4b;
}

If your app runs one theme, set one value and pin the theme with the theme option. Set the variables on .udoc-ui-root itself, not on an element inside it: the hover and selected colors are worked out there.

Style the UI through these variables. A rule that reaches into it by its class names depends on how it's built inside, which can change from one release to the next.

Color roles ​

The roles every part of the UI paints from:

VariablePaintsLightDark
--udoc-color-surfaceThe area around the pages#e6e6e6#181818
--udoc-color-surface-containerThe toolbar, the ribbon, the panels and the status bar#f3f3f3#252525
--udoc-color-surface-container-highCards in a panel, and what floats over the pages#f9f9f9#2c2c2c
--udoc-color-surface-container-highestMenus and dialogs#ffffff#333333
--udoc-color-on-surfaceText and icons#1f1f1f#e8e8e8
--udoc-color-on-surface-variantSecondary text: labels, dates, placeholders#5f5f5f#a8a8a8
--udoc-color-outlineThe borders of fields#7f7f7f#808080
--udoc-color-outline-variantDividers, frames and the page border#cccccc#444444
--udoc-color-primaryFocus, selection, switches and filled buttons#2b2b2b#e0e0e0
--udoc-color-on-primaryText and icons on the primary color#ffffff#1b1b1b
--udoc-color-errorErrors and destructive actions#c62828#f28b82
--udoc-color-on-errorText and icons on the error color#ffffff#5c1410
--udoc-color-scrimThe backdrop behind a dialog50% black70% black

A lighter surface stands higher, in both themes: the area around the pages lowest, the chrome above it, and menus and dialogs on top.

Regions ​

Each region of the UI takes its fill from a variable of its own, so you can set one apart without changing the rest:

VariableRegionDefault
--udoc-toolbar-backgroundThe toolbar--udoc-color-surface-container
--udoc-ribbon-backgroundThe ribbon--udoc-color-surface-container
--udoc-panel-backgroundThe side panels--udoc-color-surface-container
--udoc-status-bar-backgroundThe status bar--udoc-color-surface-container
--udoc-canvas-backgroundThe area around the pages, and the gaps between them--udoc-color-surface
--udoc-canvas-guide-backgroundThe ruler, and a spreadsheet's row and column headers--udoc-color-surface-container
--udoc-canvas-scrollbar-backgroundThe scrollbars' tracks--udoc-color-surface-container

Marks on the page ​

What the UI draws over a page has colors of its own, which read against anything a page holds, whatever your primary color is:

VariableMarks
--udoc-canvas-selectionThe selection, its handles and its tint
--udoc-canvas-hoverThe annotation under the pointer
--udoc-canvas-search, --udoc-canvas-search-activeSearch matches, and the current one
--udoc-canvas-marquee and its -fillA selection drawn by dragging
--udoc-scrollbar-thumb, --udoc-scrollbar-thumb-hoverThe scrollbars' thumbs

States ​

A control's hover, pressed, selected and disabled looks are opacities: --udoc-state-hover-opacity (6%), --udoc-state-pressed-opacity (12%) and --udoc-state-selected-opacity (14%) of its color, and --udoc-state-disabled-opacity (38%) for a disabled control.

Words ​

The UI speaks English, Simplified and Traditional Chinese, Japanese, Korean, Spanish, French, German, Brazilian Portuguese, Arabic and Russian. It follows the browser's language unless the locale option names one, such as "zh-CN". A language it doesn't ship falls back to one in the same language and script, then to English.

The translations option replaces any of its strings by key, to use your own wording or to supply a language it doesn't ship:

ts
import { UDocViewer } from "@docmentis/udoc-viewer";

const viewer = await UDocViewer.create(document.getElementById("udoc")!, {
    translations: {
        "toolbar.download": "Save a copy",
        "toolbar.print": "Print pages",
    },
});
await viewer.open("https://example.com/report.pdf");

Messages lists the keys. The editor adds those of edit mode, in its own Messages.

Draw over the pages ​

setOverlay(id, source) adds elements of your own over the pages: a button, a badge, a marker. They follow the pages as the view scrolls and zooms.

ts
import { UDocViewer } from "@docmentis/udoc-viewer";

const viewer = await UDocViewer.create(document.getElementById("udoc")!);
await viewer.open("https://example.com/report.pdf");

// A button beside each page on screen, which follows it as the view scrolls
// and zooms.
viewer.setOverlay("comment-buttons", (frame) =>
    frame.views.map((view) => ({
        key: `comment:${view.index}`,
        x: view.x + view.width + 8,
        y: view.y,
        create: () => {
            const button = document.createElement("button");
            button.textContent = "Comment";
            // The overlay layer lets the pointer through to the page; the
            // button takes it back.
            button.style.pointerEvents = "auto";
            return button;
        },
        update: (button) => {
            button.onclick = () => openComments(view.index);
        },
    })),
);

function openComments(page: number): void {
    console.log(`Comments on page ${page + 1}`);
}

The source is called each time the view is painted, with the frame: the pages on screen, each with its index and its box in CSS pixels, and the scale from document points to CSS pixels. It returns an item for each element to show:

  • key names the element from one frame to the next, so the same key moves the same element rather than making a new one. An element whose key is no longer returned, as when its page scrolls away, is removed.
  • x and y are where the element's top-left corner goes, in CSS pixels. Set scale to have it grow and shrink with the zoom.
  • create() makes the element the first time its key appears, and update() refreshes it on every frame.

The source runs on every frame, so keep it quick, and work out everything from the frame it's given. The layer lets the pointer through to the page, so an element that takes clicks sets pointer-events: auto. In a workbook, the frame's sheet says which sheet its pages are on.

removeOverlay(id) removes an overlay. The UI's own elements over the pages are overlays too, under ids that start with udoc:, so you can remove one, such as udoc:annotation-bar, the bar over a selected annotation, and draw your own in its place. Pass { aboveSelection: true } to setOverlay to draw above the selection's handles, as that bar does.