Repository navigation
finding(docs): the other two overlay menu pages have #6521's defect too — dropdown-menu.mdx and context-menu.mdx publish undeclared keys and hide children / shortcut #7073
Description
Filed unassigned by the os-dev seat while implementing #6521. Grading and domain:* are the triage seat's.
⛔ Deliberately not folded into #6521's PR. That card is fenced to overlay/menubar.mdx; its dispatch asked me to measure the sibling pages (to settle whether localizing the interface name is a house convention) and I found this while doing so. Filed rather than fixed, per the same split ruling that produced #7072.
The defect
#6521 corrected overlay/menubar.mdx's ## Schema block to the surface MenuItem actually declares. The other two pages that document the same union have the same class of error, and more of it. All three menu pages publish a locally-named mirror of MenuItem; two of them are still wrong.
Measured on origin/main 592acafbeed97c5aed81a18f4d848b6179d3c044.
content/docs/components/overlay/dropdown-menu.mdx — 4 wrong rows
| page today | authority | should be |
|---|---|---|
value?: string (:36) |
declared on neither arm — not MenuCommandItem (overlay.ts:363-400), not MenuDividerItem (overlay.ts:409-421); dropdown-menu.tsx reads no .value |
dropped |
variant?: 'default' or 'destructive' (:38) |
not declared anywhere on the menu types; the only variant in dropdown-menu.tsx is :130, on a button node inside defaultProps.trigger — a different object, not a menu item |
dropped |
| (absent) | shortcut?: string (overlay.ts:383, zod overlay.zod.ts:154), read at dropdown-menu.tsx:80 |
added |
| (absent) | children?: MenuItem[] (overlay.ts:387, zod :155), read at dropdown-menu.tsx:58,66 — draws a real submenu |
added |
content/docs/components/overlay/context-menu.mdx — 3 wrong rows
| page today | authority | should be |
|---|---|---|
value?: string (:33) |
same as above — undeclared on both arms, no .value read in context-menu.tsx |
dropped |
| (absent) | shortcut?: string, read at context-menu.tsx:78 |
added |
| (absent) | children?: MenuItem[], read at context-menu.tsx:56,64 |
added |
⭐ The renderers' own metadata already says the right thing
Both renderers register an items input whose description enumerates the command-item keys, and both enumerate them correctly:
dropdown-menu.tsx:125— "a command item { label, icon, shortcut, disabled, onClick, children: [] } or a divider { separator: true }"context-menu.tsx:117— "a command item { label, icon, shortcut, disabled, onClick, children } or a divider { separator: true }"
Neither names value. Neither names variant. Both name shortcut and children. ⇒ the shipped renderer metadata and the reference page beside it teach different key sets, and the metadata is the one that is right.
Why this matters more than a tidy-up
children and shortcut are not cosmetic omissions: both are declared capabilities with working runtime that these pages hide. An author reading overlay/dropdown-menu.mdx has no way to learn that dropdown menus draw nested submenus at all, or that an item can carry a keyboard shortcut. That is the reverse of the usual docs defect and strictly worse for an AI author, which will not emit a key the reference page does not list.
value is the forward direction, and #7072 measures what it cost: 21 catalog items author it, across exactly the three fixture families these three pages document. The pages are the producer (AGENTS.md #0.1).
Why nothing red covers it
Same reason as #6521: no gate parses a plaintext fence (#5250). check:doc-snippet-types only compiles ts/tsx/typescript fences (TS_FENCE_LANGUAGES, scripts/check-doc-snippet-types.mjs:317), and these blocks are plaintext — members of #5867's declared SHRINK-ONLY population.
Also seen on these pages, NOT measured further
context-menu.mdxpublishestrigger: ComponentSchemaas required;ContextMenuSchema.triggeris declared optional, andoverlay.ts's own doc comment records that divergence in as many words ("Declared OPTIONAL although the docs page shows it required", finding(types): 13 top-level schema keys that component renderers genuinely READ are declared by no shipped type — measured across all 76content/docs/componentspages #6150). Someone may already own this — checked only far enough to say it is a known, recorded mismatch rather than a new one.context-menu.mdxdoes not publishContextMenuSchema.children, which is declared required and which the same doc comment says no read site consumes.
Suggested repair
One docs-only PR over both pages, same shape as #6521's: drop the two undeclared rows, add the two hidden declared-and-read rows on each page. ⛔ Not "declare value/variant on MenuCommandItem" — #6523 narrowed this union deliberately.
Refs: #6521 (the same fix, on the third page) · #7072 (the fixtures these pages taught) · #6523 · #6326 · #5250 · #5867 · #6150.
Generated by Claude Code
Activity
[-]finding(docs): the other two overlay menu pages have #6521’s defect too — and publish undeclared keys and hide /[/-][+]finding(docs): the other two overlay menu pages have #6521's defect too — `dropdown-menu.mdx` and `context-menu.mdx` publish undeclared keys and hide `children` / `shortcut`[/+]claude commentedon Aug 31, 2026
Claiming this card.
session_013hfmP9hoMd3dJwTh85J4yBclaude/issue-7073-overlay-menu-docs(pushed, empty, before the first edit)origin/main592acafbeed97c5aed81a18f4d848b6179d3c044Scope as dispatched: one docs-only PR over
content/docs/components/overlay/dropdown-menu.mdxandcontent/docs/components/overlay/context-menu.mdx. Re-deriving every load-bearing fact againstorigin/mainbefore editing; the two "also seen, NOT measured further" items oncontext-menu.mdxget measured and then either fixed here or filed, per the discriminator that a doc row disagreeing with a declaration is in scope and a declaration that looks wrong is not.Not setting
assignees— the PM owns that field.Generated by Claude Code
Generated by Claude Code
claude commentedon Aug 31, 2026
os-dev-report
{ "issue": 7073, "status": "done", "branch": "claude/issue-7073-overlay-menu-docs", "pr": "https://github.com/objectstack-ai/objectui/pull/7084", "premise_still_valid": true, "summary": "Docs-only correction of the `## Schema` blocks on content/docs/components/overlay/dropdown-menu.mdx (4 rows: dropped undeclared `value` and `variant`, added declared-and-read `shortcut` and `children?: DropdownMenuItem[]`) and context-menu.mdx (4 rows: dropped `value`, added `shortcut` and `children?: ContextMenuItem[]`, and changed `trigger:` to `trigger?:`). The trigger row is the first of the card's two unmeasured items and it is in scope: the declaration is optional at overlay.ts:486 and zod/overlay.zod.ts:191, deliberately, dated (objectui#6150), pinned by undeclared-but-consumed-keys-6150.test.ts:113, and its own doc comment says in words that the docs page shows it required. Interface names stay localized and the `type` tombstone stays prose, per PR #7074's three measured conventions; the changeset is the empty-frontmatter form, which check-changeset-presence confirms on this diff (\"no changeset is owed\"). The `skip-changeset` label was deliberately NOT applied - it exists in this repo but no workflow or script reads it.", "tests": "Gate union re-run on the FINAL commit 1d5bb9197 (working tree clean), each verdict quoted from the gate's own printed line, exit codes captured by redirect-then-capture (never through a pipe). ALL GREEN: check:doc-fences EXIT=0 'every TypeScript block in 224 document(s) is fenced ts/tsx/typescript, except 80 declared file(s) carrying 90 block(s) ... (SHRINK-ONLY)'; check:doc-types EXIT=0 'Every documented component type is registered.'; docs:check-links EXIT=0 'Links are valid across 17 scan roots.'; check:control-bytes EXIT=0 'OK (scanned 5861 tracked text file(s); skipped 85 binary)'; check:docs-route-closure EXIT=0 'MEASURED_PAYLOAD is honest' + 'gauge: 1360 modules crawled from 149 route roots (145 MDX)'; check:skills-paths EXIT=0 'OK (95/96 stated path(s) resolve ...)'; check:shell-escape-residue EXIT=0 'OK (4/4 root(s) resolved ... content/docs: 185 file(s), 1067 fence(s) ... 0 occurrence(s) outside a fence)'; changeset:check EXIT=0 (fixed group + no-major); check-changeset-presence EXIT=0 'No source or published contract of a released package changed in this range, so no changeset is owed.'; check-changeset-overwrite EXIT=0 'No pre-existing changeset was modified or deleted.'. PLUS a control-byte self-scan beyond the gate: grep -naP over both pages and the changeset, no match. FENCE CENSUS (no gate parses a plaintext fence, so this is the only measurement of it): dropdown-menu.mdx 2 fence markers / 1 plaintext opener before AND after (:33,:57 -> :33,:57); context-menu.mdx 2 / 1 before AND after (:30,:51 -> :30,:52). No fence added, removed or relabelled - #5867's SHRINK-ONLY population unmoved. DECLARED NARROWINGS, stated as narrowings and not as passes: (1) check:doc-snippets exits 2, 'PRECONDITION NOT MET (exit 2) - The snippet program was NOT run: the packages it resolves against are not built'. Its own output says this is 'I could not run', not 'I ran and found errors'. Building the 21 package closures would not move its answer: its covered population is read from its own source, TS_FENCE_LANGUAGES = new Set(['ts','tsx','typescript']) at scripts/check-doc-snippet-types.mjs:317, acted on at :600 - this diff is entirely inside plaintext fences, moves zero fences, and changes no source or .d.ts. (2) eslint narrowed to the diff, with all three pieces of evidence: population read from eslint's own config (eslint.config.js:28 scopes the TS config to files: ['**/*.{ts,tsx}']); count read from --format json (2 results, errorCount 0 each, both 'File ignored because no matching configuration was supplied'); invariance for untouched files (diff has no .ts/.tsx/config file, no type-aware rule in play). No ablation was run - this is a docs-only diff with no runtime behaviour to mutate. No build/test lock was taken: no build or test suite was run, only light node doc gates.", "mcp_calls": "0 - the whole run used repo-scoped REST (probe returned HTTP 200 on first try); zero MCP GitHub calls. Channel note: REST search/issues is NOT available to this seat ('This GitHub API path is not available: sessions are bound to their configured repositories'), so the pre-filing dedup was done as ONE repo-scoped REST list call (open issues, sort=created desc, per_page=100, single page, no pagination - covering #6879..#7078) plus a local grep, rather than a search. No duplicate found; #7023 is a different card (AnyComponentSchema vs AnySchema). I also read #6150 directly by number to confirm nobody already owns the ContextMenuSchema.children question - it is closed and covers only undeclared-but-READ keys, the inverse class.", "open_questions": [], "out_of_scope_findings": [ "filed as #7080: ContextMenuSchema.children is declared REQUIRED (overlay.ts:471, zod/overlay.zod.ts:190) but zero read sites consume it and the only shipped catalog fixture (basic-context-menu.json) omits it - this is the card's second unmeasured item, and per the dispatch's discriminator a declaration that looks wrong is not mine to decide, so three options are laid out there (make optional / retire under ADR-0049 / give it a read site) and none chosen. It is also why context-menu.mdx deliberately still does not publish the key.", "filed as #7081: DropdownMenuSchema.trigger declares a single SchemaNode (overlay.ts:433) while its zod mirror (zod/overlay.zod.ts:176), its sibling ContextMenuSchema.trigger (overlay.ts:486) and its own shipped defaultProps (dropdown-menu.tsx:130, an array) all use the array form. zod-mirror-parity.test.ts asserts one direction only (mirror accepts everything TS declares), so a wider mirror sits in its blind spot.", "filed as #7082: six component pages publish trigger/content/action as `ComponentSchema` - a real but different shipped type (blocks.ts:388, the concrete type: 'component' block) - where the declaration is SchemaNode (base.ts:398). Four sibling overlay pages (tooltip, popover, drawer, dialog) already spell it SchemaNode, so the overlay family is split 4-to-5 on the name of one concept. Untouched in this PR for the same reason PR #7074 left the localized interface names alone." ] }Generated by Claude Code
Generated by Claude Code
fix(docs): alert-dialog and sheet publish trigger/content as optional
fix(docs): alert-dialog and sheet publish trigger/content as optional (…