Skip to content

feat(examples): add configurable-toolbar Custom UI example (SD-2929)#3159

Open
caio-pizzol wants to merge 4 commits intomainfrom
caio/sd-2929-configurable-toolbar
Open

feat(examples): add configurable-toolbar Custom UI example (SD-2929)#3159
caio-pizzol wants to merge 4 commits intomainfrom
caio/sd-2929-configurable-toolbar

Conversation

@caio-pizzol
Copy link
Copy Markdown
Contributor

The smallest example that proves how to build your own toolbar with superdoc/ui. Three built-in command buttons (bold, italic, underline) wired per-id via ui.commands.<id>.observe(...), plus one custom command via ui.commands.register(...) on the same surface. Body-only fixture, no framework.

Linked from Custom UI > Toolbar and commands. Single concept per the examples rules in dx-comms/architecture/examples-and-demos.md: one custom toolbar, one registered custom command, no theming / comments / track changes / mode toggle.

The custom command (example.insertClause) reads the current selection target from ui.selection.getSnapshot().selectionTarget and inserts a fixed snippet via editor.doc.insert(...) at that target. getState disables the button when the editor isn't ready or there's no positional selection, so the toolbar reads consistently across built-ins and customs.

Verified: pnpm install; pnpm --filter superdoc build; pnpm exec tsc --noEmit clean; dev server boots on http://localhost:5173/. Manifest entry, README link, and custom-ui matrix in ci-examples.yml updated.

The smallest example that proves how to build your own toolbar with
superdoc/ui. Three built-in commands (bold, italic, underline) wired
per-id via ui.commands.<id>.observe, plus one custom command via
ui.commands.register on the same surface. Body-only fixture, no
framework.

Linked from the Custom UI > Toolbar and commands docs page. Single
concept per the examples rules: one custom toolbar, one registered
custom command, no theming, no comments, no track changes.
@caio-pizzol caio-pizzol requested a review from a team as a code owner May 5, 2026 14:43
@linear
Copy link
Copy Markdown

linear Bot commented May 5, 2026

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: db1ad57d8b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

id: 'example.insertClause',
execute: ({ superdoc: sd }) => {
const editor = sd?.activeEditor;
const target = ui.selection.getSnapshot().selectionTarget;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve selection before executing insertClause

execute reads ui.selection.getSnapshot().selectionTarget at click time, but clicking a toolbar button moves focus off the editor and can clear the live selection first; this is already modeled in create-super-doc-ui tests (ui.selection.capture survives a later selection clear). In that path target becomes null and Insert clause silently no-ops even though the button was enabled just before the click. Capture the target before focus shifts (e.g., pointerdown/mousedown with preventDefault) or otherwise preserve the selection used for execution.

Useful? React with 👍 / 👎.

@codecov-commenter
Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Inline links from toolbar-and-commands.mdx and custom-commands.mdx
pointing at examples/editor/custom-ui/configurable-toolbar/. Same
plain-link pattern used by the selection-capture link PR (#3143).

The example teaches both halves of the surface (built-in command
binding + ui.commands.register), so both docs pages get a callout.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 5, 2026

Clicking a toolbar button steals focus from the editor on mousedown,
which can collapse the live selection before the click handler runs.
For built-in commands the buttons could end up disabled mid-click; for
the custom Insert clause command, ui.selection.getSnapshot()
.selectionTarget would return null and the insert silently no-ops.

Add a mousedown preventDefault on every toolbar button to keep the
editor focused while the click is dispatched. Same trick the built-in
toolbar uses internally. Caught by the bot reviewer on #3159.
@caio-pizzol caio-pizzol self-assigned this May 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants