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 an assign_async/3 result, plain data, or a loading flag.
  • Slots for the states around loading: skeleton for your own markup to measure (the Suspense shape, together with error), empty_message with the empty attribute for a result that arrived empty, and error for a failed assign. The library styles none of them.
  • remember keeps 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/1 clears one scope, Skullet.Memory.clear/0 clears all of them, and entries expire after config :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 with theme={…} or once with <Skullet.provider>, which also sets mode, animation and speed for everything inside it.
  • Reveals: smart (instant for a flash, a quick crossfade for a refetch, one crossfade for small content, a page cascade otherwise), plus together, sequence, sweep and instant, with their timings and enter effects as custom properties.
  • registerReveal/2 and attach(root, {reveal: spec}) take a reveal of your own: order, enter, wipe, delay, duration, hold and choose.
  • <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-block and skullet-ignore hint 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-debug in the URL, skullet-debug on an element, or skullet-xray to 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. Pass nonce={…} to skeleton/1, provider/1, box/1 and Boot.boot/1.
  • priv/static ships an ES module for bundlers (skullet.js), the same engine as a script for pages without a build step (skullet.min.js, which defines window.Skullet), the inlined pre-paint script, and a hand-written skullet.d.ts.

Compatibility

  • Elixir ~> 1.18, Phoenix LiveView ~> 1.2, Phoenix.HTML ~> 4.3.
  • Under a Content Security Policy, script-src and style-src need the nonce; no 'unsafe-inline' is required.