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-page

Camera-zoom unfold to a new route. Click the source hex (or any <a data-hp-unfold> text link) and the source's colour rapidly expands to cover the viewport — then the destination page is revealed underneath. Browser back reverses the animation: the destination fades out as a viewport-sized hex shrinks back to the source's original position.

Backed by cross-document View Transitions (@view-transition: navigation: auto in global.css). Browsers without support navigate without the animation — the link still works. Filled / saturated sources work best; outline-style sources still animate but the colour read is dominated by the canvas-coloured interior at scale.

Examples API Intent Changelog

The preview attribute plays the expand + hold + shrink cycle in place, no navigation. Use this for showcase pages, dev workflow, or any context where you want to demo the animation without leaving the page. The source's content (label) stays at its original size — only the colour expands.

play play play <body> <hp-unfold-page preview> <hp-cell variant="action" filled slot="source">play</hp-cell> </hp-unfold-page> </body>

Click palette — the action's primary colour floods the viewport, then the palette page appears. Browser back returns with the inverse shrink animation.

palette hp-cell motion <body> <hp-unfold-page href="/palette"> <hp-cell variant="action" filled slot="source">palette</hp-cell> </hp-unfold-page> </body>

Any <a> with the data-hp-unfold attribute triggers the same view-transition expand. The link's own CSS color becomes the overlay fill — brand-coloured links flood the viewport in their brand colour. Try: go to palette or jump to hp-cell .

<body> <a href="/palette" data-hp-unfold style="color: var(--hp-secondary)"> go to palette </a> <!-- Animation keyframes (global.css) --> @view-transition { navigation: auto; } ::view-transition-old(hp-unfold-source) { animation: hp-unfold-expand var(--hp-unfold-bloom) ease-out forwards; } ::view-transition-new(hp-unfold-source) { animation: hp-unfold-shrink var(--hp-unfold-bloom) ease-out forwards; } @keyframes hp-unfold-expand { from { transform: scale(1); } to { transform: scale(var(--hp-unfold-peak, 50)); } } @keyframes hp-unfold-shrink { from { transform: scale(var(--hp-unfold-peak, 50)); } to { transform: scale(1); } } </body>

Install

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

Properties

Property Attribute Type Default Description
href href string "" Target URL. Must be same-origin for cross-document View Transitions to engage; cross-origin navigations skip the VT and just navigate.
preview preview boolean false When set, clicking the source plays the expand-and-shrink animation in place without navigating. The overlay scales up to viewport coverage, holds, then scales back down. Use for showcase demos and visual previews.

Slots

Slot Description
source The hex / element that triggers the expand

When to use

Use <hp-unfold-page> with a filled or saturated hex source (hp-cell variant="action" filled, variant="anchor", or any toned cell) for high-impact navigation moments — entering a detail page, launching a quest, opening a settings surface. Use the data-hp-unfold attribute on regular text links to give them the same brand-coloured expand. Set the link's CSS color deliberately — that's the colour that floods the viewport. Mix freely with non-unfold navigation. Sidebar / nav-rail links that don't have data-hp-unfold get the default cross-document fade — both feel like Hexpunk, the unfold is the flourish. Use on every link. The expand is a signal that "you're going somewhere important" — firing on every nav dilutes the signal. Use for in-place detail expansion (<hp-unfold-list>) or modal detail views (<hp-unfold-overlay>). Reserve this for actual route navigation.

Browser support

Cross-document View Transitions are Chrome 126+ (stable). Firefox and Safari ship same-document transitions but not cross-document yet (at the time of writing). On unsupported browsers, the link still works — it just navigates without animation. The showcase enables transitions globally via @view-transition: navigation: auto in global.css.

Back navigation

When the user returns to a page that was the source of a forward <hp-unfold-page> nav, this element detects the back-or-forward navigation (via the Performance Navigation Timing API) and the previous URL (via the Navigation API entries, falling back to document.referrer). If the previous URL matches this element's href, the source receives the view-transition-name at page load — and the ::view-transition-new shrink animation plays automatically.

Text-link sources (data-hp-unfold) currently only animate the forward direction. Back navigation falls back to the default cross-document fade. A future iteration can persist the last-clicked link's identity in sessionStorage and recreate the overlay on the back-target page.

Reduced motion

With prefers-reduced-motion: reduce, the expand and shrink keyframes are suppressed — the user sees a default cross-fade between pages, no scale tween.

No per-component entries in CHANGELOG.md yet.

esc