Skip to main content

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 — icon plus appearance: ICON gives an icon-only button.
  • Icon gallery ↗ — every token in the shipped sprite, searchable.