Skip to content

fix(ui): keep the icon gallery renderable when icons.tsx exports a non-component - #2559

Closed
ARE404 wants to merge 1 commit into
apache:mainfrom
ARE404:are404/fix-icons-story
Closed

fix(ui): keep the icon gallery renderable when icons.tsx exports a non-component#2559
ARE404 wants to merge 1 commit into
apache:mainfrom
ARE404:are404/fix-icons-story

Conversation

@ARE404

@ARE404 ARE404 commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

What

Design System/Icons currently throws on mount, which fails the Storybook smoke run.

The gallery enumerates icons.tsx and mounts every export:

const LUCIDE_ICONS = Object.entries(Icons)
  .map(([name, value]) => ({ name, Comp: value as IconEntry['Comp'] }))

That held while the module was only components. #2538 added ICON_SIZE — the sizing ladder (meta / control / chrome / empty / plate) call sites read — so the story now mounts a plain object as an element. React rejects it outright:

[design-system-icons--lucide-icons @ catalog] console.error:
Error: Minified React error #130 (element type is invalid: got object)

Enumerated at runtime, it is the only one: 112 exports, 1 non-component.

The fix

Keep the enumeration and filter on what can actually be mounted. The enumeration is deliberate — the story's own comment on BOT_BRAND_PROVIDERS makes the argument, and it applies here too: a hand-kept list is satisfied by any subset, so a newly added icon would silently never render.

Lucide's icons arrive as forwardRef objects rather than plain functions, so the test is React's own element-type marker, not typeof value === 'function'.

Why CI did not catch it

The storybook job is path-gated (needs.changes.outputs.storybook == 'true'). On the runs where it mattered it was skipped, so main is green with this story broken — I hit it from a branch that does trip the gate.

Verification

npm --workspace @maka/desktop run build-storybook && npm --workspace @maka/desktop run smoke:storybook

  • before: ✗ design-system-icons--lucide-icons1 story check(s) failed, exit 1
  • after: ✓ design-system-icons--lucide-iconsProduct Storybook smoke passed (48 manifest check(s), 101 catalog render(s)), exit 0

Split out of #1874 rather than folded into it — it is unrelated to that feature and shouldn't need its review.

…n-component

`icons.tsx` is not only components: apache#2538 added `ICON_SIZE`, the sizing ladder
call sites read. The gallery enumerates the module and mounts whatever comes
back, so that object was rendered as an element — React rejects it outright
("element type is invalid", error apache#130) and the whole story goes down with it,
which fails the Storybook smoke run.

The enumeration is the point and stays: a hand-kept list is what would let a
newly added icon go unrendered. Filter on what can actually be mounted
instead. Lucide's icons arrive as `forwardRef` objects rather than plain
functions, so the test is React's own element-type marker rather than
`typeof value === 'function'`.

Verified with `build-storybook` + `smoke:storybook`: the run passes end to end
(48 manifest checks, 101 catalog renders) where it previously failed on this
one story.
@ARE404

ARE404 commented Aug 9, 2026

Copy link
Copy Markdown
Contributor Author

Heads-up on this PR's own storybook job: it is red, but not for the story this fixes — that one now passes:

✓ design-system-icons--lucide-icons @ catalog
✗ product-settings-pages--daily-review-model-selector-open-narrow @ floor
   Error: Daily Review controls overflow at 480px

That is a second, independent breakage sitting behind the same path gate, and this branch is a single file (packages/ui/stories/icons.stories.tsx) so it cannot be the cause.

Worth knowing before someone tries to reproduce it: it passes on macOS and fails on Linux CI. My local build-storybook + smoke:storybook run reports ✓ … --narrow @ floor and Product Storybook smoke passed (48 manifest check(s), 101 catalog render(s)) on the same commit. So it needs a Linux run to see at all.

The assertion at settings-pages.stories.tsx:964 ORs several geometry conditions into one message, so which one trips is not visible from the error. Given #2546 ("place daily review selector below trigger") is recent and the assertion includes doesNotCoverTrigger, that is where I would look first — but I have not verified it and am leaving it to whoever owns that change rather than guessing in this PR.

I have not touched it here. Happy to take it in a third PR if you want it from me.

@ARE404

ARE404 commented Aug 9, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #2544 — same bug, same shape of fix, already on main. Closing this rather than rebasing it.

For anyone reading back: yours filters on 'render' in value, mine on React's $$typeof marker; both correctly keep lucide's forwardRef objects and drop ICON_SIZE, so there is nothing left to reconcile.

The second failure I noted above — product-settings-pages--daily-review-model-selector-open-narrow @ floor, Linux-only — looks like it may be covered by #2556 ("bound settings selector menus"). I will confirm from #1874's run once it is rebased past both.

@ARE404 ARE404 closed this Aug 9, 2026
@ARE404
ARE404 deleted the are404/fix-icons-story branch August 9, 2026 06:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant