Skip to content

Generate Lucide icon components from the pinned icon set - #2506

Merged
pournasserian merged 1 commit into
v2from
2434-lucide-icon-components
Oct 18, 2026
Merged

pournasserian merged 1 commit into
v2from
2434-lucide-icon-components

Conversation

@pournasserian

Copy link
Copy Markdown
Member

Closes #2434

What

Lucide icons as inline SVG components generated from the icon set, the last open item of #2434.

  • Icons.targets adds a GenerateIcons target to the Admin project:
    • src/FluentCMS.Admin/Icons/icons.txt lists the icons the admin uses, one Lucide name per line.
    • dotnet build src/FluentCMS.Admin -t:GenerateIcons downloads the pinned Lucide release once per machine into a cache (%LocalAppData%\FluentCMS\lucide or ~/.cache/fluentcms/lucide, like the Tailwind binary) and verifies it.
    • It then writes one component per listed icon into Components/Icons and copies the release's licence next to the list.
    • The generated components are committed. A normal build does not download or generate anything, so CI and offline builds are unchanged.
  • The components are named as in lucide-react (XIcon, ChevronDownIcon), in FluentCMS.Admin.Components.Icons, which _Imports.razor now imports.
    • Each renders Lucide's own <svg> attributes and shapes, with aria-hidden="true" and the classes lucide lucide-<name> merged with a Class parameter.
    • Other attributes pass through and override the defaults, for example stroke-width="3", or aria-hidden="false" with a label for an icon that carries meaning.
    • Size comes from the surrounding classes, as in shadcn ([&_svg:not([class*='size-'])]:size-4).
  • The hand-copied SVGs are gone. Dialog, Sheet and Toaster close buttons use XIcon, Checkbox CheckIcon, Select and DiffView ChevronDownIcon, RadioGroupItem CircleIcon, CommandInput SearchIcon, the theme toggle SunIcon and MoonIcon, and /ui PlusIcon. The markup they render is unchanged apart from the lucide classes and the width and height attributes Lucide carries.
  • /ui has an Icons section listing every generated icon with its component name.
  • CONTRIBUTING.md: how to add an icon, how the set is pinned, and its licence.

How the set is pinned and licensed

  • Pinned: Icons.targets sets LucideVersion to 1.59.0, the current release, and pins two SHA-256 checksums:

    • the release archive lucide-icons-1.59.0.zip from the GitHub release;
    • the release's LICENSE at the 1.59.0 tag.

    Lucide publishes no checksums, so these were computed from the downloads and are recorded here. A download that does not match is deleted and the build fails. Every generated file names the version it came from, and a test fails if that version differs from the pin. Updating means changing the version and both checksums, then running the target.

  • Licensed: Lucide is ISC. The icons it took from Feather are MIT, and the licence file lists them; seven of the eight icons used here are among them (all but sun). Both licences allow use and modification with the notice kept. src/FluentCMS.Admin/Icons/LICENSE is that file verbatim, and every generated component points to it.

Boxes on #2434

Ticked with this pull request:

That leaves no open box, so this closes #2434. One item in the issue's Acceptance list has no box and is not done: automated WCAG 2.1 AA checks on /ui (UX-04). They need a browser test tool, and #2468 proposed running axe-core through Playwright when Playwright arrives with the desk flows (F-DSK, #2422).

Why

  • Generated and committed, not generated on every build. A build-time generator would download the archive on every clean machine and CI run for a few kilobytes of markup. Committing the output keeps the build as it is. The pin, the list and the tests keep the output honest.
  • Only the icons in use. The full set has 1,891 icons. A component for each would add them all to the assembly and to Tailwind's scan for icons nobody renders, so the list grows with the screens.
  • An MSBuild target, not a tool. It needs only the .NET SDK, uses the same download, verify and cache pattern as Tailwind.targets, and its one inline task turns an SVG file into a component.
  • Icon suffix. Several Lucide names collide with components (badge, command, table). lucide-react exports the suffixed names as well, so shadcn examples that use XIcon read the same.

No new package; the icons are data from the pinned release.

Tests

  • IconsTests:
    • Every name in icons.txt has a generated component, and every component is listed.
    • Every component names the pinned version, and the targets file pins both checksums.
    • The licence is the ISC one with the Feather MIT section.
    • Each icon renders Lucide's svg (view box, stroke, stroke width), hidden from assistive technology, with its classes merged.
    • Attributes override the defaults.
  • ShowcaseTests: 23 sections, and the Icons section renders every generated icon.
  • The existing tests for Checkbox, Select, DiffView, the theme toggle and the overlays pass unchanged against the generated icons.

Checked on /ui: the icons render at the size their surroundings give them (16 px in buttons and inputs, 20 px in the Icons section); in dark mode the theme toggle shows the moon and hides the sun; the checkbox tick shows only when checked, with its heavier stroke; the radio dot shows only on the checked option.

dotnet build -warnaserror, the full suite and markdownlint pass locally, and -t:GenerateIcons run from an empty cache downloads, verifies and regenerates byte-identical files.

Checklist

  • Linked to an issue a maintainer has confirmed
  • Targets v2
  • Tests or docs updated where behaviour changed
  • No tool-generated co-author trailers or footers

@pournasserian pournasserian added this to the M1 Governance core milestone Oct 18, 2026
@pournasserian pournasserian added v2 FluentCMS v2 (v2 branch) type:chore Repository, tooling or housekeeping area:infra Persistence, host, CI and build labels Oct 18, 2026
@pournasserian
pournasserian merged commit e8a6977 into v2 Oct 18, 2026
2 checks passed
@pournasserian
pournasserian deleted the 2434-lucide-icon-components branch October 18, 2026 23:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:infra Persistence, host, CI and build type:chore Repository, tooling or housekeeping v2 FluentCMS v2 (v2 branch)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Admin shell and component set

1 participant