refactor(web): one icon system — fold settings' lucide-solid icons into the vendored Icon component, drop the dependency #199

Closed
opened 2026-07-22 02:08:51 +02:00 by dominik.polakovics · 1 comment

What to build

Consolidate the SPA back to a single icon mechanism: the vendored Icon component (ADR-0019). The settings rework (#198) introduced lucide-solid as a package dependency for its section/category icons, so the app currently has two icon systems — vendored Lucide glyphs behind Icon, and per-icon lucide-solid imports in the settings UI. Both render the same Lucide designs; the split is purely in delivery mechanism.

Direction (maintainer decision, triage 2026-08-03): vendor the missing glyphs into the Icon component, migrate the settings UI onto it, and remove the lucide-solid dependency — honoring ADR-0019's "no icon package" decision rather than superseding it.

Historical note: this issue originally prescribed the opposite migration (everything → lucide-solid) back when one-off <svg> elements were scattered across components. Those have since been consolidated into the vendored Icon component, and ADR-0019 pins that approach; only the settings UI still imports the package.

See the agent brief in the comments for the authoritative spec.

## What to build Consolidate the SPA back to a single icon mechanism: the vendored `Icon` component (ADR-0019). The settings rework (#198) introduced `lucide-solid` as a package dependency for its section/category icons, so the app currently has two icon systems — vendored Lucide glyphs behind `Icon`, and per-icon `lucide-solid` imports in the settings UI. Both render the same Lucide designs; the split is purely in delivery mechanism. Direction (maintainer decision, triage 2026-08-03): vendor the missing glyphs into the `Icon` component, migrate the settings UI onto it, and remove the `lucide-solid` dependency — honoring ADR-0019's "no icon package" decision rather than superseding it. Historical note: this issue originally prescribed the opposite migration (everything → `lucide-solid`) back when one-off `<svg>` elements were scattered across components. Those have since been consolidated into the vendored `Icon` component, and ADR-0019 pins that approach; only the settings UI still imports the package. See the agent brief in the comments for the authoritative spec.
dominik.polakovics changed title from refactor(web): migrate all ad-hoc inline SVG icons to lucide-solid to refactor(web): one icon system — fold settings' lucide-solid icons into the vendored Icon component, drop the dependency 2026-08-03 01:55:33 +02:00
Author
Owner

This was generated by AI during triage.

Agent Brief

Category: enhancement
Summary: Migrate the settings UI's lucide-solid icons into the vendored Icon component and remove the lucide-solid package dependency.

Current behavior:
The SPA has two icon systems rendering the same Lucide designs. Most of the app uses the vendored Icon component — a single component with an IconName union type mapping names to inline Lucide SVG glyphs (24×24 viewBox, fill="none", stroke="currentColor", stroke-width 2, aria-hidden, accessible name on the enclosing control), per ADR-0019. The settings UI (the settings layout's back/forward chevrons and the global/repo settings category registries) instead imports icons per-icon from the lucide-solid npm package, and the shared settings category registry types its icon entries with the package's LucideProps type.

Desired behavior:
One icon system: every icon in the SPA renders through the vendored Icon component, and lucide-solid is gone from the dependency set. Vendor the glyphs currently used only via the package into the Icon component's glyph map, copying the SVG paths from upstream Lucide (ISC license — keep the attribution note in the component header accurate): bell, bot, calendar-clock, container, folder-input, lock-keyhole, plane-landing, plug, settings-2, triangle-alert, chevron-left, chevron-right. (git-branch is also used by settings but already vendored.) Keep each glyph visually identical to what the package rendered.

Key interfaces:

  • The IconName union type — extend with the new glyph names.
  • The glyph map inside the Icon component — one entry per new name, following the existing pattern (glyphs as functions returning SVG children; note the component's caveat about which SVG child tags the Solid compiler namespaces correctly — e.g. <line> is drawn as an equivalent <path>).
  • The settings category registries (global and repo) — their icon fields currently hold lucide-solid component references typed via LucideProps; rework to the Icon-based equivalent (e.g. an IconName string rendered by the shared layout), removing the LucideProps type import.
  • The settings layout component — replace its direct lucide-solid chevron imports with Icon usages.
  • package.json — remove the lucide-solid dependency (and its lockfile entries).
  • Tests that mock lucide-solid (the settings layout test does) — rework to the Icon-based rendering; existing assertions on accessible names must keep passing.

Acceptance criteria:

  • No import from lucide-solid remains anywhere in the web app source or tests
  • lucide-solid is removed from the web app's dependencies and lockfile
  • All settings section/category icons and the settings layout chevrons render via the vendored Icon component with no visible glyph change (same designs, sizes, stroke behavior)
  • New glyphs inherit currentColor and render correctly in light and dark themes
  • The <svg> stays aria-hidden with accessible names on enclosing controls; existing accessibility-related test assertions still pass
  • The web app's test suite, typecheck, and build all pass

Out of scope:

  • Changing any icon choice (which glyph appears where) — this is a mechanism migration only
  • Redesigning the Icon component API beyond extending the name union
  • A superseding ADR — this direction upholds ADR-0019; at most add a short note to it recording that the temporary lucide-solid usage from the settings rework was folded back in
  • Icon changes outside the web SPA
> *This was generated by AI during triage.* ## Agent Brief **Category:** enhancement **Summary:** Migrate the settings UI's `lucide-solid` icons into the vendored `Icon` component and remove the `lucide-solid` package dependency. **Current behavior:** The SPA has two icon systems rendering the same Lucide designs. Most of the app uses the vendored `Icon` component — a single component with an `IconName` union type mapping names to inline Lucide SVG glyphs (24×24 viewBox, `fill="none"`, `stroke="currentColor"`, stroke-width 2, `aria-hidden`, accessible name on the enclosing control), per ADR-0019. The settings UI (the settings layout's back/forward chevrons and the global/repo settings category registries) instead imports icons per-icon from the `lucide-solid` npm package, and the shared settings category registry types its icon entries with the package's `LucideProps` type. **Desired behavior:** One icon system: every icon in the SPA renders through the vendored `Icon` component, and `lucide-solid` is gone from the dependency set. Vendor the glyphs currently used only via the package into the `Icon` component's glyph map, copying the SVG paths from upstream Lucide (ISC license — keep the attribution note in the component header accurate): `bell`, `bot`, `calendar-clock`, `container`, `folder-input`, `lock-keyhole`, `plane-landing`, `plug`, `settings-2`, `triangle-alert`, `chevron-left`, `chevron-right`. (`git-branch` is also used by settings but already vendored.) Keep each glyph visually identical to what the package rendered. **Key interfaces:** - The `IconName` union type — extend with the new glyph names. - The glyph map inside the `Icon` component — one entry per new name, following the existing pattern (glyphs as functions returning SVG children; note the component's caveat about which SVG child tags the Solid compiler namespaces correctly — e.g. `<line>` is drawn as an equivalent `<path>`). - The settings category registries (global and repo) — their icon fields currently hold `lucide-solid` component references typed via `LucideProps`; rework to the `Icon`-based equivalent (e.g. an `IconName` string rendered by the shared layout), removing the `LucideProps` type import. - The settings layout component — replace its direct `lucide-solid` chevron imports with `Icon` usages. - `package.json` — remove the `lucide-solid` dependency (and its lockfile entries). - Tests that mock `lucide-solid` (the settings layout test does) — rework to the `Icon`-based rendering; existing assertions on accessible names must keep passing. **Acceptance criteria:** - [ ] No import from `lucide-solid` remains anywhere in the web app source or tests - [ ] `lucide-solid` is removed from the web app's dependencies and lockfile - [ ] All settings section/category icons and the settings layout chevrons render via the vendored `Icon` component with no visible glyph change (same designs, sizes, stroke behavior) - [ ] New glyphs inherit `currentColor` and render correctly in light and dark themes - [ ] The `<svg>` stays `aria-hidden` with accessible names on enclosing controls; existing accessibility-related test assertions still pass - [ ] The web app's test suite, typecheck, and build all pass **Out of scope:** - Changing any icon *choice* (which glyph appears where) — this is a mechanism migration only - Redesigning the `Icon` component API beyond extending the name union - A superseding ADR — this direction *upholds* ADR-0019; at most add a short note to it recording that the temporary `lucide-solid` usage from the settings rework was folded back in - Icon changes outside the web SPA
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Cloonar/coding-lab#199
No description provided.