The framework's structural icons are drawn with a single masked primitive,
.pa-icon, so every glyph inherits the current text colour, scales
with font size, and is themeable from one place. At this layer an icon is a raw
<span class="pa-icon pa-icon--NAME"> — how the library's own
chrome renders affordances. There is also an
<.icon> component
that resolves names through swappable provider sets (Font Awesome, Heroicons,
Lucide, …) — see Icon Components. This page lists the masked icons that ship as
variables and explains the hover-to-fill affordance.
The masked icon primitive
Each masked glyph is a <span class="pa-icon pa-icon--name">. The glyph is
an SVG mask; the box is painted in currentColor and shows
through it. That means an icon automatically matches its surrounding text colour and
scales with font-size (default 1em, override with
--pa-icon-size).
Same class, sized with --pa-icon-size and coloured with color /
currentColor.
<!-- default 1em, inherits text colour -->
<span class="pa-icon pa-icon--search" aria-hidden="true"></span>
<!-- sized + coloured -->
<span class="pa-icon pa-icon--search"
style="--pa-icon-size: 2.4rem; color: var(--pc-accent);"></span>
Icon variables
These structural affordances ship as icon variables. Add the modifier class to a
.pa-icon span; each modifier points --pa-icon-src at the
matching --pa-icon-name token.
Close / clear / remove
--x
--clear
--remove
Disclosure & direction
The four chevron directions are one glyph rotated with a transform, so overriding the chevron re-skins all four at once. Same for the ellipsis (horizontal / vertical).
--chevron
--chevron-up
--chevron-right
--chevron-down
--chevron-left
--caret-up
--caret-down
--expand
--collapse
Actions
--add
--edit
--delete
--save
--copy
--download
Utility
--search
--refresh
--filter
--check
--ellipsis
--ellipsis-vertical
--link
--external-link
--settings
--bell
--user
--favorites
Severity
One shared family used by toasts, alerts, callouts, notifications and popconfirm, so every severity surface shows the same mark. Shown here in their semantic colours.
--info
--success
--warning
--danger
How the tokens re-skin
Most icons trace through a shared, cross-ecosystem contract, so a single override re-skins Pure Admin, the pure-css shell and the KeenMate web components together:
.pa-icon--search → var(--pa-icon-src)
→ var(--pa-icon-search)
→ var(--base-icon-search, /* inline Lucide fallback */)
-
--base-icon-*— the shared contract (published in@keenmate/base-css-variablesand mirrored by@keenmate/pure-css). Override once to re-skin everything. -
--pa-icon-*— Pure Admin's family; falls back to an inline Lucide glyph so icons always render even without the contract loaded. -
pa-only glyphs — a few (e.g.
--pa-icon-favorites) are Pure Admin-only and are not part of the--base-*contract, so they're defined directly with no--base-icon-*route.
To retarget a single glyph, set its --pa-icon-name (or the shared
--base-icon-name) at :root or on any subtree.
Hover-to-fill (enabled buttons & tabs)
An icon can swap to a filled variant when its enabled button or tab is hovered. It's opt-in on two axes:
-
Per glyph — an icon opts in by declaring a filled source on
--pa-icon-src-hover. Icons without one are left untouched. -
Per context — the swap only fires inside an enabled
.pa-btnor.pa-tabs__itemon:hover. Disabled controls never react.
The default Lucide set is outline-only
Lucide ships no filled glyphs, so hover-to-fill is dormant out of the box — the mechanism is present but there's nothing to fill to. To activate it, point--pa-icon-src-hover at a filled glyph from a set that has one —
Tabler (a Lucide look-alike), Fluent, or Material. The live demo below uses
a Tabler regular/filled star pair.
Live demo
Hover each control. The first uses a Tabler outline→filled star and morphs; the second is a
Lucide star and stays outline (nothing to fill to); the third is the same Tabler
star but disabled, so it never reacts despite being fillable (proving the disabled gate). No
transition — mask-image can't tween, so the fill is an instant swap.
How to enable it
Define a modifier that declares both a resting (outline) and a hover (filled) source. The framework's global rule swaps them on hover:
/* your glyph — resting outline + filled-on-hover source */
.pa-icon--star {
--pa-icon-src: var(--pa-icon-star); /* Lucide outline */
--pa-icon-src-hover: url("…tabler filled star…"); /* filled variant */
}
/* framework rule (ships in core) — no-op unless a glyph declared a hover src. */
.pa-btn:not(:disabled):hover .pa-icon,
.pa-tabs__item:not(:disabled):hover .pa-icon {
mask-image: var(--pa-icon-src-hover, var(--pa-icon-src));
}
The fallback to --pa-icon-src is what makes the rule safe to ship globally:
any icon that didn't declare a filled source simply keeps its resting glyph.