Skip to content

The menu renderers read an undeclared item.onSelect, while the declared MenuItem.onClick is read by nothing #6346

Description

@os-warren

Surfaced while implementing objectui#6132 (PR #6345). Not fixed there: that card ruled a docs question, and this is a code-side contract question whose fix lands in packages/.

What was measured

objectui#6132's ruling redirects three menu reference pages at MenuItem.onClick, on the grounds that it is a real declared slot. It is — I verified it in three places before doing the redirect:

  • source packages/types/src/overlay.ts:346onClick?: () => void;
  • built packages/types/dist/overlay.d.ts:334 — the exact line objectui#6132 cited
  • Zod mirror packages/types/src/zod/overlay.zod.ts:136onClick: z.function().optional().describe('Click handler')

But no renderer reads it. The renderers read a different, undeclared key on the same item:

// packages/components/src/renderers/overlay/dropdown-menu.tsx:67<DropdownMenuItemkey={i}disabled={item.disabled}inset={item.inset}onSelect={item.onSelect}>
// packages/components/src/renderers/overlay/context-menu.tsx:65
<ContextMenuItemkey={i}disabled={item.disabled}inset={item.inset}onSelect={item.onSelect}>

packages/components/src/renderers/overlay/menubar.tsx wires no item handler at all — neither spelling.

Neither onSelect nor inset is declared on MenuItem. The helper is typed renderMenuItems(items: any[]), which is why the mismatch type-checks.

Confirming the negative:

$ grep -rn "onClick" packages/components/src/renderers/overlay/*.tsx(no matches)

Why it matters

Declared and enforced disagree in both directions on the same object:

  • an author following the shipped type writes onClick — it validates, it publishes, and it never fires;
  • an author who gets a working menu wrote onSelect — which no type declares, so nothing protects it from being renamed away.

This is the failure mode objectui#6132's own four-axis analysis called the most expensive one ("能通过校验、能发布、然后静默什么都不做"), except here it survives because the prop is declared, so it reads as correct.

Note this is a thirdMenuItem-shaped defect in the same family as objectui#6326 and objectui#6278 (both about an item's icon), and unlike those it is about the handler rather than the glyph.

The decision this needs

Which spelling is the contract?

I have no recommendation strong enough to skip triage — B matches observed runtime behaviour, A matches the published declaration, and the choice depends on whether any authored onSelect exists in the wild. Worth measuring before ruling.

⚠️ Whichever way this goes, PR #6345's three doc pages (overlay/context-menu.mdx, overlay/dropdown-menu.mdx, overlay/menubar.mdx) name onClick and would need the same correction under option B.

Refs: objectui#6132 · PR #6345 · objectui#6326 · objectui#6278 · objectui#4453.


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatneeds-user-decision

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions