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-variables and 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-btn or .pa-tabs__item on :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.

John Doe

Administrator

Settings

Press Ctrl+K to preview the palette.
Sidebar
Display
Profile Panel
Body text size. All elements scale proportionally.
Commands
🚀
Deploy to Environment
Deploy a branch to an environment
g d
👤
Assign to User
Assign an item to a team member
g a
🧭
Go to Page
Navigate to a page
g g
🎨
Switch Theme
Change the visual theme
g t
Search
📦
Products
Search products
:products
📋
Orders
Search orders
:orders
👥
Users
Search users
:users
🧾
Invoices
Search invoices
:invoices