Skip to content

finding(components): ui:button inlines its own copy of resolveIcon instead of importing it, so any future fix to the shared resolver silently misses it #5993

Description

@yinlianghui

Found while implementing #5930, verifying the premise that resolveIcon is "the same resolver ui:button uses". It is the same algorithm, but not the same function.

What is on the tree

packages/components/src/renderers/form/button.tsx (the ui:button registration, namespace ui) does not import resolveIcon. It carries a byte-equivalent reimplementation at module scope — its own toPascalCase, its own iconNameMap containing the single entry Home -> House, and its own index into icons from lucide-react:

letIcon: LucideIcon|null=null;if(schema.icon){consticonName=toPascalCase(schema.icon);constmappedIconName=iconNameMap[iconName]||iconName;Icon=(iconsasany)[mappedIconName]asLucideIcon;}

packages/components/src/renderers/action/resolve-icon.ts is the shared version, and the action:* family (action-button, action-menu, action-group, action-icon) plus renderers/complex/data-table.tsx all import it.

Why it matters

Behaviour is identical today — same population, same casing rule, same Home -> House alias, same "unknown name renders nothing" outcome — so nothing is currently mis-rendering. The risk is divergence: an alias added to iconNameMap in resolve-icon.ts (which is exactly how lucide retirements have been absorbed — see #5586, #5622) does not reach ui:button. The copy would keep resolving the retired spelling to nothing while every action:* site started resolving it correctly, and no gate separates them because check:icon-record-names declares both modules as legitimate record readers.

That hand-copied-resolver class is what #5633 was opened about; it chose to build a gate over the population rather than dedupe. This is the dedupe half, still outstanding.

Shape of the repair

Import resolveIcon in form/button.tsx, delete the local toPascalCase and iconNameMap, and drop form/button.tsx from DECLARED_RECORD_READERS in scripts/check-lucide-icon-record-names.mjs — the census rediscovers readers from source on every run and fails on drift in both directions, so that edit is verified rather than asserted.

Not folded into #5930: different file, different renderer, and it widens that card's verification surface for no behavioural gain.

Metadata

Metadata

Assignees

Labels

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

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions