Repository navigation
fix(components): ui:menubar draws an item's authored icon on every arm, at any depth (objectui#6326) - #10246
Merged
objectstack-fleet[bot] merged 2 commits intoSep 24, 2026
Conversation
…m, at any depth (objectui#6326) MenubarMenu.items is MenuItem[], which declares icon?: string, but the menubar renderer never read the key. Resolve it through resolveIcon (the lucide RECORD surface, as objectui#5930 / #6278 ruled for the two sibling menus) on the leaf, submenu-trigger and submenu-child arms. The item walk is now a local recursion, so a submenu child carrying its own children is drawn as a nested submenu instead of a leaf that drops them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LkCKMa5bvrw3L4ezcNXEXW
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
|
objectstack-fleet
Bot
deleted the
claude/issue-6326-menubar-item-icon
branch
September 24, 2026 13:54
This was referenced Sep 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 free
to 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 #6326
What changed
ui:menubarnow draws an item's authoredicon.MenubarMenu.itemsis typedMenuItem[], andMenuItemdeclaresicon?: string(the component docs list it too), butpackages/components/src/renderers/overlay/menubar.tsxnever read the key:git grep -n -i iconon that file returned 0 lines at basea78cd378c. Controls on the same pathspec:labelreturned 10 anddisabledreturned 2.resolveIcon, the lucide RECORD surface. This is the shape objectui#5930 ruled fordropdown-menuand objectui#6278 carried tocontext-menu.LazyIconis not used.ui:dropdown-menurenders an item's authorediconas raw TEXT — the catalog fixture named with-icons.json draws the words "edit", "copy", "trash" beside its labels #5930 ruled that repairing only the leaf is "a narrower version of the same bug".renderMenubarItems, in this file only). The old renderer walked exactly one level. A submenu child that had its ownchildrenwas drawn as a plain leaf, so those children were never shown, even thoughMenuItem.childrenis recursive by type and the docs describe it as "drawn as a nested submenu". The card's triage said this incidental rides the fix if the answer is "honour".content/docs/components/overlay/menubar.mdxgains an## Iconssection, with the same wording as the context-menu page..changeset/6326-menubar-item-icon.md, for@object-ui/components.⛔ Not touched:
dropdown-menu.tsxandcontext-menu.tsx. objectui#6278's ruling forbids generalising across containers, and objectui#6327 (consolidating the three recursions) is on hold. No published type or accepted shape changed (Clause-② no).Premise checks (at base
a78cd378c)icon? No. finding(components):button-groupimplements no selection, and never wires the per-buttononClick/disabledit declares — the catalog authors 29 keys nothing reads #7077's ruling (comment 5534409692) coversbutton-grouponly: "icondisposition on this component = delete". It namesmenubaronly as a sibling in thedisabled/onClickwiring convention. Catalog fixtures declare childiconkeys that button-group, breadcrumb and command never read — two of them are named with-icons.json and render none #5931's last comment points thebutton-groupicon third at finding(components):button-groupimplements no selection, and never wires the per-buttononClick/disabledit declares — the catalog authors 29 keys nothing reads #7077. finding(components): three near-identical menu-item recursions inrenderers/overlay/— the same icon bug has now been repaired in two of them separately #6327 has zero comments. finding(components):ui:context-menunever reads an item's authoredicon— dropdown-menu's identical twin, left behind by #5930 #6278's ruling is scoped tocontext-menu.disabled? The card's note said the nested-child arm dropsdisabled. That is no longer true: the objectui#6346 rider already forwardsdisabled={child.disabled}. The one-level-deep half was true, and this PR repairs it.Evidence
New suite
packages/components/src/__tests__/menubar-item-icon.test.tsxhas 10 rows, with lucide not mocked. Glyphs are asserted by the identity lucide gives them,svg.lucide-NAME, derived from the authored name. The submenu trigger's always-present chevron is asserted as a positive control on the instrument. A retired spelling (edit) must draw no glyph.Tests 5 failed | 5 passed (10). The five failures are the leaf, submenu-trigger, submenu-child, depth-2 trigger and grandchild rows. The harness, retired-spelling and chevron-control rows stayed green.Tests 10 passed (10).3dd2a7b. Each mutation was checked on disk (marker count 1, remaining icon renders 1) and restored undertrap … EXIT INT TERMusinggit checkout HEAD --. After each restore, the blob hash matched HEAD andgit diff HEADhad 0 lines.dist/is in the path.pnpm exec vitest run packages/components/(from repo root, on3dd2a7b):Test Files 287 passed (287) / Tests 2787 passed (2787). The merge oforigin/mainthat followed touched zero files underpackages/components/.6d7e1e7:component-fixture-declared-keys,menu-item-unionandcheck-handler-key-read-sites.turbo run type-check --filter=@object-ui/components: 9/9 successful.tsc -p tsconfig.test.json --listFilesincludes both the renderer and the new test.eslint .pass: 503 files judged by--format json, 0 errors, both changed files present. Lint is not type-aware (noprojectService/projectineslint.config.js), so this diff cannot change the lint verdict for any untouched file.check-changeset-presence,-claims,-no-major,-fixed,-overwrite,vi-mock-specifiers/-inherit/-override-shape,test-path-roots,control-bytes,lucide-icon-record-names,doc-fence-languages,doc-links,doc-example-ids,doc-component-types,handler-key-read-sites,doc-example-types,doc-snippet-types(672 of 672 block(s) judged, 0 failed, after building its 35-task prerequisite),new-cross-file-line-citationsanddoc-example-shared-reader.Acceptance notes
application-menubar.jsonstill authors noicon. No census entry was added tocheck-lucide-icon-record-names.mjsformenubar: with no authored name, itsminnon-vacuity rule would fail by design. The renderer is pinned by the suite above.disabled(MenubarSubTrigger/ContextMenuSubTrigger/DropdownMenuSubTriggerget nodisabledprop). This was read from source and not probed at runtime, so it is not filed as a defect. The carrier is objectui#6327, which would touch all three copies.Session:
https://claude.ai/code/session_01LkCKMa5bvrw3L4ezcNXEXWGenerated by Claude Code