Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.superdoc.dev/llms.txt

Use this file to discover all available pages before exploring further.

Framework-agnostic patterns built on createHeadlessToolbar(). Pick the one closest to your stack.
On React? Reach for Custom UI › Toolbar and commands instead. The typed React surface (useSuperDocCommand, ui.commands.register) re-renders one button per command, ships with selection / comments / track-changes hooks, and works with any design system (shadcn, MUI, Mantine, Tailwind). The headless examples below are for non-React stacks.

Vue + Vuetify

Vertical sidebar panel. Navigation drawer with expansion panels grouping related controls. Stack: Vue 3, Vuetify 3, Material Design Icons
<v-navigation-drawer permanent width="260">
  <v-expansion-panels>
    <v-expansion-panel title="Text">
      <template #text>
        <v-btn-toggle v-model="activeFormats" multiple>
          <v-btn icon="mdi-format-bold" @click="execute('bold')" />
          <v-btn icon="mdi-format-italic" @click="execute('italic')" />
          <v-btn icon="mdi-format-underline" @click="execute('underline')" />
        </v-btn-toggle>

        <v-select
          label="Font size"
          :items="fontSizes"
          @update:model-value="v => execute('font-size', v)"
        />
      </template>
    </v-expansion-panel>
  </v-expansion-panels>
</v-navigation-drawer>

Full source

Vue + Vuetify example

Svelte + Tailwind

Fixed bottom bar. Compact, mobile-inspired layout with Svelte 5 runes for reactivity. Stack: Svelte 5, Tailwind CSS, Lucide Svelte
<script>
  let snapshot = $state(toolbar.getSnapshot());

  $effect(() => {
    return toolbar.subscribe(({ snapshot: s }) => {
      snapshot = s;
    });
  });
</script>

<div class="fixed bottom-0 inset-x-0 flex items-center gap-1 px-3 h-12 bg-white border-t">
  <button
    class:active={snapshot.commands.bold?.active}
    onclick={() => toolbar.execute('bold')}
  >
    <Bold size={16} />
  </button>
  <button
    class:active={snapshot.commands.italic?.active}
    onclick={() => toolbar.execute('italic')}
  >
    <Italic size={16} />
  </button>
</div>

Full source

Svelte + Tailwind example

Vanilla JS

Zero-framework proof. Plain buttons, native selects, DOM manipulation. No build step required. Stack: No framework, plain HTML/CSS/JS, Lucide
// Sync button states from toolbar snapshot
toolbar.subscribe(({ snapshot }) => {
  for (const btn of document.querySelectorAll('[data-cmd]')) {
    const cmd = snapshot.commands[btn.dataset.cmd];
    btn.classList.toggle('active', cmd?.active);
    btn.disabled = cmd?.disabled;
  }
});

// Single event listener via delegation
document.querySelector('#toolbar').addEventListener('click', (e) => {
  const cmd = e.target.closest('[data-cmd]')?.dataset.cmd;
  if (cmd) toolbar.execute(cmd);
});
<!-- Markup -->
<div id="toolbar">
  <button data-cmd="bold"><b>B</b></button>
  <button data-cmd="italic"><i>I</i></button>
  <button data-cmd="underline"><u>U</u></button>
</div>

Full source

Vanilla JS example

Running the examples

cd examples/advanced/headless-toolbar/<example-name>
pnpm install
pnpm dev
Replace <example-name> with vue-vuetify, svelte-shadcn, or vanilla.

Next steps

Custom UI (React)

The recommended path for React apps. Typed hooks, custom commands, selection-aware buttons.

Headless toolbar API reference

Full command table, snapshot shape, and helper utilities.