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-unfold-overlay

Lightbox-style hex overlay. Click / tap / Enter on the source opens a hex- clipped native <dialog> at the viewport centre containing the slotted detail content. Esc closes natively; a backdrop click closes via a manual listener (native <dialog> doesn't ship light dismiss). Uses showModal() so we inherit Top Layer, the ::backdrop pseudo, and a focus trap for free — no z-index management.

Companion to <hp-unfold-list> (ring expansion in place) and the still-to-come <hp-unfold-page> (camera-zoom into a new route via View Transitions). Three separate primitives with three separate navigation contracts.

Examples API Intent Changelog

Click player to spotlight the profile detail. Esc or backdrop click to close.

player

kira_chen

Level 42 hexcrafter — Western Loop division

Recent: completed Stardust Refactor · 12 minutes ago

profile
<body> <hp-grid> <hp-unfold-overlay q="0" r="0"> <hp-cell variant="anchor" slot="source">player</hp-cell> <h2>kira_chen</h2> <p>Level 42 hexcrafter — Western Loop division</p> <p>Recent: completed "Stardust Refactor"</p> <hp-cell variant="action" filled tabindex="0">profile</hp-cell> </hp-unfold-overlay> </hp-grid> const overlay = document.querySelector("hp-unfold-overlay"); overlay.addEventListener("hp-unfold-open", () => { /* analytics, prefetch */ }); overlay.addEventListener("hp-unfold-close", () => { /* … */ }); overlay.toggle(); // flip open / closed overlay.close(); // close if open overlay.open = true; // direct property write also works </body>

Same element outside a grid — the overlay still centers on the viewport.

details

Build #4082

Pushed to main by kira_chen

24 commits · 8 files changed · all green

deployed
<body> <hp-unfold-overlay> <hp-cell variant="action" slot="source" tabindex="0">details</hp-cell> <h2>Build #4082</h2> <p>Pushed to main by kira_chen</p> <hp-cell tone="positive" active>deployed</hp-cell> </hp-unfold-overlay> </body>

Install

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

Properties

Property Attribute Type Default Description
open open boolean false Reflected open / closed state. Setting it imperatively calls showModal / close on the inner <dialog>.

Events

Event Type Description
CustomEvent
hp-unfold-open Event When the overlay opens
hp-unfold-close Event When the overlay closes (backdrop or .close())

Slots

Slot Description
source The trigger element (always visible)
(default) The overlay body content

When to use

Reach for <hp-unfold-overlay> when the detail view is rich enough to demand the user's focused attention — profile cards, build details, item cards, settings panels. The modal contract makes "you're in detail mode" unambiguous. Slot the source as a single labelled hex (hp-cell variant="anchor" / variant="action") — it stays clickable as the trigger and the modal opens centred on viewport. Keep overlay content reasonably narrow. The hex clip-path cuts corners; wide rectangular layouts will lose their edges. Centred prose + one or two action hexes fits the shape naturally. Use for in-place expansion where the surrounding context should stay readable — that's <hp-unfold-list>'s job (ring bloom around the source). Use for navigating to a new route — that's <hp-unfold-page>'s job (cross-document camera-zoom via View Transitions). Stack overlays. Modal-on-modal is navigationally hostile; close the current one and re-open a different one.

Accessibility

showModal() traps focus inside the dialog while it's open and returns focus to the trigger on close — both native browser behaviours. The source gets tabindex="0" on slotchange (consumers can override). aria-pressed on the source mirrors the open state so hp-cell's hue swap engages without separate wiring.

Reduced motion

With prefers-reduced-motion: reduce, the scale + opacity tweens are suppressed — the overlay snaps open and closed instantly. The backdrop still appears, focus trap still engages, hue swap on the source remains (state signal, not decoration).

Roadmap

Source → overlay morph via View Transitions API — the source's bbox tweens into the overlay's bbox, more "spotlight unfold" than "scale from centre". Falls back gracefully to the current scale animation when View Transitions isn't supported. Optional tether arc back to the source slot (the unfold-tether token chain from DESIGN.md), drawn over the backdrop while the overlay is open.

No per-component entries in CHANGELOG.md yet.

esc