Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 24 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ jobs:
with:
global-json-file: global.json

# ShellIcons.Blazor multi-targets net8.0 + net9.0, so both runtimes must
# be available on the CI runner even though the SDK is pinned to net10.
# ShellIcons.Blazor targets net8.0 + net9.0, so the tests need both runtimes.
- name: Install net8 + net9 runtimes
uses: actions/setup-dotnet@v4
with:
Expand All @@ -38,14 +37,33 @@ jobs:
- name: Test
run: dotnet test ShellIcons.slnx --configuration Release --no-build --verbosity normal

# Smoke pack — proves the packable project produces a valid .nupkg on
# every commit, so the release workflow can't be blindsided by a packaging
# bug. Packs the specific project (not the solution) to skip non-packable
# ones cleanly — packing the solution warns for every IsPackable=false project.
# The project, not the solution: packing the solution warns for every non-packable project.
- name: Smoke pack
run: dotnet pack src/ShellIcons.Blazor/ShellIcons.Blazor.csproj --configuration Release --no-build --output nupkgs
env:
ContinuousIntegrationBuild: true

- name: List produced packages
run: ls -la nupkgs/

# Windows builds every MAUI target (Android, iOS, Mac Catalyst, Windows); ubuntu lacks the workloads.
maui:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
global-json-file: global.json

- name: Install MAUI workload
run: dotnet workload install maui

- name: Build (all platform targets)
run: dotnet build ShellIcons.Maui.slnx --configuration Release
env:
ContinuousIntegrationBuild: true

- name: Test
run: dotnet test tests/ShellIcons.Maui.Tests --configuration Release --no-build --verbosity normal
17 changes: 6 additions & 11 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,18 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
9.0.x
10.0.x
global-json-file: global.json

# Keep in step with the ShellDocs.* package versions in ShellIcons.Docs.csproj.
- name: Install ShellDocs.CLI
run: dotnet tool install -g ShellDocs.CLI --prerelease

- name: Restore
run: dotnet restore ShellIcons.slnx
run: dotnet tool install -g ShellDocs.CLI --version 0.1.7-alpha

# Prerenders every content/ page to static HTML; CNAME ships from wwwroot/.
- name: Build docs (static)
working-directory: docs/ShellIcons.Docs
run: shelldocs build --output ../../publish --spa-fallback

- name: Set custom domain (CNAME)
run: echo "shellicons.shellui.dev" > publish/CNAME
run: shelldocs build --output ../../publish --spa-fallback --site-url https://shellicons.shellui.dev

# Jekyll would drop the _framework/ and _content/ folders.
- name: Disable Jekyll
run: touch publish/.nojekyll

Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ x86/
## NuGet packages
*.nupkg
*.snupkg
nupkgs/

## Static docs build (shelldocs build --output publish)
publish/

## IDE
.vs/
Expand Down
31 changes: 31 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Changelog

All notable changes to the ShellIcons packages. `ShellIcons.Blazor` is published on NuGet; `ShellIcons.Maui` is in preview and not published yet.

Format based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versioning follows [SemVer](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- **Blazor: `{Name}Icon` components** — `<ChevronRightIcon />`, `<ZapIcon />`, … in the root `ShellIcons` namespace. A single `@using ShellIcons` now works next to UI kits whose component names match Lucide icons (`Badge`, `Table`, `Router`, …), which previously failed with RZ9985. This is the recommended form for markup. Lucide's `shell` icon is the one exception, since `ShellIcon` is the dispatcher; use `Icon.Shell()` (build info `SHELLICONS003`).
- **Blazor: `Icon.*` factory** — `Icon.ChevronRight()` returns a `RenderFragment`, for icons as values: component parameters and lists built in C#. Unused icons are still trimmed.
- **Blazor: clear error for `@onclick` on an icon.** On a component, Razor passes `@onclick="…"` as a plain string, which broke rendering in the browser with a cryptic error. It now throws an `InvalidOperationException` that explains the forms that work.
- **`ShellIcons.Maui` (preview, not yet on NuGet)** — the same catalog as native MAUI `Path` shapes: typed controls (`<icons:ChevronRight />`), an `IconName` dispatcher (`<icons:Icon Name="Search" />`), and `IconCatalog` with tags, categories, alias-aware `TryParse` and `Search`. Builds for Android, iOS, Mac Catalyst and Windows.
- Build diagnostics for custom icons that can't be converted for MAUI: `SHELLICONS002` (unsupported SVG such as `<g>` or `transform`), `SHELLICONS004` (name not usable as an enum member), `SHELLICONS005` (shape outside the viewBox, dropped).
- Docs site at [shellicons.shellui.dev](https://shellicons.shellui.dev) (deployed from `main`), with a searchable icon browser and a MAUI section.

### Changed

- `Icon.*` calls with no arguments reuse a cached fragment instead of allocating on every render. `ShellIcons.Blazor.dll` is about a third smaller than the first factory version, even with the new `{Name}Icon` components.
- Components in `ShellIcons.Icons` are no longer `sealed`.
- The build no longer references `Microsoft.SourceLink.GitHub`, whose `Microsoft.Build.Tasks.Git 8.0.0` dependency has a known vulnerability (NU1902). Source Link now comes from the .NET SDK; packages still link to the exact commit.

### Fixed

- The README's click-handler example for `additionalAttributes` used the key `"@onclick"`; the working key is `"onclick"`.
- MAUI: Lucide 0.475.0's `save-off.svg` contains a stray shape outside the viewBox. Browsers clip it; on MAUI it's dropped so it can't draw beside the icon.

## [0.1.0-alpha] — 2026-08-22

First release of `ShellIcons.Blazor`: all 1,555 icons from Lucide 0.475.0 as typed components, the `<ShellIcon Name="…" />` dispatcher, `IconCore` with `Size`, `StrokeWidth`, `AbsoluteStroke`, `Class` and `Title`, and a drop-in path for custom icons.
76 changes: 50 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,24 @@ Lucide-derived SVG icons for **Blazor**, **Avalonia**, and **.NET MAUI**.
- Native rendering per target: inline `<svg>` in Blazor, native `Path` shapes in Avalonia/MAUI
- Tree-shakeable typed components per icon

See [SHELLICONS.md](SHELLICONS.md) for the full design proposal.
Docs: [shellicons.shellui.dev](https://shellicons.shellui.dev)

## Status

**Docs live in dev, Phase 2 complete — full Lucide 0.475.0 catalog (1555 icons) auto-generated for Blazor.**

- [x] Design doc
- [x] Solution scaffold
- [x] Blazor `IconCore` with Size/StrokeWidth/Class/Title/AbsoluteStroke props
- [x] Lucide catalog sync script (pinned via `LUCIDE_VERSION.txt`)
- [x] `catalog/custom/` drop-in path for repo-owned icons
- [x] Roslyn incremental source generator — reads both `catalog/lucide/` and `catalog/custom/`, emits 1555 typed components + `ShellIcon` dispatcher
- [x] Test suite: 46 unit + integration tests (xUnit + bUnit)
- [x] Docs site at [docs/ShellIcons.Docs](docs/ShellIcons.Docs) — ShellDocs-powered, runs at `dotnet run` on http://localhost:5145
- [x] Live icon browser at `/icons` — searchable, 1555-cell grid with click-to-copy
- [x] GH Pages workflow + `CNAME` for [shellicons.shellui.dev](https://shellicons.shellui.dev)
- [x] CI + Release pipelines — see [RELEASING.md](RELEASING.md) for the runbook
- [ ] Blocker: `shelldocs.cli` build doesn't emit `index.html` or the WASM runtime — GH Pages deploy waits on a CLI fix upstream
- [ ] First publish `ShellIcons.Blazor 0.1.0-alpha` to NuGet — bump version, tag `v0.1.0-alpha`, approve in the Actions UI
- [ ] Avalonia target (Phase 4)
- [ ] MAUI target (Phase 5)
| Package | Status |
|---|---|
| `ShellIcons.Blazor` | **0.1.0-alpha on [NuGet](https://www.nuget.org/packages/ShellIcons.Blazor)** — 1,555 Lucide 0.475.0 icons |
| `ShellIcons.Maui` | **Preview, unpublished** — builds for Android, iOS, Mac Catalyst and Windows; see [src/ShellIcons.Maui](src/ShellIcons.Maui/README.md) |
| `ShellIcons.Avalonia` | Planned — will reuse the MAUI path conversion |

- [x] Source generators emit every icon from the vendored catalog (`LUCIDE_VERSION.txt`) plus drop-in `catalog/custom/` icons
- [x] Blazor: suffixed components (`<ChevronRightIcon />`), `Icon.*` factory, `<ShellIcon Name>` dispatcher — safe next to UI kits
- [x] MAUI: typed controls, `IconName` dispatcher, `IconCatalog` metadata with alias lookup
- [x] 135 tests (xUnit + bUnit + headless MAUI), CI for both solutions, tag-driven release — see [RELEASING.md](RELEASING.md)
- [x] Docs site at [docs/ShellIcons.Docs](docs/ShellIcons.Docs) (ShellDocs 0.1.7-alpha), with a searchable icon browser
- [x] Static build for GitHub Pages ([shellicons.shellui.dev](https://shellicons.shellui.dev)) — deploys on push to `main`
- [ ] MAUI: check rendering on Android/iOS devices, then publish
- [ ] Avalonia target

## Blazor quickstart

Expand Down Expand Up @@ -153,14 +150,27 @@ Without `Title` icons are decorative (`aria-hidden="true"`); with it they get `r
<XIcon Title="Close dialog" />
```

## MAUI quickstart (preview)

```xml
<ContentPage xmlns:icons="https://shellicons.dev/maui">
<icons:ChevronRight Size="16" />
<icons:Icon Name="{Binding StatusIcon}" Color="{DynamicResource Primary}" />
</ContentPage>
```

Not on NuGet yet — reference `src/ShellIcons.Maui` from source. Docs: [MAUI getting started](docs/ShellIcons.Docs/content/docs/maui/getting-started.md).

## Repo layout

```
shell-icons/
├── SHELLICONS.md design proposal
├── CHANGELOG.md release notes
├── RELEASING.md how to cut a release
├── LUCIDE_VERSION.txt pinned upstream tag
├── NOTICE.md Lucide ISC attribution
├── ShellIcons.slnx
├── ShellIcons.slnx Blazor, generators, tests, docs — no MAUI workload needed
├── ShellIcons.Maui.slnx MAUI projects — needs `dotnet workload install maui`
├── Directory.Build.props
├── catalog/
│ ├── lucide/icons/ vendored Lucide SVGs (populated by sync-lucide.ps1)
Expand All @@ -170,15 +180,20 @@ shell-icons/
├── scripts/
│ └── sync-lucide.ps1 refresh vendored Lucide catalog
├── src/
│ ├── ShellIcons.Blazor/ Razor Class Library (net8.0;net9.0)
│ └── ShellIcons.Generator/ Roslyn incremental source generator (netstandard2.0)
│ ├── ShellIcons.Blazor/ Razor Class Library (net8.0;net9.0)
│ ├── ShellIcons.Generator/ Blazor source generator (netstandard2.0)
│ ├── ShellIcons.Maui/ MAUI library (preview)
│ └── ShellIcons.Generator.Xaml/ MAUI source generator + SVG → path conversion
├── tests/
│ ├── ShellIcons.Generator.Tests/ xUnit: SvgParser, Naming
│ └── ShellIcons.Blazor.Tests/ xUnit + bUnit: IconCore, generated icons, dispatcher
│ ├── ShellIcons.Generator.Tests/ xUnit: SvgParser, Naming, path conversion
│ ├── ShellIcons.Blazor.Tests/ xUnit + bUnit: components, factory, dispatcher, collisions
│ └── ShellIcons.Maui.Tests/ headless MAUI: controls, XAML, whole-catalog geometry
├── docs/
│ └── ShellIcons.Docs/ ShellDocs site — dev at http://localhost:5145
└── .github/workflows/
└── docs.yml GH Pages deploy pipeline (waits on shelldocs.cli fix)
├── ci.yml ubuntu: ShellIcons.slnx · windows: ShellIcons.Maui.slnx
├── release.yml tag → NuGet (Trusted Publishing) + GitHub Release
└── docs.yml static build → GitHub Pages
```

## Docs
Expand All @@ -192,7 +207,16 @@ dotnet run

Serves at http://localhost:5145. Pages live in `docs/ShellIcons.Docs/content/docs/*.md`. Live component previews via `razor:preview` code fences work out of the box.

The `/icons` route is a searchable browser of the entire catalog with click-to-copy component names.
`/docs/icons` is a searchable browser of the entire catalog with click-to-copy component names.

Build the static site the way the deploy workflow does (needs `dotnet tool install -g ShellDocs.CLI --version 0.1.7-alpha`):

```bash
cd docs/ShellIcons.Docs
shelldocs build --output ../../publish --spa-fallback --site-url https://shellicons.shellui.dev
```

Every page under `content/` is prerendered to plain HTML, so any static host can serve `publish/`. Pages added as Razor `@page` routes outside `content/` are not prerendered — put new pages in `content/` (a component can be used from markdown, as `content/docs/icons.md` does).

## Refreshing the Lucide catalog

Expand Down
Loading
Loading