feat(admin): allow trusted plugins to add editor panels#2187
Conversation
🦋 Changeset detectedLatest commit: 28139f7 The changes in this PR will be included in the next version bump. This PR includes changesets to release 17 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Scope checkThis PR changes 548 lines across 10 files. Large PRs are harder to review and more likely to be closed without review. If this scope is intentional, no action needed. A maintainer will review it. If not, please consider splitting this into smaller PRs. See CONTRIBUTING.md for contribution guidelines. |
@emdash-cms/admin
@emdash-cms/auth
@emdash-cms/auth-atproto
@emdash-cms/blocks
@emdash-cms/cloudflare
@emdash-cms/contentful-to-portable-text
emdash
create-emdash
@emdash-cms/gutenberg-to-portable-text
@emdash-cms/plugin-cli
@emdash-cms/plugin-types
@emdash-cms/registry-client
@emdash-cms/registry-lexicons
@emdash-cms/registry-verification
@emdash-cms/sandbox-workerd
@emdash-cms/x402
@emdash-cms/plugin-ai-moderation
@emdash-cms/plugin-atproto
@emdash-cms/plugin-audit-log
@emdash-cms/plugin-color
@emdash-cms/plugin-embeds
@emdash-cms/plugin-field-kit
@emdash-cms/plugin-forms
@emdash-cms/plugin-webhook-notifier
commit: |
There was a problem hiding this comment.
The change is a focused, well-scoped feature that fits EmDash's trusted-plugin model: it adds a contentEditorPanels export contract, resolves/filters panels using PluginAdminContext and the admin manifest, renders them in host-owned settings-sidebar sections, and isolates failures with a React error boundary. The implementation is clean, focused tests and docs are present, and the changeset is appropriate.
One process note: the PR checklist item "New features link to an approved Discussion" is left unchecked even though the description links to Discussion #2105. That box should be ticked, or the approval status confirmed, before merge per the feature PR policy.
One code finding: the new error boundary's retry button is a raw <button> despite the AGENTS.md rule to use Kumo components. It mirrors the existing PluginFieldErrorBoundary pattern, but new code should migrate to Kumo Button instead. Otherwise the changed files are in good shape and the new conventions (Lingui wrapping, RTL-safe logical classes, manifest lifecycle filtering) are followed.
| <button | ||
| type="button" | ||
| className="mt-1 text-xs font-medium text-kumo-brand underline" | ||
| onClick={() => this.setState({ hasError: false })} | ||
| > | ||
| <Trans>Retry</Trans> | ||
| </button> |
There was a problem hiding this comment.
[suggestion] The fallback UI uses a raw <button> with hand-rolled Tailwind classes (text-kumo-brand underline). AGENTS.md requires using Kumo components rather than custom buttons so the control gets Kumo focus rings, sizing, and dark-mode/RTL behavior for free. Import Button from @cloudflare/kumo and use it here (and, separately, migrate the identical pattern in the pre-existing PluginFieldErrorBoundary).
| <button | |
| type="button" | |
| className="mt-1 text-xs font-medium text-kumo-brand underline" | |
| onClick={() => this.setState({ hasError: false })} | |
| > | |
| <Trans>Retry</Trans> | |
| </button> | |
| <Button | |
| type="button" | |
| variant="ghost" | |
| size="sm" | |
| className="mt-1" | |
| onClick={() => this.setState({ hasError: false })} | |
| > | |
| <Trans>Retry</Trans> | |
| </Button> |
Overlapping PRsThis PR modifies files that are also changed by other open PRs:
This may cause merge conflicts or duplicated work. A maintainer will coordinate. |
There was a problem hiding this comment.
The feature is a focused, well-scoped extension that fits EmDash's trusted-plugin model: it adds a contentEditorPanels export contract, resolves/filters panels via PluginAdminContext and the admin manifest, renders them in host-owned settings-sidebar sections, and isolates failures with a React error boundary. The approach is right for the problem.
Status of prior findings:
- ✅ The previous Kumo
Buttonfinding is resolved —ContentEditorPanelBoundarynow imports and usesButtonfrom@cloudflare/kumoinstead of a raw<button>. ⚠️ The process note from the last review remains: the PR checklist item "New features link to an approved Discussion" is still unchecked. The description links to Discussion #2105, but per the feature PR policy the box should be ticked (or the approval status explicitly confirmed) before merge.
What I checked:
- Panel contract, validation, manifest lifecycle filtering, collection/role filtering, deterministic ordering, and render-error recovery in
packages/admin/src/lib/content-editor-panels.tsx. - Integration into
ContentSettingsPaneland themanifestpass-through fromContentEditor. - RTL/Tailwind classes, Lingui wrapping, Kumo component use, and comment discipline against
AGENTS.md. - Test coverage in
ContentSettingsPanel.test.tsxand the newcontent-editor-panels.test.tsx. - Changeset quality and documentation in
react-admin.mdx. - No changes touch server routes, SQL, content-table queries, or logged-out query counts.
Headline conclusion: The implementation is clean, the new tests and docs are appropriate, and the changeset is user-facing. No code defects were found. Once the Discussion checkbox is confirmed/ticked, this is ready to merge.
c090a03 to
28139f7
Compare
What does this PR do?
Adds a focused
contentEditorPanelsextension contract for trusted React plugins. Plugins can contribute host-framed panels to the saved-entry settings sidebar while EmDash retains layout ownership, collection and role filtering, disabled-plugin lifecycle handling, deterministic ordering, and render-error isolation.New entries keep the native editor unchanged. A failing contribution cannot take down the editor.
Discussion: #2105
Type of change
Checklist
pnpm typecheckpassespnpm lintpassespnpm testpasses (or targeted tests for my change)pnpm formathas been runmessages.pochanges except in translation PRs - a workflow extracts catalogs on merge tomain.Screenshots / test output
pnpm typecheckpnpm lint- 0 warnings, 0 errorspnpm format