@trailvine/vanilla
Plain JS/DOM binding — renderTimelineSVG for a pure, SSR-safe markup string, and
mountTimeline for mounting (and cleanly unmounting) directly against a container element.
Both accept every field from the shared options reference
(points, layout, path, wrap?, mobileBehavior?),
plus the same caption/captionPosition fields described on the
React page — this page covers what's specific to the vanilla binding.
renderTimelineSVG
A pure function — no DOM required, safe to call during SSR.
function renderTimelineSVG<T>(
options: TrailvineOptions<T> & { caption?: string; captionPosition?: 'top' | 'bottom' }
): string; mobileBehavior: 'list' is fully supported here — both markups (SVG and the plain list) are emitted
together, toggled by a scoped @media query, no JavaScript required.
mobileBehavior: 'vertical' is not fully supported by this function alone — a
static string can't react to the viewport resizing after the fact. Use mountTimeline instead if
you need that behavior.
mountTimeline
Mounts a rendered timeline into a real container element, with lifecycle management.
function mountTimeline<T>(
container: HTMLElement,
options: TrailvineOptions<T> & { caption?: string; captionPosition?: 'top' | 'bottom' }
): MountResult;
interface MountResult {
unmount: () => void;
}
This is the only place mobileBehavior: 'vertical' genuinely works — it uses
matchMedia (with a legacy Safari fallback) to re-run layout at a different orientation when the
viewport crosses the breakpoint, which requires real, live browser access that a pure string function doesn't have.
Cleanup
Calling the returned unmount() clears the container and removes only that instance's
listener — mounting two timelines and unmounting one has no effect on the other, each call creates its own
closure-scoped listener.
const { unmount } = mountTimeline(document.getElementById('timeline'), options);
// later, e.g. in a framework's cleanup hook:
unmount(); Multi-instance safety
Every call gets its own scoped class/id prefix via a simple incrementing counter (not
crypto.randomUUID() — this keeps the package dependency-free and works identically during SSR
and in the browser).
Next steps
- Options reference — every field on
layout,path, andwrap. - React API — the equivalent React binding.
- Playground — tune every option live; the "Vanilla" tab under "Copy config as code" generates a real
mountTimelinesnippet from whatever you've configured.