Hexpunk
InstallConceptsElementsProsehp-cellhp-codehp-copyhp-hexhp-latexhp-visually-hiddenhp-buttonhp-checkboxhp-formhp-labelhp-radiohp-selecthp-sliderhp-togglehp-toggle-grouphp-badgehp-taghp-progresshp-spinnerhp-backgroundhp-clusterhp-collapsiblehp-demohp-gridhp-scroll-areahp-separatorhp-sidebarhp-toolbarhp-avatarhp-iconhp-pixelhp-linkhp-menubarhp-navigation-menuhp-tabshp-alert-dialoghp-context-menuhp-dialoghp-dropdown-menuhp-hover-cardhp-popoverhp-tooltiphp-bannerhp-toasthp-tetherhp-module-handlehp-unfold-listhp-unfold-overlayhp-unfold-pagehp-bondhp-link-nodePaletteAnimationsReleases

hp-pixel

Box-shadow pixel art. Static, smooth state morph, or sprite-sheet (sprite mode comes later). The two pixel icons below share the same nine logical pixels — hover them to see the smooth interpolation.

Examples API Intent Changelog
<body> <hp-pixel pixel-size="4" id="my-pixel"></hp-pixel> document.getElementById("my-pixel").art = "#.#.#\n#.#.#\n.....\n#.#.#\n#.#.#"; <!-- State morph (CodePen-style) --> <hp-pixel pixel-size="6" id="menu" tabindex="0"></hp-pixel> import { menu } from "@hexpunk/core/pixel-icons/menu"; const el = document.getElementById("menu"); el.states = menu; el.interactive = true; // wires :hover / :focus-visible / :active / [aria-pressed] <!-- Multi-colour palette --> el.palette = [ "var(--hp-primary)", "var(--hp-secondary)", "var(--hp-warn)", ]; el.art = "010\n121\n010"; // each digit indexes into palette </body>

Install

bun add @hexpunk/core lit
import "@hexpunk/core";

Properties

Property Attribute Type Default Description
art art string | undefined Static ASCII grid. `#` = lit, `.` = empty, digits index into `palette`.
state state string | undefined Current state when `.states` is set. Falls back to `"idle"`.
pixelSize pixel-size number 3 Pixel size in CSS px. Default `3`.
interactive interactive boolean false Auto-swap to `hover` / `focus` / `active` named states on the matching pseudo-classes. No JS state-flip required.

When to use

Use the states mode for interactive icons that need to morph between shapes (menu ↔ X, play ↔ pause). Setting interactive wires CSS-only fallbacks for :hover / :focus-visible / :active / [aria-pressed]. Use art mode for purely decorative pixel marks that don't change — favicons, achievement badges, tiny logos. Override --hp-pixel-shadow at runtime if you need to script frames imperatively (custom transitions, sprite playback). Don't set the shadow when interactive is enabled — the inline override beats the CSS-driven swaps. Reach for <hp-pixel> when you need stroke-icon parity. Use <hp-icon> for Lucide-style icons that should match icon-sm/md/lg tokens.

No per-component entries in CHANGELOG.md yet.

esc