The icon library
Icons are referenced by token, never by file: a node carries
icon: "delete", and a resolver turns that into markup. Because everything
routes through that one resolver, the entire icon set is swappable without
touching a single UiNode.
For the icon node itself — fields, sizes, status colours, live preview — see
icon.
Tokens: semantic aliases vs raw ids
The default sprite ships two kinds of name:
- Semantic aliases —
delete,edit,add,back,download,show,folder,document,info,warning,error,success,ai,bot. These describe intent, so they survive a change of icon library. - Raw ids — the entire Lucide set (2000+ glyphs)
ships in the sprite, each under its Lucide name:
sparkles,rocket,fingerprint,brain, … Browse them at lucide.dev/icons.
Prefer the aliases where one fits. They are the reason a re-skin is a config change rather than a find-and-replace across your application code — raw ids are tied to Lucide's naming.
The alias list lives in
core/mc-semantic-ui-core/icons/icons.json.
An unknown token renders nothing visible — a missing icon is a typo, and it
fails where you can see it.
Pointing at a different sprite
// SSR
IconRenderer.setSpriteUrl("/assets/my-icons.svg");
// SPA
import { setIconSpriteUrl } from "/sui/renderer.js";
setIconSpriteUrl("/assets/my-icons.svg");
Replacing the scheme entirely
Inline SVG, an icon font, an image CDN — the resolver decides:
import { setIconResolver } from "/sui/renderer.js";
setIconResolver((name, opts) =>
`<i class="fa fa-${name}"${opts.title ? ` title="${opts.title}"` : ""}></i>`);
IconRenderer.setResolver((name, cssClass, title, id) -> "<i class=\"fa fa-" + name + "\"></i>");
Every renderer routes through the active resolver, so one call re-skins every icon on the page — including the ones inside built-in nodes such as menu items and table row actions.
Adding to the resolver
setIconResolver replaces everything, icon sets included — right for an app
that owns its icons, wrong for a plugin, which would take the icons of every
other plugin with it. A plugin wraps the active resolver instead:
import { getIconResolver, setIconResolver } from "/sui/renderer.js";
const previous = getIconResolver();
setIconResolver((name, opts) => name.startsWith("live-") ? liveBadge(name, opts) : previous(name, opts));
IconRenderer.Resolver previous = IconRenderer.getResolver();
IconRenderer.setResolver((name, cls, title, id) ->
name.startsWith("live-") ? liveBadge(name) : previous.render(name, cls, title, id));
For icons that are just symbols in a sprite, nothing of this is needed:
declare the sprite as an icon set and every
token with its prefix resolves from it — addIconSprite(prefix, url) in the
browser, which installAll calls for you.
Changing the default sprite
The sprite is a generated, committed artifact; the Maven build only copies
it. To change the set, edit the token → icon-id map in
core/mc-semantic-ui-core/icons/icons.json and regenerate:
cd core/mc-semantic-ui-core
npm run build:icons # rewrites src/main/resources/icons.svg
Commit the regenerated icons.svg. To move to a different icon library
altogether, install that library's static-SVG package, re-point the ids in
icons.json and regenerate — the semantic aliases, and therefore all your
application JSON, stay exactly the same.
Styling
.sui-icon is 1em × 1em, fill: none, stroke: currentColor. Colour an icon
by setting color on it or on an ancestor. An icon from an
icon set also carries sui-icon--set and is
filled instead: fill: currentColor; stroke: none, so a symbol's own fixed
colours win. The sprite's status helpers —
sui-icon--success, --warning, --danger, --muted — are ready-made
cssClass values.
See also
icon— the node reference.action—iconplusappearance: ICONgives an icon-only button.- Icon gallery ↗ — every token in the shipped sprite, searchable.