Skip to content

finding(components): ui:menubar never reads an item's icon either — the third MenuItem-shaped container, and the one no census can see #6326

Description

@os-support-ai

Found while repairing #6278 (ui:context-menu's unread icon). Filed unassigned, out of that card's fence — #6278 is scoped to context-menu and its 裁决 explicitly forbids generalising the fix across containers.

What was measured, at ad54f7587

packages/components/src/renderers/overlay/menubar.tsx contains 0 references to icon (case-insensitive 0 as well).

That is not a shrug about a key nobody declared. MenubarMenu.items is typed as MenuItem[] — the same interface dropdown-menu and context-menu items use, and it declares icon?: string:

// packages/types/src/overlay.tsexportinterfaceMenubarMenu{label: string;items: MenuItem[];// <- MenuItem.icon?: string}

content/docs/components/overlay/menubar.mdx documents it too:

interface MenubarItem {
label?: string;
value?: string;
icon?: string;
...

The renderer has three places an item is drawn, and none of them reads the key:

<MenubarSubTrigger>{item.label}</MenubarSubTrigger>// submenu trigger{item.children.map((child,childIdx)=>(<MenubarItemkey={childIdx}>{child.label}</MenubarItem>// nested child))}<MenubarItemkey={itemIdx}disabled={item.disabled}>{item.label}</MenubarItem>// leaf

So ui:menubar is the third and last member of the MenuItem-shaped family, alongside the two already answered: dropdown-menu (repaired by #5930) and context-menu (repaired by #6278).

Why this one was invisible, and why that is the interesting part

#6278's table was built by enumerating authoredicon strings in the schema catalog and grouping them by nearest typed ancestor. examples/schema-catalog/src/schemas/components-overlay-menubar/application-menubar.json authors zeroicon keys, so menubar could never appear in that table — not because the renderer is fine, but because no fixture exercises the key.

The same blind spot applies downstream: scripts/check-lucide-icon-record-names.mjs has no 'menubar' census entry, and even if one were added, its min non-vacuity precondition would (correctly) fail, because the descent reaches nothing. A gate that judges authored names cannot see a documented key that nothing authors.

That makes this a declared-but-unread key of the #4632 / #4652 / #4721 class, not the "fixture draws the wrong thing" class — the failure is silent in both directions: an author following the published MenubarItem shape gets no glyph and no error, and no gate reports anything.

Not addressed here, and not addressed by

The open question, stated but not answered

Whichever way #5931 is decided for its three containers probably decides this one too: either MenuItem.icon is honoured everywhere it is typed and documented (route through resolveIcon, the RECORD surface, as #5930 ruled), or the key is removed from the surfaces that do not read it. Filed as a finding rather than pm:queue for exactly that reason — it should follow #5931's answer, not pre-empt it.

Incidentally, the nested-child arm above also renders only one level deep and drops disabled, unlike the sibling renderers' recursion. Noted, not investigated.

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpm:blocked

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions