Live demo — this example is server-driven; run the showcase locally for the interactive version.

Icon

Server-rendered inline SVG icons wrapped in PatternFly v6's .pf-v6-c-icon chrome. One Qute API across four icon sets — Font Awesome Solid / Regular / Brands and PatternFly's own pficons — with PF v6's full size, status, and behavior modifiers.

Examples

Basic

The simplest usage — pass a name in set:slug form. The icon defaults to medium size and is hidden from screen readers.

A standalone icon — defaults to medium size, no status color, hidden from screen readers.

Icon sets

Same API, four sources: fa, fa-regular, fa-brands, and pficon. The set prefix maps to the vendored directory under web/vendor/icons/.

fa:circle-check
fa-regular:envelope
fa-brands:github
pficon:cluster

Sizes

PF v6 ships six standalone size modifiers — sm, md, lg, xl, 2xl, 3xl — that resolve to global icon-size tokens.

sm md lg xl 2xl 3xl

Body sizes

Body-relative sizes (body-sm, body-default, body-lg) match the surrounding body text's icon-size token. Use these when an icon sits beside body copy.

Small body text with a body-sm icon.

Default body text with a body-default icon.

Large body text with a body-lg icon.

Heading sizes

Heading-relative sizes (heading-sm through heading-3xl) match the surrounding heading's icon-size token. Use these when an icon sits beside heading copy.

Heading with a heading-sm icon.
Heading with a heading-md icon.
Heading with a heading-lg icon.
Heading with a heading-xl icon.
Heading with a heading-2xl icon.
Heading with a heading-3xl icon.

Sizing within container

Pass iconSize to size the icon glyph independently of its size container. iconSize applies pf-m-{iconSize} to .pf-v6-c-icon__content while size stays on the wrapper.

size("3xl").iconSize("sm")
size("3xl").iconSize("md")
size("3xl").iconSize("lg")
size("3xl").iconSize("xl")
size("3xl").iconSize("3xl")

Inline

Set inline=true so the icon inherits the surrounding font size and color via PF's pf-m-inline modifier. Useful inside running prose.

Inline icons inherit the surrounding font size and color. For example, this check icon and this warning icon flow with the text — no extra size needed.

Status colors

Pass status to color the icon via PF v6 semantic tokens: info, success, warning, danger, or custom.

info success warning danger custom

In progress

inProgress=true adds pf-m-in-progress on the wrapper and renders a __progress overlay containing the PF v6 spinner. PF's CSS hides __content and shows __progress via opacity — no JS involved.

With inProgress(), the wrapper gets pf-m-in-progress and an additional __progress overlay is rendered containing the PF v6 spinner. PF's CSS hides __content (opacity 0) and shows __progress (opacity 1) — no JavaScript involved.

Custom in-progress icon

Pass progressIcon to render a Font Awesome / pficon glyph inside the __progress overlay instead of the default PF v6 spinner.

Icon.of("fa:download") with inProgress().progressIcon("fa:hourglass-half") — the hourglass glyph renders inside __progress instead of the default PF spinner.
Same component without progressIcon — falls back to the default components/feedback/spinner inside __progress.

With accessible label

Pass label to expose the icon to assistive technology — the rendered <svg> gets role="img" and the matching aria-label. Without a label, the SVG is marked aria-hidden="true".

Pass label to expose the icon to assistive tech. The rendered <svg> gets role="img" and the matching aria-label.
Without label, the SVG is marked aria-hidden="true" — appropriate when the icon is purely decorative or sits next to text that already conveys the meaning.

Documentation

Icon component props

Parameters accepted by {#include components/icon ... /}. Model mode: pass iconModel=<Icon> built in Java instead — the Java tab on each example shows the builder. All are passed as Qute named parameters.

* required
Name Type Default Description
* name String "set:slug" Icon identifier. set is one of fa, fa-regular, fa-brands, pficon. slug is the icon's filename without the .svg.
size "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "body-sm" | "body-default" | "body-lg" | "heading-sm" | "heading-md" | "heading-lg" | "heading-xl" | "heading-2xl" | "heading-3xl" Renders pf-m-{size} on the icon wrapper. Standalone sizes (sm3xl) use fixed tokens; body-* and heading-* inherit the matching text-relative token.
iconSize Same union as size Sizes the icon glyph independently from its container. Applies pf-m-{iconSize} to .pf-v6-c-icon__content while size stays on the wrapper.
status "info" | "success" | "warning" | "danger" | "custom" Adds pf-m-{status} to the icon's __content element, coloring the glyph via the matching semantic color token.
inline boolean false When truthy, applies pf-m-inline so the icon inherits the surrounding font size and color.
inProgress boolean false Adds pf-m-in-progress on the wrapper and renders an additional __progress overlay alongside __content. PF v6 CSS swaps which is visible via opacity — no JavaScript involved.
progressIcon String "set:slug" PF v6 spinner (components/feedback/spinner) Glyph rendered inside the __progress overlay when inProgress=true. Omit to use the dedicated PF v6 spinner component; pass a name to override with a Font Awesome / pficon glyph. Has no effect when inProgress is falsy.
label String Accessible label. When provided, the <svg> renders with role="img" and aria-label; otherwise it gets aria-hidden="true".

icons:svg() arguments

The icons Qute namespace exposes the raw resolver. Use it when you need just the <svg> without PF's .pf-v6-c-icon chrome — for example, inside a pf-v6-c-tree-view__node-toggle-icon or a button's pf-v6-c-button__icon. Always chain .raw so Qute doesn't HTML-escape the SVG.

* required
Position Type Description
* 1 — name String "set:slug" Same identifier as the component's name param. An unknown name renders a visible red placeholder marked data-missing-icon.
2 — label String (optional) Accessible label. Same semantics as the component's label: when present the SVG gets role="img" + aria-label, otherwise aria-hidden="true".

Returns a Qute RawString, so the usage is {icons:svg('fa:check').raw} or {icons:svg('pficon:cluster', 'Cluster overview').raw}.

Usage

Component vs. raw namespace. Prefer the {#include components/icon /} component whenever you want the full PF v6 icon chrome — size modifiers, status colors, inline / in-progress flags. Reach for {icons:svg(...).raw} only when you need a bare SVG inside markup that supplies its own chrome (tree-view toggles, button icon slots, code-editor controls).

Where the icons live. SVGs are vendored under runtime/.../META-INF/resources/web/vendor/icons/, one subdirectory per set:

Set prefix Vendor directory Source
fa vendor/icons/fa-solid/ Font Awesome 7 Solid
fa-regular vendor/icons/fa-regular/ Font Awesome 7 Regular
fa-brands vendor/icons/fa-brands/ Font Awesome 7 Brands
pficon vendor/icons/pficon/ PatternFly v6 pficons

Missing icons. A typo like fa:doesnotexist renders a red square placeholder carrying data-missing-icon and logs one WARN per unique missing name. The smoke tests assert that data-missing-icon never appears in any rendered route — so a bad name fails CI loudly rather than shipping silently.

Caching. Each SVG is read from the classpath once, parsed to extract its viewBox and inner markup, and cached for the JVM's lifetime. Missing names are cached too — repeated lookups don't re-walk the classpath.

Accessibility. When you pass a label, the SVG renders with role="img" and aria-label. Omit label for icons that are purely decorative or that sit next to text already conveying the meaning — they'll get aria-hidden="true" and stay out of the accessibility tree.

Design — why two APIs?

Why icons: (plural) and not icon:? The namespace name marks the catalog; the method name is a single lookup into it — same convention as users.find(id) in OO code. Reading {icons:svg('fa:check')} as "from the icons collection, get the SVG for fa:check" matches the mental model better than treating the namespace as a singular noun. The cost is a one-letter inconsistency with {#include components/icon /} (singular path) — we accepted that to keep the catalog metaphor.

Why a component and a namespace function? The two surfaces exist because PatternFly markup has two contexts:

  • Standalone icons need PF's full chrome — .pf-v6-c-icon wrapper for size / inline / in-progress modifiers, plus .pf-v6-c-icon__content for status color and iconSize. The {#include components/icon ... /} component is that chrome, parameterised. It uses Qute's named include parameters (e.g. size="2xl" status="success" inProgress=true) because the component takes eight optional inputs, and named params keep call sites readable.
  • PatternFly-supplied slots already provide their own chrome — .pf-v6-c-button__icon, .pf-v6-c-tree-view__node-toggle-icon, and friends. They expect a bare <svg> inside; wrapping in another .pf-v6-c-icon container would nest chrome inside chrome and break the layout. The {icons:svg(name).raw} namespace returns just the SVG — positional args (name, optional label) are enough because there's no chrome to configure.

Could it be unified? A single {icons:svg(name).chrome} accessor looks tempting, but Qute namespace functions are positional. Chrome with eight optional inputs would force either an unreadable positional call (icons:svg('fa:save', '2xl', null, 'success', false, true, null, 'Saving')) or a fluent builder Qute's grammar wasn't built for. The include's named parameters are the right fit for chrome configuration; the namespace function is the right fit for "just the SVG". That's why they coexist.

Rule of thumb. If you're authoring a standalone icon, reach for the component. If PatternFly's CSS already gives you an icon slot, reach for icons:svg(...).raw.