Skip to main content
Surfaces let you show dialogs and floating overlays above the document. Use them for things like:
  • password prompts
  • find and replace
  • lightweight tools or inspectors
  • custom workflow dialogs
SuperDoc supports two surface modes:
  • dialog: modal, centered, blocks interaction behind it
  • floating: non-modal, pinned to the visible document area

When to configure surfaces up front

Most apps do not need any extra setup to use surfaces. If you are opening a surface directly with superdoc.openSurface(...), you can do that with a normal SuperDoc instance and no special config. Add modules.surfaces only when you want:
  • global defaults for dialogs or floating overlays
  • a central resolver for intent-based requests using kind
  • built-in surface behaviors such as opt-in find/replace or password prompt customization

Open a surface

superdoc.openSurface(request)

Open a dialog or floating surface above the document. Returns: SurfaceHandle
Object
required
Surface request
Provide either:
  • component or render for a direct surface request
  • kind for a resolver-based request
component and render are mutually exclusive.

Dialog example

Floating example

Close a surface

superdoc.closeSurface(id?)

Close a surface programmatically.
  • pass an id to close a specific surface
  • omit id to close the topmost active surface
  • if both are open, dialog closes before floating

Handle lifecycle

openSurface() returns a handle with:
  • id
  • mode
  • close(reason?)
  • result
handle.result always resolves. It does not reject for normal lifecycle events. Possible results:
  • { status: 'submitted', data }
  • { status: 'closed', reason }
  • { status: 'replaced', replacedBy }
  • { status: 'destroyed' }
There is one active dialog slot and one active floating slot. Opening a new surface in the same mode replaces the previous one.

Vue component content

For Vue consumers, component is the simplest path.
Your component receives:
  • surfaceId
  • mode
  • request
  • resolve(data?)
  • close(reason?)

React and other frameworks

For React, use render() and mount into the provided container.
This is the same pattern as external link popovers: SuperDoc owns the shell, and your app mounts content into the provided container.

Optional instantiation config

Add modules.surfaces only if you want shared defaults, a resolver, or built-in surface behaviors such as find/replace.
See the full list of available defaults in the configuration reference.

Resolver-based surfaces

Use a resolver when you want to open a surface by intent instead of passing a renderer each time.
There is no built-in surface registry yet. If you use kind, you must provide modules.surfaces.resolver.

Built-in Find and Replace

SuperDoc includes a built-in find/replace popover for editor-backed documents. It is disabled by default so existing apps can keep their own Cmd+F / Ctrl+F handling. When enabled, SuperDoc intercepts those shortcuts while focus is inside SuperDoc and opens the built-in UI. From shortcut handling, SuperDoc only steals Cmd+F / Ctrl+F when it can actually open a surface. If findReplace.resolver returns { type: 'none' }, or the config is invalid or throws, the browser’s native find remains active. Enable it via modules.surfaces.findReplace:

Text customization

Override any of the built-in labels and placeholders:

Find-only mode

Disable replace actions and keep only the find UI:
false | true | Object
default:"false"
Find/replace configuration. Disabled by default; set to true to enable the built-in UI, or pass an object to customize labels, disable replace actions, or replace the rendering.

Custom Vue component

Replace the built-in content with your own Vue component. Your component receives a findReplace prop with reactive state and actions:
Inside your component:

Custom render function (React, vanilla JS)

Use render for framework-agnostic mounting. The render function receives a FindReplaceRenderContext:
ctx exposes container, findReplace, resolve, close, surfaceId, and mode. ctx.findReplace exposes plain JavaScript getters/setters instead of Vue refs so non-Vue renderers can work with it directly.

Conditional resolver

Use resolver when your app wants to decide at runtime whether to use built-in, custom, external, or suppressed rendering. The resolver receives a read-only context with texts and replaceEnabled:
Resolution types: The resolver can coexist with component/render. If the resolver returns null or { type: 'default' }, the direct component/render is used. If neither is configured, the built-in popover renders. Precedence: resolver → component/render → built-in.

The findReplace handle

Custom Vue components receive findReplace as a Vue handle with refs/computed refs. External render functions receive ctx.findReplace with the same API surface, but mutable fields are exposed as plain JavaScript getters/setters and derived fields are plain getters.

{ type: 'none' } semantics

{ type: 'none' } means suppress SuperDoc’s find/replace surface for that open attempt. When find/replace is opened via Cmd+F / Ctrl+F, suppression falls back to the browser’s native find dialog instead of swallowing the shortcut.

Built-in password prompt

SuperDoc includes a built-in password dialog for encrypted DOCX files. Enabled by default. On wrong password, the dialog stays open and shows an error. On success, the document loads normally.
Set to false to disable:

Text customization

Override any of the built-in copy:
false | true | Object
default:"true"
Password prompt configuration. Enabled by default when omitted; set to false to disable.

Custom Vue component

Replace the built-in dialog content with your own Vue component. Your component receives a passwordPrompt prop with everything it needs:
Inside your component:

Custom render function (React, vanilla JS)

Use render for framework-agnostic mounting. The render function receives a PasswordPromptRenderContext:

Conditional resolver

Use resolver when you need per-document decisions. The resolver receives a read-only PasswordPromptContext (documentId, errorCode, texts) and returns a resolution:
Resolution types: The resolver can coexist with component/render. If the resolver returns null or { type: 'default' }, the direct component/render is used. If neither is configured, the built-in prompt renders. Precedence: resolver → component/render → built-in.

The passwordPrompt handle

Every custom UI (component or render) receives a passwordPrompt handle with this shape:

How actions work

Submit / unlock button:
  1. Call await passwordPrompt.attemptPassword(password)
  2. If { success: true }: call resolve() to close the dialog
  3. If { success: false, errorCode }: keep the dialog open, show your error state
resolve() with no arguments is sufficient. The password flow does not consume the resolved data. Cancel / dismiss button:
  • Call close('user-cancelled')
Other actions (forgot password, help links): app-owned. Keep the dialog open or close with a custom reason.
Do not set doc.password or increment editorMountNonce directly. Use passwordPrompt.attemptPassword(password): it handles the document mutation and remount internally.

{ type: 'none' } semantics

{ type: 'none' } means suppress SuperDoc’s password prompt. The resolver context does not expose attemptPassword, so none cannot be used to build a self-hosted modal that retries passwords through SuperDoc. Use this when your app handles passwords entirely outside SuperDoc: for example, pre-prompting before instantiation or server-side decryption. For global suppression, use passwordPrompt: false instead.

Relationship with the exception event

If passwordPrompt is disabled, encrypted files emit DOCX_PASSWORD_REQUIRED or DOCX_PASSWORD_INVALID on the exception event. Your app can handle password entry through that event instead. When passwordPrompt is enabled, recoverable encryption errors are intercepted by the password prompt flow. If the prompt renders successfully (built-in, custom, or external), the exception event is suppressed. If the prompt cannot render (resolver returned { type: 'none' }, invalid config, or resolver threw), the original exception event is re-emitted so your app can handle it.

Multi-document handling

When multiple encrypted documents are loaded, the password prompt queues one dialog at a time in FIFO order. After the user submits or cancels for one document, the next dialog appears.

Styling

Background, shadow, border radius, padding, and edge offset are all customizable via --sd-ui-surface-* and --sd-ui-floating-* CSS variables. Find/replace controls use --sd-ui-find-replace-*, and search highlight colors use --sd-ui-search-match-bg plus --sd-ui-search-match-active-bg. See the full token table in Custom themes.