# Open dialogs and floating surfaces

> Render application UI in SuperDoc-managed dialog and floating layers with explicit lifecycle outcomes.



Surfaces place application UI above the document without coupling it to Editor internals. Use a dialog for modal decisions and a floating surface for a non-modal tool or inspector.

```ts
import { SuperDoc } from 'superdoc';
import 'superdoc/style.css';

const superdoc = new SuperDoc({ selector: '#editor', document: '/contract.docx' });

export const confirmInEditor = async (message: string): Promise<boolean> => {
  const handle = superdoc.openSurface<{ confirmed: true }>({
    mode: 'dialog',
    title: 'Confirm action',
    render: ({ container, close, resolve }) => {
      const text = document.createElement('p');
      text.textContent = message;
      const cancel = document.createElement('button');
      cancel.type = 'button';
      cancel.textContent = 'Cancel';
      const confirm = document.createElement('button');
      confirm.type = 'button';
      confirm.textContent = 'Confirm';
      cancel.addEventListener('click', () => close('cancel'));
      confirm.addEventListener('click', () => resolve({ confirmed: true }));
      container.append(text, cancel, confirm);
    },
  });

  const outcome = await handle.result;
  return outcome.status === 'submitted' && outcome.data?.confirmed === true;
};

window.addEventListener('beforeunload', () => superdoc.destroy());

```

The `render()` callback receives an empty container plus `resolve()` and `close()` controls. Mount DOM, React, Vue, or another framework into that container and return cleanup for any framework root or listener that outlives the nodes themselves.

`handle.result` resolves for normal lifecycle outcomes. Check `status` before reading data: a surface can be submitted, closed, replaced by another surface in the same slot, or destroyed with the Editor. There is one active slot per mode.

Give every surface a visible `title`, `ariaLabel`, or `ariaLabelledBy`. Decide whether Escape, backdrop clicks, and outside pointer events should close it. These defaults affect interaction, not authorization or transaction safety.

Configure `modules.surfaces` only for shared defaults, intent resolution, or built-in surfaces such as find/replace and password prompts. Direct `openSurface()` calls do not require a resolver.
