Dynamic Island
`<pura-dynamic-island>` is the iOS Dynamic Island: a floating black pill that morphs between named states. Declare the states in `states` (default `compact,expanded`); each one becomes a named slot. Set `state` and the island runs a FLIP animation: it measures the pill before and after the content swap and interpolates width, height and border-radius with WAAPI on a real spring `linear()` easing (sampled by `pura-spring`'s exported math, preset via `spring` or `stiffness`/`damping`/`mass`), while the outgoing pane blurs and fades out and the incoming pane blurs in. SSR paints the active state's pane fully styled, and switching `state` without JS still swaps the content via pure CSS. Reduced motion swaps instantly. Theme with `--pura-dynamic-island-bg/-fg/-radius/-<state>-radius/-padding/-shadow`. Each instance registers in `window.__puraDynamicIslands` by `data-pura-id` with `{ state, states, setState }` and mirrors live state in `data-pura-island-state`.
Preview
<!-- notification pill: compact dot expands into the full message -->
<pura-dynamic-island id="island">
<span slot="compact">1 new message</span>
<div slot="expanded" style="display: flex; align-items: center; gap: .75rem;">
<img src="/avatars/ana.jpg" alt="" width="36" height="36" style="border-radius: 50%;" />
<div>
<strong>Ana</strong>
<p>Lunch at noon?</p>
</div>
</div>
</pura-dynamic-island>
<script>
const island = document.getElementById("island");
island.addEventListener("statechange", (e) => console.log(e.detail));
island.setAttribute("state", "expanded");
</script>
<!-- custom states with a wobblier spring and a squarer expanded shape -->
<pura-dynamic-island states="compact,player" spring="wobbly"
style="--pura-dynamic-island-player-radius: 1.5rem;">
<span slot="compact">Now playing</span>
<div slot="player">...album art, title, controls...</div>
</pura-dynamic-island> Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
state | string | compact | Active state name; must match an entry of states. Changing it triggers the morph. |
states | string | compact,expanded | Comma-separated list of state names; each becomes a named slot and a pane. |
spring | "default" | "gentle" | "wobbly" | "stiff" | "slow" | "snappy" | snappy | Spring preset for the size morph (sampled into a CSS linear() easing). |
stiffness | number | — | Spring stiffness override. |
damping | number | — | Spring damping override. |
mass | number | — | Spring mass override. |
Installation
pura is copy-paste and dependency-free. Load the whole library, or just this component.
<link rel="stylesheet" href="/pura/tokens.css">
<script type="module" src="/pura/lib/dynamic-island.js"></script> import "./pura/lib/dynamic-island.js";