Activity Timeline .mv-activity-timeline

Timeline verticale tout en CSS sur un <ol> natif : puce, icône, initiales ou avatar en marqueurs sur cinq tons, connecteurs qui s’arrêtent avant chaque marqueur et passent en pointillés vers les étapes prévues, un marqueur « en cours » pulsant, des groupes par jour, et des mises en page alternée et compacte qui suivent la largeur du conteneur.

CatégorieAffichage de données
TypeCSS uniquement (.mv-activity-timeline)
Statutstable
Keywordstimeline, activity, activity feed, history, order history, order tracking, changelog, audit log, vertical timeline, events, feed

When to use

  • An order, a ticket or a shipment must show what happened and when, with the current status and the steps still to come
  • A product changelog or release history lists versions by date with a short note for each one
  • A side panel shows who did what on a project, grouped by day, with comments and attached files
  • An audit or account log lists dated events with a clear tone for successes, warnings and failures

Avoid when

  • Users must work through the steps of a process themselves, such as a wizard or onboarding → use Stepper instead
  • The need is a time ruler with a playhead for video, audio or animation editing → use Timeline Scrubber instead
  • The feed updates in real time and new entries should slide in as they arrive → use Animated List instead

Installation

node scripts/add.mjs activity-timeline --out ./src/marvelous

Agent IA avec le serveur MCP de Marvelous UI : install_components({ slugs: ["activity-timeline"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).

Fichiers copiés (dépendances comprises) : tokens/tokens.css, core/base.css, components/activity-timeline/activity-timeline.css.

Utilisation

Balisage de référence : partez de celui-ci et personnalisez-le avec les attributs, data-* et les variables CSS :

<div id="mv-at-demo" style="display:grid;gap:1.25rem;width:100%">
  <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,22rem),1fr));gap:1.25rem;align-items:start">

    <!-- Order history: icons, tones, a step in progress, upcoming steps -->
    <section class="mv-card" aria-labelledby="mv-at-order-title">
      <div class="mv-card-header" style="display:flex;align-items:start;justify-content:space-between;gap:1rem">
        <div>
          <h3 class="mv-card-title" id="mv-at-order-title">Order #MV-48213</h3>
          <p class="mv-card-description">Placed Sep 22, 2026 · 3 items · $248.00</p>
        </div>
        <span class="mv-badge" data-variant="info">In transit</span>
      </div>
      <div class="mv-card-content">
        <ol class="mv-activity-timeline" role="list" aria-label="Order history">
          <li class="mv-activity-timeline-item" data-tone="success">
            <span class="mv-activity-timeline-marker" aria-hidden="true">
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>
            </span>
            <div class="mv-activity-timeline-body">
              <time class="mv-activity-timeline-time" datetime="2026-09-22T10:14">Sep 22, 2026, 10:14 AM</time>
              <h4 class="mv-activity-timeline-title">Order placed</h4>
              <p class="mv-activity-timeline-description">Paid with Visa ending in 4242.</p>
            </div>
          </li>
          <li class="mv-activity-timeline-item" data-tone="success">
            <span class="mv-activity-timeline-marker" 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 8 12 3 3 8v8l9 5 9-5z"/><path d="m3 8 9 5 9-5M12 13v8"/></svg>
            </span>
            <div class="mv-activity-timeline-body">
              <time class="mv-activity-timeline-time" datetime="2026-09-23T16:02">Sep 23, 2026, 4:02 PM</time>
              <h4 class="mv-activity-timeline-title">Shipped</h4>
              <p class="mv-activity-timeline-description">Left the Rotterdam warehouse with DHL Express.</p>
            </div>
          </li>
          <li class="mv-activity-timeline-item" data-tone="warning">
            <span class="mv-activity-timeline-marker" 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 9v4M12 17h.01"/><path d="M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0z"/></svg>
            </span>
            <div class="mv-activity-timeline-body">
              <time class="mv-activity-timeline-time" datetime="2026-09-24T08:30">Sep 24, 2026, 8:30 AM</time>
              <h4 class="mv-activity-timeline-title">Held at customs</h4>
              <p class="mv-activity-timeline-description">Cleared after 6 hours. New estimate: <strong>Sep 26</strong>.</p>
            </div>
          </li>
          <li class="mv-activity-timeline-item" data-state="current" aria-current="step">
            <span class="mv-activity-timeline-marker" aria-hidden="true">
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 6h12v10H2z"/><path d="M14 9h4.5L22 12.5V16h-8"/><circle cx="6.5" cy="17.5" r="1.75"/><circle cx="17.5" cy="17.5" r="1.75"/></svg>
            </span>
            <div class="mv-activity-timeline-body">
              <time class="mv-activity-timeline-time" datetime="2026-09-25T07:48">Sep 25, 2026, 7:48 AM</time>
              <h4 class="mv-activity-timeline-title">In transit to Chicago, IL</h4>
              <div class="mv-activity-timeline-content">
                <div class="mv-activity-timeline-card" style="display:flex;align-items:center;justify-content:space-between;gap:.75rem;flex-wrap:wrap">
                  <div style="min-width:0">
                    <div style="color:var(--mv-fg-muted);font-size:var(--mv-text-xs)">DHL tracking number</div>
                    <div style="font-family:var(--mv-font-mono);font-size:var(--mv-text-xs);overflow-wrap:anywhere">JD014600006281234567</div>
                  </div>
                  <a class="mv-button" data-variant="outline" data-size="sm" href="#mv-at-order-title">Track package</a>
                </div>
              </div>
            </div>
          </li>
          <li class="mv-activity-timeline-item" data-state="upcoming">
            <span class="mv-activity-timeline-marker" 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 11 9-7 9 7"/><path d="M5 10v10h14V10"/><path d="M10 20v-6h4v6"/></svg>
            </span>
            <div class="mv-activity-timeline-body">
              <time class="mv-activity-timeline-time" datetime="2026-09-26">Expected Sep 26, 2026</time>
              <h4 class="mv-activity-timeline-title">Delivery</h4>
              <p class="mv-activity-timeline-description">Signature required at 1450 W Randolph St.</p>
            </div>
          </li>
        </ol>
      </div>
    </section>

    <!-- Activity log: compact, grouped by day, avatars -->
    <section class="mv-card" aria-labelledby="mv-at-activity-title">
      <div class="mv-card-header">
        <h3 class="mv-card-title" id="mv-at-activity-title">Activity</h3>
        <p class="mv-card-description">Atlas redesign</p>
      </div>
      <div class="mv-card-content">
        <ol class="mv-activity-timeline" data-variant="compact" role="list" aria-label="Project activity">
          <li class="mv-activity-timeline-group">
            <h4 class="mv-activity-timeline-heading" id="mv-at-today">Today</h4>
            <ol role="list" aria-labelledby="mv-at-today">
              <li class="mv-activity-timeline-item">
                <span class="mv-activity-timeline-marker"><img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop offset='0' stop-color='%23fde68a'/%3E%3Cstop offset='1' stop-color='%23d97706'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='64' height='64' fill='url%28%23g%29'/%3E%3Cpath d='M10 66c1-12 10-19 22-19s21 7 22 19z' fill='%231f2937'/%3E%3Crect x='27' y='36' width='10' height='12' rx='4' fill='%23e7b590'/%3E%3Ccircle cx='32' cy='27' r='11' fill='%23e7b590'/%3E%3Cpath d='M20.5 26c0-8 5-13 11.5-13s11.5 5 11.5 13c-2-4-6-6.5-11.5-6.5S22.5 22 20.5 26z' fill='%237c2d12'/%3E%3C/svg%3E" alt=""></span>
                <div class="mv-activity-timeline-body">
                  <div class="mv-activity-timeline-header">
                    <p class="mv-activity-timeline-title"><strong>Aiko Tanaka</strong> commented on <a href="#mv-at-activity-title">Checkout flow v3</a></p>
                    <time class="mv-activity-timeline-time" datetime="2026-09-25T10:42">10:42 AM</time>
                  </div>
                  <div class="mv-activity-timeline-content">
                    <blockquote><p>Can we keep the promo code field collapsed by default? It pushes the Pay button below the fold on small phones.</p></blockquote>
                  </div>
                </div>
              </li>
              <li class="mv-activity-timeline-item">
                <span class="mv-activity-timeline-marker"><img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop offset='0' stop-color='%2399f6e4'/%3E%3Cstop offset='1' stop-color='%230f766e'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='64' height='64' fill='url%28%23g%29'/%3E%3Cpath d='M10 66c1-12 10-19 22-19s21 7 22 19z' fill='%23f8fafc'/%3E%3Crect x='27' y='36' width='10' height='12' rx='4' fill='%23b98363'/%3E%3Ccircle cx='32' cy='27' r='11' fill='%23b98363'/%3E%3Cpath d='M20.5 26c0-8 5-13 11.5-13s11.5 5 11.5 13c-2-4-6-6.5-11.5-6.5S22.5 22 20.5 26z' fill='%231c1917'/%3E%3C/svg%3E" alt=""></span>
                <div class="mv-activity-timeline-body">
                  <div class="mv-activity-timeline-header">
                    <p class="mv-activity-timeline-title"><strong>Mateo Álvarez</strong> uploaded 2 files</p>
                    <time class="mv-activity-timeline-time" datetime="2026-09-25T09:15">9:15 AM</time>
                  </div>
                  <div class="mv-activity-timeline-content">
                    <ul class="mv-activity-timeline-attachments" role="list">
                      <li><a class="mv-activity-timeline-attachment" href="#mv-at-activity-title"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14 3H6a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V8z"/><path d="M14 3v5h5"/></svg>checkout-mobile.fig <small>4.2 MB</small></a></li>
                      <li><a class="mv-activity-timeline-attachment" href="#mv-at-activity-title"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14 3H6a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V8z"/><path d="M14 3v5h5M9 13h6M9 17h4"/></svg>user-test-notes.pdf <small>860 KB</small></a></li>
                    </ul>
                  </div>
                </div>
              </li>
              <li class="mv-activity-timeline-item" data-tone="success">
                <span class="mv-activity-timeline-marker" aria-hidden="true">
                  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>
                </span>
                <div class="mv-activity-timeline-body">
                  <div class="mv-activity-timeline-header">
                    <p class="mv-activity-timeline-title"><strong>Deploy #1284</strong> to staging succeeded</p>
                    <time class="mv-activity-timeline-time" datetime="2026-09-25T08:03">8:03 AM</time>
                  </div>
                </div>
              </li>
            </ol>
          </li>
          <li class="mv-activity-timeline-group">
            <h4 class="mv-activity-timeline-heading" id="mv-at-yesterday">Yesterday</h4>
            <ol role="list" aria-labelledby="mv-at-yesterday">
              <li class="mv-activity-timeline-item">
                <span class="mv-activity-timeline-marker"><img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop offset='0' stop-color='%23fecdd3'/%3E%3Cstop offset='1' stop-color='%23e11d48'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='64' height='64' fill='url%28%23g%29'/%3E%3Cpath d='M10 66c1-12 10-19 22-19s21 7 22 19z' fill='%23fafaf9'/%3E%3Crect x='27' y='36' width='10' height='12' rx='4' fill='%238d5a3b'/%3E%3Ccircle cx='32' cy='27' r='11' fill='%238d5a3b'/%3E%3Cpath d='M20.5 26c0-8 5-13 11.5-13s11.5 5 11.5 13c-2-4-6-6.5-11.5-6.5S22.5 22 20.5 26z' fill='%23111827'/%3E%3C/svg%3E" alt=""></span>
                <div class="mv-activity-timeline-body">
                  <div class="mv-activity-timeline-header">
                    <p class="mv-activity-timeline-title"><strong>Priya Nair</strong> moved <a href="#mv-at-activity-title">Payment errors</a> to In review</p>
                    <time class="mv-activity-timeline-time" datetime="2026-09-24T17:37">5:37 PM</time>
                  </div>
                </div>
              </li>
              <li class="mv-activity-timeline-item" data-tone="danger">
                <span class="mv-activity-timeline-marker" aria-hidden="true"></span>
                <div class="mv-activity-timeline-body">
                  <div class="mv-activity-timeline-header">
                    <p class="mv-activity-timeline-title"><strong>Build #1283</strong> failed on main</p>
                    <time class="mv-activity-timeline-time" datetime="2026-09-24T14:10">2:10 PM</time>
                  </div>
                  <p class="mv-activity-timeline-description">3 tests failed in cart.spec.ts</p>
                </div>
              </li>
              <li class="mv-activity-timeline-item" data-tone="accent">
                <span class="mv-activity-timeline-marker" aria-hidden="true"><span>KO</span></span>
                <div class="mv-activity-timeline-body">
                  <div class="mv-activity-timeline-header">
                    <p class="mv-activity-timeline-title"><strong>Kwame Osei</strong> joined the project</p>
                    <time class="mv-activity-timeline-time" datetime="2026-09-24T11:20">11:20 AM</time>
                  </div>
                </div>
              </li>
            </ol>
          </li>
        </ol>
      </div>
    </section>
  </div>

  <!-- Changelog: alternates on wide containers, stacks on the left below 40rem -->
  <section class="mv-card" aria-labelledby="mv-at-changelog-title">
    <div class="mv-card-header">
      <h3 class="mv-card-title" id="mv-at-changelog-title">Changelog</h3>
      <p class="mv-card-description">What shipped in Atlas this quarter.</p>
    </div>
    <div class="mv-card-content">
      <ol class="mv-activity-timeline" data-variant="alternate" role="list" aria-label="Releases">
        <li class="mv-activity-timeline-item" data-state="current">
          <span class="mv-activity-timeline-marker" aria-hidden="true"></span>
          <div class="mv-activity-timeline-body">
            <time class="mv-activity-timeline-time" datetime="2026-09-25">Rolling out now</time>
            <h4 class="mv-activity-timeline-title">Bulk editing <span class="mv-badge" data-variant="secondary">v3.3.0</span></h4>
            <p class="mv-activity-timeline-description">Select up to 500 rows and change owner, status or due date in one go. Reaching all workspaces by Sep 30.</p>
          </div>
        </li>
        <li class="mv-activity-timeline-item" data-tone="accent">
          <span class="mv-activity-timeline-marker" 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 3.5 14.4 9l5.6.6-4.2 3.8 1.2 5.6L12 16.1 7 19l1.2-5.6L4 9.6 9.6 9z"/></svg>
          </span>
          <div class="mv-activity-timeline-body">
            <time class="mv-activity-timeline-time" datetime="2026-09-18">Sep 18, 2026</time>
            <h4 class="mv-activity-timeline-title">Saved views <span class="mv-badge" data-variant="secondary">v3.2.0</span></h4>
            <p class="mv-activity-timeline-description">Keep your filters, sorting and columns, then share the view with a link.</p>
            <div class="mv-activity-timeline-content">
              <ul>
                <li>Pin up to 10 views in the sidebar</li>
                <li>Views follow the workspace time zone</li>
              </ul>
            </div>
          </div>
        </li>
        <li class="mv-activity-timeline-item" data-tone="success">
          <span class="mv-activity-timeline-marker" aria-hidden="true">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2 4 14h7l-1 8 9-12h-7z"/></svg>
          </span>
          <div class="mv-activity-timeline-body">
            <time class="mv-activity-timeline-time" datetime="2026-09-04">Sep 4, 2026</time>
            <h4 class="mv-activity-timeline-title">Exports 4x faster <span class="mv-badge" data-variant="secondary">v3.1.2</span></h4>
            <p class="mv-activity-timeline-description">CSV and Excel exports of 100,000 rows now finish in under 8 seconds.</p>
          </div>
        </li>
        <li class="mv-activity-timeline-item" data-tone="danger">
          <span class="mv-activity-timeline-marker" 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 3 4 6v6c0 4.5 3.4 8 8 9 4.6-1 8-4.5 8-9V6z"/><path d="m9 12 2 2 4-4"/></svg>
          </span>
          <div class="mv-activity-timeline-body">
            <time class="mv-activity-timeline-time" datetime="2026-08-27">Aug 27, 2026</time>
            <h4 class="mv-activity-timeline-title">Security update <span class="mv-badge" data-variant="secondary">v3.1.1</span></h4>
            <p class="mv-activity-timeline-description">Sessions now expire after 12 hours of inactivity. Please update self-hosted installs.</p>
          </div>
        </li>
      </ol>
    </div>
  </section>
</div>

API

Attributes

NameTypeDefaultDescription
data-variantalternate | compact(left-aligned)On .mv-activity-timeline. alternate: entries on both sides of a centered rail, dates facing the text, once the list is at least 40rem wide (container query), left-aligned below. compact: smaller markers and tighter spacing, for side panels.
data-toneneutral | accent | success | warning | dangerneutralOn an entry or on its marker: color of the dot or the icon disc (soft tint).
data-statecurrent | upcomingOn an entry. current: solid marker with a halo and a pulsing ring (static under reduced motion); aria-current="step" has the same effect. upcoming: hollow marker, muted title, dashed connector leading to it.
data-sidestart | endOn an entry, in the alternate layout: forces its side instead of the automatic alternation.

CSS classes

NameDescription
mv-activity-timelineOn an <ol> (or <ul>) with role="list". Its children are entries, or day groups.
mv-activity-timeline-itemOne entry (<li>): a marker and a body side by side, joined to the next entry by a connector.
mv-activity-timeline-markerThe marker. Empty: a dot. With an <svg>: an icon disc. With a <span>: initials. With an <img alt="">: an avatar. Add aria-hidden="true" when it is decorative.
mv-activity-timeline-bodyText column: time, title, description, content, in any order.
mv-activity-timeline-timeOn a <time datetime>: date or time, muted and tabular.
mv-activity-timeline-titleEntry title (heading or <p>); may hold <strong>, links and a .mv-badge.
mv-activity-timeline-headerOptional row holding the title and the time side by side (activity feed style); wraps on narrow widths.
mv-activity-timeline-descriptionSecondary text under the title.
mv-activity-timeline-contentFree content under the text: a card, a <blockquote> (styled as a quoted comment), a <ul> of notes, attachments.
mv-activity-timeline-cardFramed box for details inside the content (tracking number, summary, diff).
mv-activity-timeline-attachmentsRow of attachment chips (<ul role="list">).
mv-activity-timeline-attachmentOne file chip (<a> or <span>): an icon, a name and an optional <small> for the size.
mv-activity-timeline-groupA day group (<li>): a .mv-activity-timeline-heading followed by a nested <ol> of entries. Each group has its own rail.
mv-activity-timeline-headingGroup label (Today, Sep 24, 2026…), with a hairline after it; a centered pill in the alternate layout.

CSS variables

NameDefaultDescription
--mv-activity-timeline-marker-size2rem (compact: 1.5rem)Width of the marker column and size of icon, initials and avatar markers.
--mv-activity-timeline-dot-size0.75rem (compact: 0.5rem)Size of plain dot markers.
--mv-activity-timeline-gap0.875rem (compact: 0.625rem)Space between the marker column and the text.
--mv-activity-timeline-space1.5rem (compact: 1rem)Vertical space between entries.
--mv-activity-timeline-linevar(--mv-border)Connector color.
--mv-activity-timeline-line-width2px (compact: 1.5px)Connector thickness.

Accessibility

A native ordered list: put role="list" on the <ol> (and on nested group lists) so Safari keeps list semantics without bullets, and give it an aria-label or aria-labelledby. Each date is a <time datetime> with the full date in visible text or in its datetime. Markers carry no meaning on their own: mark them aria-hidden="true" (or give avatars alt=""), and write the status in the title or a badge, never with color alone. For the step in progress, add aria-current="step" (it also applies the current styling). Day groups are nested lists labelled by their heading. The pulsing ring stops under reduced motion (OS setting or data-motion="reduce") and in print; the static halo stays so the current step is still marked. In forced colors, connectors and markers use CanvasText and the current marker gets a Highlight outline. Logical properties throughout, so the rail sits on the right in right-to-left pages. No JavaScript and nothing focusable except the links you add.

Cette page a été traduite par IA. Signaler un problème de traduction