Skip to content

ViewSwitcher renders NO icon for chart and gantt views: both icon names were dropped from lucide's icons record #5586

Description

@os-sales

Measured while implementing #5321 on origin/main @ f2158ec86. Filed unassigned, not claimed, and deliberately not fixed there#5321 owns the missing tree KEY in the same map, and this is a different defect (a key that is present but whose VALUE no longer resolves), needing new icon names chosen rather than a key added.

What was measured

ViewSwitcher.resolveIcon (packages/plugin-view/src/ViewSwitcher.tsx) turns an icon NAME into a component by PascalCasing it and looking it up in lucide's icons record:

const iconName = toPascalCase(name);
const mapped = iconNameMap[iconName] || iconName;
return (icons as any)[mapped] || null;

Two of the names ObjectView's iconMap supplies do not exist in that record on the installed lucide-react@1.31.0. Probed directly against the installed package:

kanban kanban -> Kanban RESOLVES
calendar calendar -> Calendar RESOLVES
map map -> Map RESOLVES
gallery layout-grid -> LayoutGrid RESOLVES
timeline activity -> Activity RESOLVES
gantt gantt-chart -> GanttChart *** MISSING ***
grid table -> Table RESOLVES
list list -> List RESOLVES
detail file-text -> FileText RESOLVES
chart bar-chart-3 -> BarChart3 *** MISSING ***
tree list-tree -> ListTree RESOLVES

The cause is that lucide keeps the old spellings as deprecated NAMED EXPORTS while dropping them from the icons record that a by-name lookup reads. Measured on the same version:

namenamed exportin icons
BarChart3yesno
GanttChartyesno
GanttChartSquareyesno
ChartColumnyesyes
ChartGanttyesyes

So the compiler is no help here: ViewSwitcher.tsx imports BarChart3 and GanttChartSquare by name for its own DEFAULT_VIEW_ICONS and type-checks clean, while the by-name path beside it silently misses.

User-visible effect

getViewIcon does not fall back to DEFAULT_VIEW_ICONS once an explicit icon is set — it returns resolveIcon(view.icon), i.e. null:

function getViewIcon(view: ViewSwitcherItem): LucideIcon | null {
if (view.icon) {
return resolveIcon(view.icon);
}
return DEFAULT_VIEW_ICONS[view.type] || null;
}

and the render site is {Icon ? ( Icon ) : null}. ObjectView always supplies an icon string (icon: iconMap[v.type] || 'table'), so a host-composed chart or gantt view is drawn as a label with no icon at all, while every other type in the same switcher has one. No crash. The console reaches this: CreateViewDialog offers both chart and gantt among the view types a user can create, and those records arrive as ObjectView's views prop.

Why it is worth a card rather than a drive-by

Picking the replacements is a judgement call, not a mechanical rename — lucide offers several candidates per glyph (ChartColumn, ChartColumnBig, ChartGantt, ChartNoAxesGantt), and the choice should probably be made together with the DEFAULT_VIEW_ICONS entries beside them, which still import the deprecated aliases. There is also a guard question worth settling in the same breath: nothing today fails when a name stops resolving, which is exactly why this survived a major lucide bump. A pin asserting that every name the map supplies resolves in icons would close the class; #5321 deliberately left its resolvability assertion scoped to tree alone and says so in a comment, so that the widening happens here with the fix rather than as a surprise red.

Not fixed in #5321

#5321's ruling was about which view types are authorable, and its one behaviour change was adding the missing tree KEY (tree: 'list-tree', verified resolving). Its scope fence is packages/plugin-view/src/** plus the record; changing two working-looking icon names on a judgement call is outside it.

Dedup

Searched open issues for the lucide-name shape, for the iconMap / view-switcher icon shape, and for lucide upgrade cards. Nothing open covers it. Related and closed: #2916 (added the chart key to this same map — the key it added is the one now failing to resolve), #1885 (tree view added). Related and open: #5321 (the missing tree key, and the host-only view-type record).

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatplugin-viewpm:dispatched

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions