Uh oh!
There was an error while loading. Please reload this page.
fix(app-shell): draw real canvas chrome for renderable-but-unoffered block types - #6072
Merged
yinlianghui merged 1 commit intoAug 24, 2026
Merged
Conversation
…block types
`PageBlockCanvas` read each node's icon and colour tone from `BLOCK_TYPE_META`,
which is the palette's OFFER list ("what may an author drag in"). The canvas is
answering a different question ("what may an author already have in this page").
The two diverge for an alias pair: `record:discussion` and `record:chatter` are
one renderer under two names, so the palette advertises exactly one of them and
the other spelling — which renders perfectly — fell through to the unknown-block
box and the neutral `misc` grey.
`block-types.ts` now declares `BLOCK_RENDERER_ALIAS_GROUPS` and resolves display
chrome through `resolveBlockDisplayMeta()`, which falls back to an alias
sibling's entry. Keyed on renderer IDENTITY, not on "is excluded": the guard
test asserts every group member resolves through `ComponentRegistry` to the same
component, so exclusions that genuinely are not page blocks keep the generic
box. The palette offer list is unchanged — nothing became draggable.Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
This was referenced Aug 24, 2026
yinlianghui
marked this pull request as ready for review
August 24, 2026 15:53
Uh oh!
There was an error while loading. Please reload this page.
yinlianghui
deleted the
claude/issue-5837-canvas-icon-for-unoffered-types
branch
August 24, 2026 16:05
This was referenced Aug 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#5837
The gap
PageBlockCanvasdrew every node's icon and colour tone fromBLOCK_TYPE_META:BLOCK_TYPE_METAis the palette's offer list — it answers "what may an author drag in". The canvas is asking a different question — "what may an author already have in this page" — and one list was answering both.For most palette exclusions the two answers coincide and the generic box is the honest chrome. They diverge for an alias pair:
record:discussionandrecord:chatterare one renderer under two names, so the palette advertises exactly one of them to keep one entry per renderer, and the other spelling — which renders perfectly — gotUnknownBlockIconand the neutralmiscgrey where its twin one line above getsMessageSquareand the bluerecordtone.The change
block-types.tsgainsBLOCK_RENDERER_ALIAS_GROUPS— block types that are one renderer under several spellings — andresolveBlockDisplayMeta(type), which returns the palette entry when there is one and otherwise borrows an alias sibling's.resolveBlockToneroutes through it; the canvas reads it instead ofBLOCK_TYPE_META.Three properties this shape was chosen for:
canvas-display-meta.test.tsxasserts that against the realComponentRegistry(identity, not "both defined"). A fix keyed on exclusion would handelement:text_inputa friendly icon it has not earned.record:chatterand (as of the 17.1.0 pin) explicitly excludes the canonicalrecord:discussion— the pair is advertised under the alias #5495 moved it from the legacy alias to the canonical name). Every assertion derives the offered/unoffered split fromBLOCK_TYPE_META, and one test flips the catalogue outright to prove the resolver follows — a future flip cannot re-open this.BLOCK_TYPE_METAentry, which would breakblock-config.test.ts's "no type is both offered and excluded".BlockDisplayMetadeliberately carries onlyIcon+category, nolabel:blockLabel()never consulted the catalogue and author-visible naming is a separate decision. The gap is icon + tone only.Verification — all on
7114898f0Direction predicted before running: a page carrying the unoffered spelling must draw the same icon and tone as its offered twin, and reverting must turn those pins red.
pnpm --filter @object-ui/app-shell type-check(tsc --noEmit && tsc -p tsconfig.test.json)VERDICT command-exit 0pnpm exec vitest runon the four affected suitesTest Files 4 passed (4) / Tests 53 passed (53)eslint .inpackages/app-shell(whole package, plain, no--no-inline-config)node scripts/check-changeset-presence.mjsCounter-probe (a) — the hard constraint, run explicitly and quoted:
Counter-probe (b) — a genuinely non-page-content exclusion keeps the generic box:
an exclusion with no renderer twin keeps the generic boxcoverselement:text_input,element:record_picker,element:formandai:chat_window(all →resolveBlockDisplayMetaundefined, tonemisc), and the DOM probe assertselement:text_input's badge keeps the zincmiscclasses in the same render as the fixed pair.Counter-probe (c) — the offer list is unchanged:
the drag-in list is exactly the palette catalogue, nothing morederivesTYPES_BY_CATEGORYfromBLOCK_TYPE_METAand asserts noPALETTE_EXCLUSIONSkey is draggable;no alias-group member became offerableasserts it for the group members specifically.Reverse verification. Ablating the alias fallback out of
resolveBlockDisplayMeta(mutation proved on disk by grepping the injected text and, separately, the removed text; restore undertrap … EXIT INT TERMwith a cwd-independentgit -C … checkout HEAD --;git diff HEAD --statempty afterwards) turned exactly the four fix pins red and left both counter-probes green:No rebuild was needed for the ablation: the suite imports
../block-typesby relative path, so nodist/sits between the mutation and the run.Measured deltas from the card
isContainer, i.e. the node has child groups); a leaf node shows a live preview plus a type badge. For the discussion/chatter pair the user-visible symptom today is therefore the badge tone. The icon half is still fixed and pinned — the DOM icon probe uses container-shaped nodes to reach that branch.BLOCK_TYPE_META,resolveBlockToneand thePALETTE_EXCLUSIONSledger were re-derived on the merge-base (a1c41c516) after fix(console): trimhidden: truefields from the approvals drawer summary card #6031/refactor(app-shell): type RecordDetailView's confirm handler as the published ConfirmationHandler #6035: no delta from the card's quoted mechanism.PALETTE_EXCLUSIONSreason strings say "no renderer" for block types that do have registered renderers (element:text_input,element:record_picker). Ledger-text accuracy only, no behaviour — filed unassigned asPALETTE_EXCLUSIONSreasons say "no renderer" for two block types that do have registered renderers #6071 and deliberately not touched here.Follow-up
This takes the card's smaller shape. The honest larger shape — splitting the catalogue into a display meta table covering every type the canvas can encounter and a palette offer list subset — is more than an S card here:
BLOCK_TYPE_METAis an exhaustiveRecordkeyed by the wholeBlockTypeIdunion, and it is read by the Add-block picker, the config-panel coverage tests and the spec-derived palette tests, so the split moves that entire surface. The alias-group resolver closes the measured gap and gives that refactor a seam to grow from.Generated by Claude Code