Unreleased
0.1.0 - 2026-11-10
Added
<Skullet.skeleton>draws a skeleton of the component itself: your markup is rendered from a sample with its text transparent, measured by the browser, and covered with bars — one per wrapped line, one block per image or control. It takes anassign_async/3result, plain data, or aloadingflag.- Slots for the states around loading:
skeletonfor your own markup to measure (the Suspense shape, together witherror),empty_messagewith theemptyattribute for a result that arrived empty, anderrorfor a failed assign. The library styles none of them. rememberkeeps the data a skeleton last showed, in ETS on the node, so the next skeleton under the same scope and id is drawn from the real thing instead of the sample.Skullet.Memory.forget/1clears one scope,Skullet.Memory.clear/0clears all of them, and entries expire afterconfig :skullet, :memory_ttl_ms.- Theming through custom properties — base and highlight colours, radius,
shimmer/group-shimmer/pulse/none, speed, hold, and how much of each line is drawn — set per skeleton withtheme={…}or once with<Skullet.provider>, which also setsmode,animationandspeedfor everything inside it. - Reveals:
smart(instant for a flash, a quick crossfade for a refetch, one crossfade for small content, a page cascade otherwise), plustogether,sequence,sweepandinstant, with their timings and enter effects as custom properties. registerReveal/2andattach(root, {reveal: spec})take a reveal of your own:order,enter,wipe,delay,duration,holdandchoose.<Skullet.Boot.boot />draws the skeletons already in the server's HTML before the browser's first paint, from the same geometry, font metrics and shimmer the engine uses.<Skullet.box>stands in for what cannot be measured (a logo, a chart, a canvas);skullet-blockandskullet-ignorehint the measurement.- Images that decode after the content arrives fade in instead of popping, and show after ten seconds if they never do.
- A debug overlay outlines every reveal, and how far the content moved, with
?skullet-debugin the URL,skullet-debugon an element, orskullet-xrayto see the sample through the skeleton. - Works under a Content Security Policy without
'unsafe-inline': themes and boxes are<style>blocks signed with the page's nonce, and so is the boot script. Passnonce={…}toskeleton/1,provider/1,box/1andBoot.boot/1. priv/staticships an ES module for bundlers (skullet.js), the same engine as a script for pages without a build step (skullet.min.js, which defineswindow.Skullet), the inlined pre-paint script, and a hand-writtenskullet.d.ts.
Compatibility
- Elixir
~> 1.18, Phoenix LiveView~> 1.2, Phoenix.HTML~> 4.3. - Under a Content Security Policy,
script-srcandstyle-srcneed the nonce; no'unsafe-inline'is required.