Tracing Beam <mv-tracing-beam>
Timeline rail beside an article or changelog: the trail fills with reading progress and each section node lights up as the beam passes it, driven by a native view timeline with a light JS fallback.
| Category | Scroll |
|---|---|
| Type | Web Component (<mv-tracing-beam>) |
| Status | stable |
| Keywords | beam, timeline, article, changelog, reading-progress, sections, view-timeline, scroll-driven |
When to use
- A changelog or release timeline should light each entry as the reader moves past it
- A blog post or case study should show reading progress as a rail along its left edge, with a node per section
- Long docs split into h2 sections need a quiet progress rail that marks the sections already read
Avoid when
- A thin bar at the top of the page or a percentage ring is enough → use Scroll Progress instead
- Readers need to jump between sections and see which ones they actually read → use Reading Map instead
- The content is a short section; the rail only makes sense beside content longer than the viewport
Install
node scripts/add.mjs tracing-beam --out ./src/marvelousAI agent with the Marvelous UI MCP server: install_components({ slugs: ["tracing-beam"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).
Files copied (dependencies included): tokens/tokens.css, core/base.css, core/dom.js, core/element.js, core/motion.js, components/tracing-beam/tracing-beam.js, components/tracing-beam/tracing-beam.css.
Usage
Canonical markup, to start from and customize with attributes, data-* and CSS variables:
<div id="mv-tb-demo" class="mv-scroll-area" data-orientation="vertical" tabindex="0" aria-label="Changelog">
<style>
#mv-tb-demo { width: min(100%, 44rem); height: 420px; margin-inline: auto; border: 1px solid var(--mv-border); border-radius: var(--mv-radius-xl); background: var(--mv-bg); }
#mv-tb-demo mv-tracing-beam { margin: 1.75rem 1.5rem 2.5rem 1rem; }
#mv-tb-demo article + article { margin-top: 2.75rem; }
#mv-tb-demo .meta { display: flex; align-items: center; gap: .5rem; min-height: 1.25rem; font-size: .75rem; color: var(--mv-fg-muted); }
#mv-tb-demo .meta b { padding: .1rem .5rem; border-radius: var(--mv-radius-full); border: 1px solid var(--mv-border-strong); color: var(--mv-fg); font: 600 .7rem/1.4 var(--mv-font-mono); }
#mv-tb-demo h3 { margin: .6rem 0 .45rem; font-size: 1.2rem; letter-spacing: -.02em; }
#mv-tb-demo p { margin: 0 0 .75rem; color: var(--mv-fg-muted); font-size: .92rem; line-height: 1.65; }
#mv-tb-demo .shot { height: 8.5rem; margin: 1rem 0; border-radius: var(--mv-radius-lg); border: 1px solid var(--mv-border); background: linear-gradient(135deg, color-mix(in oklch, var(--mv-accent) 16%, transparent), transparent 55%), repeating-linear-gradient(0deg, var(--mv-border) 0 1px, transparent 1px 1.5rem), var(--mv-bg-subtle); }
#mv-tb-demo ul { margin: 0; padding-left: 1.1rem; color: var(--mv-fg-muted); font-size: .9rem; line-height: 1.8; }
</style>
<mv-tracing-beam>
<article>
<div class="meta"><b>v4.2</b><time datetime="2026-09-22">September 22, 2026</time></div>
<h3>Scroll-driven components</h3>
<p>Eight scroll components now run on native CSS timelines, so the browser animates them without any script work while you scroll. Older browsers get a small JavaScript fallback automatically.</p>
<div class="shot" role="img" aria-label="Preview of the new scroll components"></div>
<p>Each one works inside any scroll container, like this changelog, not only the window.</p>
</article>
<article>
<div class="meta"><b>v4.1</b><time datetime="2026-09-02">September 2, 2026</time></div>
<h3>Command palette</h3>
<p>Fuzzy search, groups, keyboard shortcuts and a list of recent actions, in under 4 KB.</p>
<ul>
<li>Full keyboard navigation</li>
<li>Results announced to screen readers</li>
<li>Light and dark themes out of the box</li>
</ul>
</article>
<article>
<div class="meta"><b>v4.0</b><time datetime="2026-08-18">August 18, 2026</time></div>
<h3>Calendar and date picker</h3>
<p>Date ranges, ISO weeks, disabled days and built-in localization. The picker opens in a native popover, with no external library.</p>
<div class="shot" role="img" aria-label="Calendar preview"></div>
<p>Thanks to everyone who reported bugs during the beta.</p>
</article>
<article>
<div class="meta"><b>v3.9</b><time datetime="2026-07-30">July 30, 2026</time></div>
<h3>Faster installs</h3>
<p>The CLI now resolves dependencies in parallel and copies only the files a component needs. A typical install finishes in under a second.</p>
</article>
</mv-tracing-beam>
</div>API
Attributes
| Name | Type | Default | Description |
|---|---|---|---|
nodes | selector | none | :scope > :is(article, section, h2) | Elements that get a node on the rail (queried inside the host). A node lights up once the beam passes it. none: only the start dot. |
smooth | boolean | Spring-smoothed beam that trails behind fast scrolls (JS path; off with reduced motion). | |
scroller | selector | window | Reference scroll container (JS path). Default: the nearest scroll container, or the page. | |
fallback | boolean | Forces the JavaScript fallback (tests, browsers without animation-timeline). |
CSS classes
| Name | Description |
|---|---|
mv-tracing-beam-rail | Generated decorative rail (track, fill, head, nodes, dot); data-started once reading has begun (JS path). |
mv-tracing-beam-node | Generated node aligned with a target; data-passed once the beam has reached it (JS path). |
CSS variables
| Name | Default | Description |
|---|---|---|
--mv-tracing-beam-from / -to | faint accent / var(--mv-accent) | Trail gradient; -to also colors the tip and lit nodes. |
--mv-tracing-beam-gutter | 3rem | Content indent to make room for the rail. |
--mv-tracing-beam-offset | 0.25rem | Horizontal position of the rail. |
--mv-tracing-beam-dot | 1.25rem | Diameter of the start dot (and rail width); nodes are half this size. |
Accessibility
Purely decorative rail (aria-hidden, pointer-events: none); the content, its order and its focus are unchanged. Progress is 0 when the top of the content reaches the top of its scroll container and 1 when its bottom reaches the bottom, so the tip stays beside what is on screen. Native path: no script runs while scrolling. Reduced motion: no smoothing, no easing on nodes and no trailing glow; the line still tracks the position exactly. Forced colors: track in GrayText, trail and lit nodes in Highlight.