Skip to content
Edgar Mesquita edited this page Aug 15, 2026 · 16 revisions

Icons Ecosystem

🌐 This page in: English · Português

eQuantic.UI provides a comprehensive and extensible icon ecosystem. It supports multiple popular icon sets out of the box, all integrated through a unified component model.

🚀 Quick Start

To use icons in your project, install the desired icon set package and the core components package.

dotnet add package eQuantic.UI.Components
dotnet add package eQuantic.UI.Lucide

Usage

Nothing to register. A pack is a catalog of IconGlyph: you name the glyph you want and the compiler inlines that one:

using eQuantic.UI.Lucide;

Glyph(LucideIcons.Search)
Glyph(LucideIcons.Check, size: 20)

Sizes are the §07 whitelist (16 / 20 / 24 / 32). For a size off that list, Vector(glyph, size) draws the same paths without the icon contract, and Vector(glyph, size, height: h) gives a non-square figure its own aspect (since 0.2.0-preview.28; a diagram's connector was the case). Icon(...) is the factory for the framework's own curated Icons enum. See DeclarativeSurface for why the two have different names.

Because you name the glyph, nothing resolves at run time and two packs can never disagree about a name: there is no lookup to lose.

Package Description
eQuantic.UI.Lucide Beautiful & consistent icons (default set).
eQuantic.UI.Heroicons Beautiful hand-crafted SVG icons by the makers of Tailwind CSS.
eQuantic.UI.RadixIcons A crisp set of 15×15 icons designed by the Radix UI team.
eQuantic.UI.TablerIcons Over 4200 pixel-perfect icons for web design.
eQuantic.UI.FontAwesome6.Solid The world's most popular icon set (Solid variant).
eQuantic.UI.FontAwesome6.Regular Font Awesome 6 Regular icons.
eQuantic.UI.FontAwesome6.Brands Font Awesome 6 Brand icons.
eQuantic.UI.Phosphor A flexible icon family for interfaces, diagrams, and more.
eQuantic.UI.SimpleIcons Over 3000 SVG icons for popular brands.
eQuantic.UI.BootstrapIcons Free, high quality, open source icon library with 2,000+ icons.
eQuantic.UI.Iconoir A high-quality set of 1500+ open-source icons.
eQuantic.UI.MaterialSymbols Google's Material Symbols: 16,284 glyphs, the largest pack here.

Pack glyphs, write-once

An icon package is a catalog of IconGlyph: target-neutral path data, so the same entry serves the web realizer as inline SVG and the native atlas as glyph geometry. Draw one with Glyph:

using eQuantic.UI.MaterialSymbols;

Glyph(MaterialSymbolsIcons.PlayArrowRounded)
Glyph(MaterialSymbolsIcons.ExpandMore, size: 20)

Glyph, not Icon: Icon is the factory for the framework's own curated Icons enum, and the declarative surface has no overloads. See DeclarativeSurface. Sizes are the §07 whitelist (16 / 20 / 24 / 32); for anything off it, Vector(glyph, size) draws the same paths without the icon contract, and a height: argument frees the box from the square.

You pay for what you name. eqc inlines only the glyphs a page actually references: a page using two Material Symbols glyphs emits a 627-byte module, out of a catalog whose source is ~8 MB. Pack size is a build-time cost, not a download.

Since 0.2.0-preview.7

A note on Material Symbols

Google ships Material Symbols as a variable font with FILL, wght, GRAD and opsz axes, and the three cuts (outlined, rounded, sharp) are what those axes resolve to. A GPU display list cannot draw a font, so this package carries the resolved paths instead: the cut lives in the icon's name (Home, HomeRounded, HomeSharp) and there is no FILL axis, so X and XOutline are two entries. Names are the Iconify ones in PascalCase, so material-symbols:play-arrow-rounded is PlayArrowRounded.

It is also the heaviest pack the framework publishes (~13 MB of assembly against Phosphor's 8). If you need a handful of icons and have a choice, a smaller set costs less to carry.

Artwork from a .svg file

Since 0.2.0-preview.29

An icon is one path in one tint. A LOGO is several shapes, each in the colour its designer chose, that is Drawing, and it is the node you point at a file.

Put the file in the app's Assets folder and it becomes a typed member:

// Assets/mark.svg  →  Vectors.Mark
column.Add(new Drawing(Vectors.Mark, width: 240, label: "eQuantic"));

The reading happens at build time: nothing reads a file at runtime on either target, because a browser cannot and a native app would be carrying its artwork twice. A typed member rather than a path string, for the same reason the rest of this SDK generates surfaces: Vectors.Mark is a compile error when it is wrong, and Drawing("mark.svg") is a blank space at runtime.

One number keeps the artwork's own aspect (an icon defaults to a square because that is what an icon is; a squashed logo is a wrong logo). Give both to letterbox or stretch deliberately.

Tinting. A shape the file left as currentColor is the artwork asking to be tinted, so pass tint: and it follows, while every shape that chose its own colour ignores it. On the web the word currentColor reaches the markup and the tint is set as CSS color, so the cascade can answer it; on Photon each shape is rasterized and painted in its own colour.

new Drawing(Vectors.Mark, 240, tint: theme.TextPrimary)   // the monochrome half follows the theme

The subset, named the way the Markdown one is. Understood: viewBox, path, rect (with rx/ry), circle, ellipse, line, polyline, polygon, nested g, transform (translate / scale / rotate / skew / matrix, baked into the path data rather than carried), fill, stroke, stroke-width, fill-rule, the three opacities, the same properties written in a style attribute, and colours as #rgb / #rrggbb / #rrggbbaa / rgb() / rgba() / none / currentColor / the basic names. Dropped, deliberately: patterns, clipPath, mask, filter, use, image and text: each needs a paint server this model has no room for, or a font. Those shapes arrive MISSING rather than filled with a colour nobody chose, and the build says which file it skipped.

A run of colours

Since 0.2.0-preview.31

linearGradient and radialGradient are understood, with their stops, in either units (objectBoundingBox, the default, is a FRACTION of the shape's own box; userSpaceOnUse measures on the viewBox grid), and href is followed for a palette two gradients share. The defs are read in a pass of their own, so a fill may name a gradient the file declares after it, which is what half the exporters in the world write.

Each target paints the run the way it natively can. On the web the artwork carries its own defs and every shape names one with url(#…), so the browser interpolates at whatever size the box ends up; the id is a hash of the gradient itself, so one run used by two shapes is declared once and the server and the client twin land on the same string. On Photon the same alpha mask the rasterizer already made is filled with the engine's own gradient paint, which is the path gradient TEXT already used: no new draw command and no new shader entry point.

Two fences: a run crosses with two stops on Photon (the first and the last, because the engine's paint interpolates between a pair; multi-stop is its own slice), and gradientTransform, spreadMethod and a radial's focal point are dropped. A paint server the reader does not understand still paints NOTHING, which is what every paint server did before this.

🏗️ Technical Architecture

The icon system is built on a provider-based architecture:

  1. IIconProvider: Interface in eQuantic.UI.Core for resolving SVGs.
  2. Icon Component: Unified component in eQuantic.UI.Components that uses registered providers.
  3. Asset Management: Icons are rendered as lightweight SVGs directly in the DOM, maintaining full CSS styling compatibility (colors, sizes, animations).

🔄 Custom Icon Sets

You can implement your own icon provider by implementing IIconProvider and registering it in DI:

public class MyIconProvider : IIconProvider
{
    public bool CanResolve(string name) => /* check if icon exists */;

    public IComponent? CreateIcon(string name, int size = 24, double strokeWidth = 2,
        string color = "currentColor", string? className = null)
    {
        // Return SVG component
    }
}

// Register in Program.cs
builder.Services.AddSingleton<IIconProvider, MyIconProvider>();

Clone this wiki locally