Skip to content

Two more retired lucide spellings reach the icons-record resolver — edit in DetailView's mobile Edit action, smile as the icon renderer's own default — and only one of the four resolver copies is pinned #5622

Description

@os-sales

Measured while implementing #5586 on origin/main @ 8c87f0583. Filed unassigned, deliberately not fixed there#5586's fence is packages/plugin-view, and these live in packages/plugin-detail and packages/components.

The measurement

#5586's root cause is that lucide retires a spelling by dropping it from the runtime icons record while keeping it as a deprecated named export, so a by-name lookup silently returns null and the site renders no icon at all. That card fixed the two instances in plugin-view. Scanning the whole repo for the same shape finds two more on live paths.

Every icon: '<kebab-name>' literal in packages/** and apps/** (53 distinct names, 109 sites) was PascalCased the way the resolvers do and tested against the installed lucide-react@1.31.0 record:

icon-name literals scanned: 53
NOT in the icons record: 15
check-circle -> CheckCircle (canonical CircleCheckBig)
edit -> Edit (canonical SquarePen)
smile -> Smile (canonical FaceSlightlySmiling)
x-circle -> XCircle (canonical CircleX)
chevron, not-a-real-icon, text-*-500 … (see "not defects" below)

1. packages/plugin-detail/src/DetailView.tsx:784 — production

items.push({
name: 'sys_edit_mobile',
label: t('detail.edit'),
icon: 'edit',
…

Those items become an action:bar schema (same file, type: 'action:bar'), and the packages/components action renderers resolve action.icon through renderers/action/resolve-icon.ts, which reads the icons record. Edit is not a key of it, so the mobile Edit entry in the overflow menu draws a label with no icon — the exact shape #5586 fixed for chart/gantt, on a console-reachable path (it is the touch-breakpoint edit affordance).

2. packages/components/src/renderers/basic/icon.tsx:83 — the icon renderer's own default

ComponentRegistry.register('icon', IconRenderer, {
…
icon: 'smile',
inputs: [ { name: 'name', type: 'string', label: 'Icon Name', defaultValue: 'smile' }, … ]

Smile is not a key of the record either, and this renderer's own lookup is the one that console.warns and returns null when it misses. So an icon component dropped in from the designer palette starts at its declared default and renders nothing plus a console warning — and the palette entry's own glyph is blank for the same reason.

3. packages/plugin-list/src/ViewSwitcher.tsx:13-21 — the same staleness, not (yet) user-visible

VIEW_ICONS names Grid, GanttChartSquare and BarChart3 — the same three deprecated aliases #5586 replaced in plugin-view's DEFAULT_VIEW_ICONS. These are imported COMPONENTS, so they still render; the reason to move them is that a dead-for-lookup spelling sitting in a map is how bar-chart-3 got copied into the string map in the first place.

Why the same name works in some places and not others

There are two different lucide surfaces in this repo, and they disagree about aliases — measured on the installed version:

resolverreadsentriescarries edit / check-circle
plugin-view/src/ViewSwitcher.tsx, components/renderers/action/resolve-icon.ts, components/renderers/basic/icon.tsx, plugin-list/src/components/TabBar.tsxicons record1767no
app-shell/src/utils/getIcon.ts, layout/src/NavigationRenderer.tsx (via getLazyIcon)lucide-react/dynamic.mjs's iconNames2025yes

So icon: 'edit' renders correctly in the sidebar and renders nothing in an action bar. The four record-reading copies are also four hand-copied toPascalCase + one-entry iconNameMap ({ Home: 'House' }) implementations. Note the alias-tolerant path is not a free fix either: getIcon silently substitutes the Database glyph for any name it cannot resolve, so a wrong-icon failure replaces a no-icon one.

Suggested shape (for triage, not a ruling)

  1. Fix the two live names against the record (editsquare-pen, smile → the spelling picked for the palette default) and the three plugin-list component aliases.
  2. ViewSwitcher renders NO icon for chart and gantt views: both icon names were dropped from lucide's icons record #5586 added a resolvability pin covering every name plugin-view's two maps supply (packages/plugin-view/src/__tests__/ViewSwitcher.test.tsx). Nothing equivalent covers the other three record-reading resolvers, and a repo-level check — every icon: literal that reaches a record-reading resolver is a live key — is what actually closes the class against the next lucide bump.

Not defects (recorded so the next scan does not re-triage them)

  • text-amber-500 and eight siblings (app-shell/…/previews/AppNavCanvas.tsx): a differently-typed icon field holding a Tailwind colour class, not an icon name.
  • not-a-real-icon (two notification tests): deliberate negative controls.
  • chevron (types/…/accordion-item-authorable-keys.test.ts): an authorable-keys fixture, never resolved.
  • check-circle / x-circle (app-shell/…/DeclaredActionsBar.overrideAffordance.test.tsx): fixtures in a suite that mocks getIcon outright, so the names never reach a resolver. They are still retired spellings and worth correcting with the rest.
  • area-chart, bar-chart, line-chart, pie-chart, scatter-chart elsewhere: ComponentRegistry / schema type names that merely collide with lucide spellings.

Dedup

Searched open issues for the lucide-name shape, the icon-resolution shape, and lucide upgrade cards; nothing open covers these sites. Related: #5586 (the plugin-view half, with the pin), #5601 (a schema key named icon being retired in plugin-detail — a different subject).

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdomain: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