useSuperDocCommand(id) subscribes one button to one command. The component re-renders when that command flips active or disabled, never on every editor change. ui.commands.get(id)?.execute(payload?) runs the command.
A single button
A row of buttons
Build a static config and map. Each<ToolbarButton> subscribes to its own command, so unrelated state changes don’t re-render the row.
disabled / active straight from the controller.
Commands with payloads
Some commands take a value. Pass it toexecute().
What the hook returns
useSuperDocCommand returns a fallback { active: false, disabled: true, source: 'built-in' } while the editor is initializing, so your buttons render disabled with no flicker.
Built-in command ids
Common ids you’ll wire to buttons:PublicToolbarItemId in superdoc/ui is the source of truth. Anything you can pass to createHeadlessToolbar({ commands }) works as a useSuperDocCommand id.
Aggregate snapshots
Need every command in one render pass (e.g. you generate the toolbar from the active context)? Subscribe to the whole toolbar slice.useSuperDocCommand per button when you can. useSuperDocToolbar re-renders on any command change.
Trade-offs
- The hook subscribes per-id. Reusing a button component with different ids is fine: the subscription resets when
idchanges. - Built-in command state is derived from the active editor. If your provider sits above multiple editors, the ids you pass are scoped to whichever editor reported ready last.
- Custom commands you registered with
ui.commands.registerwork with the same hook.

