Nutrient Web SDK

ReferenceUIConfiguration

Interface Configuration

UI Customization configuration.

Use this to customize various components of the SDK's user interface.

Interface

Example

Fully replace the comment thread UI:

NutrientViewer.load({
// ... Your configuration.
ui: {
commentThread: (getInstance, id) => ({
render: (params) => {
// Return a DOM Node
const div = document.createElement("div");
div.innerText = `This is a custom UI for the comment thread: ${id}`;

return div;
},
}),
},
});

Customize a slot within comment thread:

NutrientViewer.load({
// ... Your configuration.
ui: {
commentThread: {
header: () => {
return {
render: () => {
const div = document.createElement("div");
div.style.backgroundColor = "lightgreen";
div.style.padding = "5px";
div.innerText = "This is a custom header for the comment thread.";

return div;
},
};
},
},
},
});

See Also

Properties

aiAssistant

Optional

AI Assistant panel — the conversational AI interface for document queries and actions. Return null from render to hide it entirely.

annotations

Optional
{ … }

Annotations — slots for viewing, selecting, and managing annotations.

Includes: actions (selected annotation actions), status (read-only indicator), textMarkupInline (text selection markup), deleteConfirm, link (link editor), note (note popup).

PropertyDescription
actions

Customize or hide the actions for selected annotations.

Note: This slot replaces customization previously done via annotationTooltipCallback. Use getInstance()?.getSelectedAnnotations() to access the selected annotation(s).

deleteConfirm

Customize or hide the delete annotation confirmation. Set autoResolve: "accept" to delete immediately without the prompt, or autoResolve: "reject" to always cancel.

link

Customize or hide the link annotation editor (shown when interacting with a link annotation).

note

Customize or hide the note annotation expanded view.

Note: This controls the popup showing the note's text content - not the note indicator icon on the canvas. The popup's appearance is determined by the PDF reader (per PDF spec §12.5.6.4), making it UI that customers may want to customize.

status

Customize or hide the locked/read-only annotation status indicator (shown when hovering locked or read-only annotations).

textMarkupInline

Customize or hide the text markup inline toolbar (toolbar shown when text is selected for markup).

Example

Custom actions toolbar for selected annotations:

NutrientViewer.load({
ui: {
annotations: {
actions: (getInstance, id) => ({
render: () => {
const bar = document.createElement("div");
const deleteBtn = document.createElement("button");
deleteBtn.textContent = "Delete";
deleteBtn.onclick = async () => {
const instance = getInstance();
const selected = instance?.getSelectedAnnotations();
if (selected?.size) await instance?.delete(selected.first().id);
};
bar.appendChild(deleteBtn);
return bar;
},
}),
},
},
});

See Also

Attachment preview — displays embedded file attachments. Return null from render to hide it entirely.

Replace the entire comment thread component UI with a custom implementation by passing a function. Or customize it partly by passing an object configuration.

The UI customization function is invoked when the SDK is ready to render a comment thread.

Example

Fully replace the comment thread UI:

NutrientViewer.load({
// ... Your configuration.
ui: {
commentThread: (getInstance, id) => ({
render: (params) => {
// Return a DOM Node
const div = document.createElement("div");
div.innerText = `This is a custom UI for the comment thread: ${id}`;

return div;
},
}),
},
});

Customize the header slot within comment thread:

NutrientViewer.load({
// ... Your configuration.
ui: {
commentThread: {
header: () => {
return {
render: () => {
const div = document.createElement("div");
div.style.backgroundColor = "lightgreen";
div.style.padding = "5px";
div.innerText = "This is a custom header for the comment thread.";

return div;
},
};
},
},
},
});

See Also

{ … }

Content editor — confirmations and warnings during content editing sessions.

Includes: exitConfirm, downloadConfirm, cannotSavePrompt, fontMismatch, subsetFont.

Use getInstance()?.saveContentEditingSession() and getInstance()?.discardContentEditingSession() to control content editing programmatically from custom UI.

PropertyDescription
cannotSavePrompt

Customize or hide the "cannot save changes" prompt (shown when the content editor cannot save).

This is an informational notice, not a yes/no confirmation, so it does not support autoResolve. Returning null from render hides the prompt and keeps the editor open; to discard the failed session programmatically call getInstance()?.discardContentEditingSession().

downloadConfirm

Customize or hide the download document confirmation (shown when downloading during content editing). Set autoResolve: "accept" to download automatically; autoResolve: "reject" dismisses it without downloading.

exitConfirm

Customize or hide the exit content editor confirmation (shown when leaving content editor with unsaved changes). Set autoResolve: "accept" to save and exit automatically; autoResolve: "reject" keeps the editor open.

fontMismatch

Customize or hide the font mismatch warning (shown when a font used in the document is not available).

subsetFont

Customize or hide the subset font warning (shown when a font is only partially embedded).

{ controls?: BaseSlot; view?: BaseSlot }

Document comparison — controls and diff view for comparing documents.

PropertyDescription
controls

Customize or hide the document comparison controls (source tabs, diff mode toggles, exit button).

view

Customize or hide the document comparison diff view.

Document editor — full-page management UI (reorder, rotate, delete, add pages).

Pass a function to fully replace, or an object with { toolbar?, body?, footer? } sub-slots.

Example

Add a custom footer to the document editor:

NutrientViewer.load({
ui: {
documentEditor: {
footer: (getInstance, id) => ({
render: () => {
const footer = document.createElement("div");
const saveBtn = document.createElement("button");
saveBtn.textContent = "Save & Close";
saveBtn.onclick = () => getInstance()?.setViewState(v => v.set("interactionMode", null));
footer.appendChild(saveBtn);
return footer;
},
}),
},
},
});

formCreator

Optional
{ propertyEditor?: BaseSlot }

Form creator — form field design tools.

Currently contains propertyEditor — the form field property editor shown when a form field is selected in designer mode.

PropertyDescription
propertyEditor

Customize or hide the form field property editor (shown when a form field is selected in form designer mode). Configure field name, type, validation, and appearance.

loader

Optional
SlotConfigurationCallback<{ id: string }> | { type: "progress" | "skeleton" }

Loader — the loading UI shown while the document is connecting.

The default is a skeleton placeholder matching the viewer layout.

Pass an options object with type to override the default, or a slot callback for full replacement. Because the loader renders while the document is still connecting, getInstance() may return null. Its lifecycle hooks use raw mount timing and can run before an instance exists. Use this slot for loading UI only.

  • { type: 'skeleton' } — skeleton placeholder matching the viewer layout.
  • { type: 'progress' } — progress indicator (spinner / progress bar).
  • (getInstance, id) => SlotConfiguration — fully replace the loader with custom DOM.
  • (getInstance, id) => ({ render: () => null }) — hide the loader entirely.

Example

Use the progress indicator:

NutrientViewer.load({
ui: {
loader: { type: 'progress' },
},
});

Fully custom loader:

NutrientViewer.load({
ui: {
loader: (getInstance, id) => ({
render: () => {
const div = document.createElement("div");
div.innerText = "Loading your document...";
div.style.display = "flex";
div.style.alignItems = "center";
div.style.justifyContent = "center";
div.style.height = "100%";
return div;
},
}),
},
});

measurements

Optional
{ calibration?: BaseSlot; settings?: BaseSlot }

Measurements — scale calibration and measurement display settings.

PropertyDescription
calibration

Customize or hide the scale calibration UI (set reference distance for measurement annotations).

settings

Customize or hide the measurement settings (precision, unit, snapping options).

Password prompt — shown when opening a password-protected document.

This slot uses raw mount lifecycle timing because it renders before the document is unlocked. getInstance() may return null in its lifecycle hooks.

Example

Custom password prompt:

NutrientViewer.load({
ui: {
passwordPrompt: (getInstance, id) => ({
render: () => {
const form = document.createElement("div");
const input = document.createElement("input");
input.type = "password";
input.placeholder = "Enter document password";
form.appendChild(input);
return form;
},
}),
},
});

preset

Optional
"minimal"

Apply a named UI preset as a baseline configuration.

  • 'minimal' - hides all UI components, leaving only the bare page canvas. Individual slot overrides specified alongside preset take precedence, so you can selectively restore specific components on top of the preset.

The preset key is resolved at load time (and when calling instance.setUI()) and is not stored in the SDK state - the result is always a plain slot configuration.

Example

Canvas-only in one line:

NutrientViewer.load({
ui: { preset: 'minimal' },
});

Canvas-only but keep custom tools:

NutrientViewer.load({
ui: {
preset: 'minimal',
tools: {
main: (getInstance, id) => ({
render: (params) => {
const div = document.createElement('div');
div.innerText = 'Custom tools';
return div;
},
}),
},
},
});

Apply a preset at runtime:

instance.setUI({ preset: 'minimal' });
// Reset to full UI:
instance.setUI({});

Reload document confirmation — shown when the document needs to be reloaded. Set autoResolve: "accept" to reload automatically, or autoResolve: "reject" to keep the current document, both without showing the prompt.

signatures

Optional
{ … }

Signatures — electronic signature creation/selection and digital signature verification.

Electronic signatures (create, list) are drawn/typed signatures applied as annotations. Digital signatures (digitalSigning, digitalStatus) are cryptographic signatures with certificates.

PropertyDescription
create

Customize or hide the electronic signature creation view (draw, type, or upload a signature).

digitalSigning

Customize or hide the digital signing flow (cryptographic signing with certificates).

digitalStatus

Customize or hide the digital signature validation status (certificate chain, integrity, timestamp).

list

Customize or hide the saved electronic signatures list (pick from previously stored signatures).

stamps

Optional
{ create?: BaseSlot; list?: BaseSlot }

Stamps — stamp creation and stamp template selection.

  • create — custom stamp creation view.
  • list — stamp picker showing available templates.
PropertyDescription
create

Customize or hide the custom stamp creation view.

list

Customize or hide the stamp selection list / picker (shows available stamp templates).

See Also

tools

Optional
{ contextual?: BaseSlot; main?: BaseSlot }

Tools — the primary and contextual tool surfaces.

  • main — always-visible tools (zoom, page navigation, mode switching, etc.)
  • contextual — mode-specific tools (annotation properties, content editor bar, form designer, etc.)
PropertyDescription
contextual

Customize or hide the contextual (mode-specific) tools - shown when entering annotations, content editor, form creator, etc. Also displays annotation properties when an annotation is selected. Return null from render to hide it entirely.

main

Customize or hide the main (always-visible) tools - zoom, page navigation, mode switching, etc. Return null from render to hide it entirely.

Example

Hide the main tools, keep contextual:

NutrientViewer.load({
ui: {
tools: {
main: (getInstance, id) => ({ render: () => null }),
},
},
});

Replace the main tools with a minimal custom bar:

NutrientViewer.load({
ui: {
tools: {
main: (getInstance, id) => ({
render: () => {
const bar = document.createElement("div");
bar.style.cssText = "display:flex;gap:8px;padding:8px;background:#1a1a1a;";
["Prev", "Next"].forEach((label, i) => {
const btn = document.createElement("button");
btn.textContent = label;
btn.onclick = () => {
const instance = getInstance();
const page = instance?.viewState.currentPageIndex ?? 0;
instance?.setViewState(v => v.set("currentPageIndex", page + (i === 0 ? -1 : 1)));
};
bar.appendChild(btn);
});
return bar;
},
}),
},
},
});

See Also