Skip to content

feat(examples): vanilla custom UI toolbar example (SD-2929)#3128

Closed
caio-pizzol wants to merge 2 commits intomainfrom
caio/sd-2929-vanilla-custom-ui-toolbar
Closed

feat(examples): vanilla custom UI toolbar example (SD-2929)#3128
caio-pizzol wants to merge 2 commits intomainfrom
caio/sd-2929-vanilla-custom-ui-toolbar

Conversation

@caio-pizzol
Copy link
Copy Markdown
Contributor

First focused minimal example under `examples/editor/custom-ui/`. Single file, ~99 lines, demonstrates the cleaned-up controller surface from SD-2917 / SD-2918 / SD-2919 / SD-2920:

  • No cast on `createSuperDocUI({ superdoc })`.
  • `ui.createScope()` for lifecycle. `ui.destroy()` cascades.
  • Per-command `observe(state => ...)` so each button only re-renders when its own command flips.
  • `BUILT_IN_COMMAND_IDS` + `ui.commands.has(id)` + `ui.commands.require(id)` validate a config-driven button list.
  • One custom command via `scope.register(...)`, auto-unregistered on scope teardown.

Also threads `PublicToolbarItemId` through the public `superdoc/ui` sub-entry. SD-2920 exposed `BUILT_IN_COMMAND_IDS` at runtime but missed the derived type, so consumers had to dip into `superdoc/headless-toolbar` to type a config array. Fixed.

Verified: `pnpm --filter superdoc build` clean; `tsc --noEmit` clean in the new example.

@linear
Copy link
Copy Markdown

linear Bot commented May 4, 2026

First focused minimal example under examples/editor/custom-ui/.
Single file (~99 lines) demonstrating the cleaned-up controller
surface from SD-2917 / SD-2918 / SD-2919 / SD-2920:

- createSuperDocUI({ superdoc }) accepts the SuperDoc instance
  directly. No cast.
- ui.createScope() collects every subscription, custom command
  registration, and DOM listener; ui.destroy() cascades into every
  scope so consumers tear everything down with one call.
- Per-command observe(state => ...) so each button only re-renders
  when its own command flips, matching the React useSuperDocCommand
  pattern.
- BUILT_IN_COMMAND_IDS, ui.commands.has(id), and ui.commands.require(id)
  validate a config-driven button list at startup so a typo cannot
  ship silently.
- One custom command via scope.register(...), auto-unregistered on
  scope teardown.

Also surfaced and fixed: PublicToolbarItemId was added to the runtime
exports of superdoc/ui (SD-2920) but never re-exported as a type from
the public sub-entry. This commit threads it through
super-editor/src/ui/index.ts and superdoc/src/ui.d.ts so consumers
can type their config arrays without dipping into the
headless-toolbar entry.

Wired into examples/manifest.json and a new custom-ui CI smoke job.
Stacked on caio/sd-2928-examples-demos-reorg until #3127 merges.
…d pnpm-setup to custom-ui CI

The earlier change in this PR added `type PublicToolbarItemId` to
the consumer-facing `superdoc/ui` re-export list (packages/superdoc/
src/ui.d.ts) but never landed the corresponding source export in the
inner barrel at packages/super-editor/src/ui/index.ts. With
`skipLibCheck: true`, TypeScript silently masked the broken
re-export; consumers writing `import type { PublicToolbarItemId }
from 'superdoc/ui'` would still pass typecheck against the dist but
would fail without skipLibCheck (and would not actually resolve to
the typed union when chased through). Add the missing source export
so the chain is real.

The new custom-ui CI matrix job restores the workspace cache and
invokes the smoke test, but does not run pnpm/action-setup. The
example's package.json predev hook calls `pnpm --filter superdoc
build`, and the playwright config falls back to `pnpm --dir <example>
run dev` when the example has no local node_modules (pnpm-hoisted
layout). Both require pnpm on PATH. Add pnpm setup so the smoke test
can launch its dev server.
@caio-pizzol caio-pizzol force-pushed the caio/sd-2929-vanilla-custom-ui-toolbar branch from 8267653 to 567d5db Compare May 4, 2026 23:42
@caio-pizzol caio-pizzol closed this May 4, 2026
@codecov-commenter
Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@caio-pizzol
Copy link
Copy Markdown
Contributor Author

Closing this for now after the Custom UI examples audit. We're going to keep examples docs-driven and concept-shaped, not surface-shaped. The next Custom UI examples should be focused vanilla examples linked from specific docs pages: selection-capture/vanilla first, then possibly configurable-toolbar/vanilla. Track changes stays inline / demo-only for now. Keeping the branch around for cherry-picking if useful.

The PublicToolbarItemId re-export fix that lived on this stack has been split out as #3135 so it can land independent of the examples conversation.

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