> ## Documentation Index
> Fetch the complete documentation index at: https://superdoc-caio-pizzol-docs-ai-core-preset.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Build custom UI with SuperDoc

SuperDoc ships built-in UI for the toolbar, comments panel, and tracked-change review. When you need your own design system, your own layout, or your own workflow, `superdoc/ui` gives you the state and actions to drive it.

## The layer model

Three layers, each with one job:

| Layer                             | What it is                                                                       | When you reach for it              |
| --------------------------------- | -------------------------------------------------------------------------------- | ---------------------------------- |
| **Document API** (`editor.doc.*`) | Stateless request/response contract. Runs in the browser and on the server.      | Read or mutate document content.   |
| **`superdoc/ui`**                 | Browser-only UI controller. Subscriptions, viewport geometry, per-command state. | Bind your UI to live editor state. |
| **Built-in modules**              | Optional UI SuperDoc renders for you.                                            | You want SuperDoc's UI as-is.      |

The Document API mutates the document. `superdoc/ui` is what your UI subscribes to. Built-in modules are SuperDoc's own consumer of those layers. Turn them off when you're providing your own.

## What it looks like

```tsx theme={null}
import { useSuperDocCommand, useSuperDocUI } from 'superdoc/ui/react';

function BoldButton() {
  const ui = useSuperDocUI();
  const bold = useSuperDocCommand('bold');

  return (
    <button
      className={bold.active ? 'active' : ''}
      disabled={bold.disabled}
      onClick={() => ui?.commands.get('bold')?.execute()}
    >
      B
    </button>
  );
}
```

One hook. One button. Subscribes only to that command's state. Re-renders only when `bold` flips `active` or `disabled`.

## What's in this section

<CardGroup cols={2}>
  <Card title="React setup" icon="atom" href="/editor/custom-ui/react-setup">
    Provider, onReady, hooks. The scaffolding every page below builds on.
  </Card>

  <Card title="Toolbar and commands" icon="bold" href="/editor/custom-ui/toolbar-and-commands">
    Wire your buttons to bold, italic, lists, undo, redo, and every other built-in command.
  </Card>

  <Card title="Custom commands" icon="code" href="/editor/custom-ui/custom-commands">
    Register your own commands. Override built-ins. Drive AI actions, clause inserts, business logic.
  </Card>

  <Card title="Comments" icon="message-square" href="/editor/custom-ui/comments">
    Custom comments sidebar with the typed selection-capture flow.
  </Card>

  <Card title="Track changes" icon="circle-check" href="/editor/custom-ui/track-changes">
    Custom tracked-change review panel. Accept, reject, navigate.
  </Card>

  <Card title="Right-click menu" icon="mouse-pointer-click" href="/editor/custom-ui/context-menu">
    Custom context menu wired through `contextAt` and `getContextMenuItems(context)`.
  </Card>

  <Card title="Selection and viewport" icon="crosshair" href="/editor/custom-ui/selection-and-viewport">
    Read the selection. Scroll an entity into view. Capture and restore selections that survive focus changes. Resolve a click point to a caret.
  </Card>

  <Card title="Document control" icon="file-output" href="/editor/custom-ui/document-control">
    Switch between editing and suggesting. Export to DOCX. Replace the open file.
  </Card>
</CardGroup>

The [API reference](/editor/custom-ui/api-reference) lists every hook and handle in one place.

## Three surfaces, three subjects

Custom-UI apps tend to land on the same shape: a toolbar, a floating bubble menu, a right-click menu. Each one answers a different "what's the subject of this action?" question. Keep them strictly separated.

| Surface                      | Subject                | Belongs here                                                                                                                                                  |
| ---------------------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Toolbar**                  | The **document**       | Mode toggle, Export, Import, Undo / Redo. Persistent controls that don't depend on a selection or a click target.                                             |
| **Floating bubble menu**     | The **selection**      | Bold, Italic, Comment on selection. Format-on-selection actions where the user's eyes stay on the work.                                                       |
| **Right-click context menu** | The **clicked target** | Accept / Reject (on a tracked change), Resolve (on a comment), Copy / Comment (when the click is *inside* the selection), Insert clause here (on plain text). |

The controller surfaces this split directly. The toolbar reads `state.selection` to gate format buttons. The bubble menu anchors via `ui.selection.getAnchorRect({ placement: 'start' })`. The context menu opens against `ui.viewport.contextAt({ x, y })` and dispatches via `item.invoke()`. Same controller, same hooks, three jobs.

## Worked example

The [reference workspace on GitHub](https://github.com/superdoc-dev/superdoc/tree/main/demos/editor/custom-ui) ships a full app on these surfaces: toolbar, custom command with keyboard shortcut, floating bubble menu, right-click context menu, comments sidebar with reply threads, tracked-change review, selection capture / restore, DOCX export and reimport.
