Animated List — <mv-animated-list>
Animated notification feed: items appear one by one with a spring, smoothly pushing the others (FLIP), with an item limit, loop mode and an add() API.
Category Data display Type Web Component (<mv-animated-list>) Status stable Keywords list, notifications, feed, flip, stagger, activity
When to use
A live activity or notification feed should show new items sliding in and pushing older ones A landing page demonstrates a product by looping a sequence of sample notifications A chat-style log grows from the bottom with a cap on how many items stay visible
Avoid when
Notifications respond to user actions and should float over the page temporarily → use Toast instead The list is static data that users scan or search; the entrance animation only delays reading Users must catch up on what changed during an absence rather than watch a live stream → use While Away instead
Get Animated List. Included in every plan: the Pro pack ships all 226 components with the CLI and the MCP server used below.
See plans
Install
node scripts/add.mjs animated-list --out ./src/marvelous
AI agent with the Marvelous UI MCP server: install_components({ slugs: ["animated-list"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).
Files copied (dependencies included): tokens/tokens.css, core/base.css, core/element.js, core/motion.js, core/observe.js, components/animated-list/animated-list.js, components/animated-list/animated-list.css.
Usage
Canonical markup — start from it and customize with attributes, data-* and CSS variables:
<div id="al-demo" style="display:grid;gap:1rem;justify-items:center;width:100%;max-width:26rem">
<mv-animated-list id="al-demo-feed" interval="1500" max="5" loop fade aria-label="Recent activity" style="width:100%;height:23rem">
<div class="mv-notification">
<span class="mv-notification-icon" style="--mv-notification-icon-bg: oklch(0.68 0.16 150)" aria-hidden="true">$</span>
<div class="mv-notification-body">
<span class="mv-notification-title">Payment received <small>· Bank</small></span>
<p class="mv-notification-text">$249.00 from Nebula Studio</p>
</div>
</div>
<div class="mv-notification">
<span class="mv-notification-icon" style="--mv-notification-icon-bg: oklch(0.62 0.19 265)" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a8 8 0 0 1-11.6 7.1L4 20l1-4.6A8 8 0 1 1 21 12z"/></svg></span>
<div class="mv-notification-body">
<span class="mv-notification-title">Sofia Reyes <small>· Messages</small></span>
<p class="mv-notification-text">“Great, the homepage mockup is approved!”</p>
</div>
</div>
<div class="mv-notification">
<span class="mv-notification-icon" style="--mv-notification-icon-bg: oklch(0.7 0.17 55)" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m3 17 6-6 4 4 8-8"/><path d="M14 7h7v7"/></svg></span>
<div class="mv-notification-body">
<span class="mv-notification-title">Traffic spike <small>· Analytics</small></span>
<p class="mv-notification-text">+212% visits to the Pricing page</p>
</div>
</div>
<div class="mv-notification">
<span class="mv-notification-icon" style="--mv-notification-icon-bg: oklch(0.64 0.15 215)" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="4"/><path d="M4 21a8 8 0 0 1 16 0"/></svg></span>
<div class="mv-notification-body">
<span class="mv-notification-title">New sign-up <small>· Team</small></span>
<p class="mv-notification-text">Daniel Kim joined the Design workspace</p>
</div>
</div>
<div class="mv-notification">
<span class="mv-notification-icon" style="--mv-notification-icon-bg: oklch(0.6 0.2 330)" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2 4 6v6c0 5 3.4 9 8 10 4.6-1 8-5 8-10V6z"/><path d="m9 12 2 2 4-4"/></svg></span>
<div class="mv-notification-body">
<span class="mv-notification-title">Deployment complete <small>· CI/CD</small></span>
<p class="mv-notification-text">v2.4.0 is live in production · 0 errors</p>
</div>
</div>
<div class="mv-notification">
<span class="mv-notification-icon" style="--mv-notification-icon-bg: oklch(0.66 0.14 180)" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="17" rx="2"/><path d="M16 2v4M8 2v4M3 10h18"/></svg></span>
<div class="mv-notification-body">
<span class="mv-notification-title">Reminder <small>· Calendar</small></span>
<p class="mv-notification-text">Weekly product sync at 2:30 PM, Lovelace room</p>
</div>
</div>
</mv-animated-list>
<button class="mv-button" data-variant="outline" data-size="sm" type="button" data-al-add>Send a notification</button>
<script type="module">
const root = document.getElementById("al-demo");
const feed = root.querySelector("mv-animated-list");
let n = 0;
root.querySelector("[data-al-add]").addEventListener("click", () => {
n += 1;
const card = document.createElement("div");
card.className = "mv-notification";
const icon = document.createElement("span");
icon.className = "mv-notification-icon";
icon.setAttribute("aria-hidden", "true");
icon.textContent = "★";
const body = document.createElement("div");
body.className = "mv-notification-body";
const title = document.createElement("span");
title.className = "mv-notification-title";
title.textContent = `You have a new fan (${n})`;
const text = document.createElement("p");
text.className = "mv-notification-text";
text.textContent = "Someone added your project to their favorites";
body.append(title, text);
card.append(icon, body);
feed.add(card);
});
</script>
</div>
API
Attributes
Name Type Default Description intervalnumber 1600Delay between two items appearing (ms). maxnumber Maximum number of items shown; the oldest fade out. loopboolean Replays the queue forever (copies of the children) — ideal for demos. fromtop | bottom topSide where new items arrive (bottom = chat style). pausedboolean Pauses the queue. fadeboolean Fades the edge where items exit (--mv-animated-list-fade).
Methods
Name Description add(el)Inserts an item immediately, animated. Returns the item. next()Reveals the next queued item right away.
Events
Name Description mv-adddetail.item: the inserted item.
Content structure
Name Description childrenInitial queue (revealed in order).
CSS classes
Name Description mv-notificationReady-to-use notification card: -icon, -body, -title, -text.
CSS variables
Name Default Description --mv-animated-list-gapvar(--mv-space-3)Gap between items. --mv-animated-list-fade5remFade length (with fade). --mv-notification-icon-bgvar(--mv-accent)Notification icon background.
Accessibility
role=list / listitem. The feed pauses on hover and while focus is inside (time to read), when off-screen and when the tab is hidden. To announce additions, add aria-live="polite" on the element (off by default so screen readers aren’t flooded in loop mode). Reduced motion: items appear without animation.