UI Namespace - types for the slot-based UI customization API.
Overview
Every visible piece of the SDK UI is a slot - a named placeholder you can fully replace
with your own DOM, partially customize (header/body/footer sub-slots), or hide entirely.
Full replacement - a callback (getInstance, id) => SlotConfiguration that returns
render, onMount, and onUnmount. The SDK renders whatever DOM node render returns.
Sub-slot customization - an object { header?, body?, footer? } where each region
is its own callback. Regions you omit keep their default rendering.
The slot callback (getInstance, id, helpers) => { render, onMount?, onUnmount? }
is called once when the SDK prepares to render the component — treat its body as
the slot's initialization phase. Some slots, like loader and passwordPrompt,
can render before load() resolves, so getInstance() returns null until the
instance is available. render(params) is called on every re-render.
For most slots, onMount(id) fires once the SDK instance is available, so
getInstance() is guaranteed non-null inside it — making it the right place to
subscribe to instance events. onUnmount(id) fires once on teardown and is
guaranteed to run even when the instance never arrived and onMount was
skipped, so setup done in the callback body (timers, listeners) always has a
cleanup path; guard instance-dependent cleanup, as getInstance() may still be
null. loader and passwordPrompt keep raw mount timing because they can
mount and unmount entirely before an instance exists; getInstance() may return
null in their lifecycle hooks. Lifecycle hooks are not a place to query the DOM
node returned from render, because that node may not be inserted yet.
Reactive re-rendering
render is invoked once at mount, then again automatically when the SDK instance
becomes available. To re-invoke it on additional changes, call
helpers.requestUpdate() from async work, event handlers, lifecycle hooks, or
other imperative code (but not synchronously from within render).
Example
Full replacement - custom comment thread with lifecycle:
UI Namespace - types for the slot-based UI customization API.
Overview
Every visible piece of the SDK UI is a slot - a named placeholder you can fully replace with your own DOM, partially customize (header/body/footer sub-slots), or hide entirely.
Slots are organized by feature domain in UI.Configuration:
main(always-visible),contextual(mode-specific)actions,status,textMarkupInline,deleteConfirm,link,noteexitConfirm,downloadConfirm,cannotSavePrompt,fontMismatch,subsetFontcreate,list,digitalSigning,digitalStatuscreate,listcalibration,settingscontrols,viewpropertyEditorcontainer, plus dynamic custom sidebar panelscommentThread,search,documentEditor,attachmentPreview,passwordPrompt,reloadConfirm,aiAssistantloader(applies to all backend modes)Customization modes
Every slot accepts one of two forms:
(getInstance, id) => SlotConfigurationthat returnsrender,onMount, andonUnmount. The SDK renders whatever DOM noderenderreturns.{ header?, body?, footer? }where each region is its own callback. Regions you omit keep their default rendering.To hide a slot entirely, return
nullfromrender:Lifecycle
The slot callback
(getInstance, id, helpers) => { render, onMount?, onUnmount? }is called once when the SDK prepares to render the component — treat its body as the slot's initialization phase. Some slots, likeloaderandpasswordPrompt, can render beforeload()resolves, sogetInstance()returnsnulluntil the instance is available.render(params)is called on every re-render.For most slots,
onMount(id)fires once the SDK instance is available, sogetInstance()is guaranteed non-null inside it — making it the right place to subscribe to instance events.onUnmount(id)fires once on teardown and is guaranteed to run even when the instance never arrived andonMountwas skipped, so setup done in the callback body (timers, listeners) always has a cleanup path; guard instance-dependent cleanup, asgetInstance()may still benull.loaderandpasswordPromptkeep raw mount timing because they can mount and unmount entirely before an instance exists;getInstance()may returnnullin their lifecycle hooks. Lifecycle hooks are not a place to query the DOM node returned fromrender, because that node may not be inserted yet.Reactive re-rendering
renderis invoked once at mount, then again automatically when the SDK instance becomes available. To re-invoke it on additional changes, callhelpers.requestUpdate()from async work, event handlers, lifecycle hooks, or other imperative code (but not synchronously from withinrender).Example
Full replacement - custom comment thread with lifecycle:
Example
Sub-slot customization - add a banner above the search panel:
Example
Hide a slot entirely:
Example
Preset - hide everything, then selectively restore:
Example
Runtime update - switch between custom and default UI:
See