Uh oh!
There was an error while loading. Please reload this page.
docs(components): follow the shipped MenuItem union on the menubar Schema block - #7074
Conversation
…hema block
The `## Schema` block published `value?: string`, which neither arm of the
shipped union declares and no menu renderer reads, and omitted
`children?: MenuItem[]`, which is declared and which the menubar renderer draws
as a real submenu. `menus` was taught as required; it is declared optional and
the renderer optional-chains it.
The `## Dividers` prose picks up the `type` tombstone sentence the two sibling
menu pages already carry, so all three say the same thing about the retired
`{ "type": "separator" }` spelling being a parse-time refusal rather than a
silent strip.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hfmP9hoMd3dJwTh85J4yBos-sam
commented
Aug 31, 2026
Dispatching seat review ( ⭐ The changeset: my order was wrong, this PR is rightMy order said "Ship The right call, and flagged as a deviation rather than quietly taken. I carried the "ship Deliverable 4 (interface names) — measurement accepted, ruling acceptedI asked for a measurement, not a preference, and got one. Independently confirmed on Three of three localize. The |
Uh oh!
There was an error while loading. Please reload this page.
Closes#6521
Docs only, publishes nothing. Three rows of
content/docs/components/overlay/menubar.mdx's## Schemablock did not describe the surfacepackages/types/src/overlay.tsdeclares, plus one prose alignment. Verified againstorigin/main592acafbeed97c5aed81a18f4d848b6179d3c044; local gate union re-run on the final commit00d0cdab5.The card's six-row "actually shipped" evidence table was measured at
50f987f9a, beforeMenuItembecame a discriminated union. Four of its rows are already satisfied onmainand are not in this diff:592acafbelabelpublished as requiredMenuCommandItem.label: string,overlay.ts:367)shortcut?: string, notstring[]overlay.ts:383)separator: true, nottype?: 'separator'MenuDividerItem(overlay.ts:409-421)A reviewer holding the stale card should reconcile against this table rather than the card's.
What this diff actually changes
value?: stringMenuCommandItem(overlay.ts:363-400), notMenuDividerItem(overlay.ts:409-421); mirrored absent in zod (overlay.zod.ts:147-168). No menu renderer reads a.value— zero occurrences acrossmenubar.tsx,dropdown-menu.tsx,context-menu.tsx.children?: MenuItem[]—overlay.ts:387, zodoverlay.zod.ts:155. Read, and it draws a real submenu:menubar.tsx:35-39branchesitem.childrenintoMenubarSub/MenubarSubTrigger/MenubarSubContent.children?: MenubarItem[];addedmenus: MenubarMenu[](required)menus?: MenubarMenu[]—overlay.ts:511,.optional()atoverlay.zod.ts:208. The renderer optional-chains it (menubar.tsx:28,schema.menus?.map), so a menubar with nomenusis legal today.menus?: MenubarMenu[];## Dividersprose ended at "Author a divider as{ "separator": true }."typeis tombstoned?: neveron both arms (overlay.ts:400,:420) and carriesretirementTombstone()guidance in zod (overlay.zod.ts:158-162) — authoring it is a parse-time refusal, not a strip.dropdown-menu.mdxandcontext-menu.mdxalready carry, verbatimchildrenis the row that matters: a declared capability with working runtime that the page hid outright, so an author reading this page had no way to learn menubar draws submenus at all.Deliverable 3 — the card's open question is false, and I did not act on it
The card asks whether the page should keep teaching
shortcut, on the stated ground that "the menubar renderer never reads it".⛔ That premise does not hold on
main.packages/components/src/renderers/overlay/menubar.tsxreads it in both arms of its recursion:The code comment at
:70-73records why, and dates it: "Parity, not new capability (objectui#6523 rider): the declaredshortcutstring already has working runtime in dropdown-menu and context-menu; menubar read it nowhere." So the renderer gap the card describes was real when the card was written and was closed by #6523.⇒
shortcutstays documented with no renderer caveat. Writing the caveat the card asks for would have installed inverse drift — publishing a limitation that does not exist.Deliverable 4 — ruling on the interface names: leave them localized, and this is a measurement
The page names its interfaces
MenubarCommandItem/MenubarDividerItem/MenubarItemwhile the shipped names areMenuCommandItem/MenuDividerItem/MenuItem. Before deciding, I read the two sibling pages that document the same union:overlay/dropdown-menu.mdxDropdownMenuCommandItem/DropdownMenuDividerItem/DropdownMenuItemoverlay/context-menu.mdxContextMenuCommandItem/ContextMenuDividerItem/ContextMenuItemoverlay/menubar.mdxMenubarCommandItem/MenubarDividerItem/MenubarItemThree of three localize the name. Not one of them publishes the shared
MenuItemname. ⇒ this is a house convention,menubar.mdxis not the outlier, and renaming it here would have made it the only page out of step. Names untouched.(The card's title — "publishes an invented
MenubarIteminterface" — is therefore only half live: the invented shape was the defect, and #6523 plus this PR close it. The name is deliberate house style.)Deliverable — ruling on
separator?: falseandtype?: never: not in the fence; the why goes in the proseSame measurement decides it. Neither sibling page publishes
separator?: falseortype?: neverin itsplaintextblock. Both instead carry the refusal as prose, in## Dividers, with its reason and its issue number. That is the house's answer to "where does a tombstone get taught", and it is the better one: a baretype?: neverrow in a teaching block tells a reader nothing, whereas the sentence says what happens and why.So: the block stays free of union mechanics, and
menubar.mdx's## Dividerspicks up the sibling sentence so all three pages now say the same thing. This is the one edit here that is not one of the card's three rows; it is the same defect class (page under-teaching the shipped contract), mechanical, and its correct form is fixed verbatim by two sibling pages.Deliverable 5 — the split, filed
value, a key no arm of the shippedMenuItemunion declares and no menu renderer reads #7072 — the 21 catalog items authoringvalue, counts re-measured on592acafbeand unchanged from the card (menubar 11, context-menu 4, dropdown-menu 3 + 3). Not touched here, per the dispatch's split ruling.dropdown-menu.mdxandcontext-menu.mdxpublish undeclared keys and hidechildren/shortcut#7073 — ⭐ found while doing the sibling-page measurement above:dropdown-menu.mdxandcontext-menu.mdxhave this same defect and more of it. Both publish the undeclaredvalue;dropdown-menu.mdxalso publishes an undeclaredvariant; and both hidechildrenandshortcut, which are declared and read (dropdown-menu.tsx:58,66,80;context-menu.tsx:56,64,78). Filed rather than folded in, for the same reason finding(examples): 21 catalog menu items authorvalue, a key no arm of the shippedMenuItemunion declares and no menu renderer reads #7072 was.Verification
content/docs/**is not published source —apps/siteisprivate: true— socheck-changeset-presencereports "no changeset is owed". The changeset therefore uses the empty frontmatter form, which that gate documents as counting and which is what PR #6345 used for its docs-only edit to this same file.patch": apatchbump would have been a false claim that a released package changed.majorwas never in play.Gate union re-run on the final commit
00d0cdab5, each verdict quoted from the gate's own output:check:doc-fences✅ every TypeScript block in 224 document(s) is fenced ts/tsx/typescript, except 80 declared file(s) carrying 90 block(s)— the SHRINK-ONLY population is unmovedcheck:doc-types✅ Every documented component type is registered.docs:check-linksLinks are valid across 17 scan roots.check:control-bytes✅ check-control-bytes: OK (scanned 5861 tracked text file(s); skipped 85 binary).check:docs-route-closure✅ MEASURED_PAYLOAD is honest+✅ gauge: 1360 modules crawled from 149 route rootscheck:skills-paths✅ OK (95/96 stated path(s) resolve across 18 guide file(s); 1 baselined).check:shell-escape-residue✅ OK (content/docs: 185 file(s), 1067 fence(s)... 0 occurrence(s) outside a fence)changeset:check(fixed)✅ All workspace packages are in the changeset fixed group.changeset:check(no-major)✅ No changeset declares a `major` bump.check-changeset-presence✅ No source or published contract of a released package changed in this range, so no changeset is owed.check-changeset-overwrite✅ No pre-existing changeset was modified or deleted.Fence census on the edited file, before and after: 2 fence markers, 1
plaintextopener. Unchanged.Declared narrowings — two gates were NOT run, and neither can see this diff
Stated as narrowings rather than passes, because "not run" and "green" must stay distinguishable.
check:doc-snippetsexits 2 here (PRECONDITION NOT MET — the packages it resolves against are not built); building the 21 package closures it names would not change its answer. Its covered population is read from its own source, not guessed:TS_FENCE_LANGUAGES = new Set(['ts', 'tsx', 'typescript'])(scripts/check-doc-snippet-types.mjs:317), acted on at:600. This diff lives entirely inside aplaintextfence and adds, removes and relabels zero fences (census above). It changes no source and no.d.ts, so no untouched document's verdict can move either.eslint—eslint.config.js:28scopes the TypeScript config tofiles: ['**/*.{ts,tsx}']. This diff contains no.tsor.tsxfile. Read from the config, not assumed.check:readme-exportsalso hit the unbuilt precondition; its own census reports its population as "43 tracked README(s) underpackages/", and this diff touches no README.CI runs the full farm regardless.
Generated by Claude Code