Welcome to Vanilla Breeze
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
Surface and switch between versions of a page over time. Two modes (release versions / per-page history); navigate action ships in Phase 1.
<version-switcher> renders a small trigger button showing the current version of a page; clicking opens a picker popover listing every available version. Two modes auto-detected from the data shape:
/v1/page, /v2/page). Classic docs version selector.Override with data-mode="releases" or data-mode="history" if the data is ambiguous.
If no inline data-versions and no data-src are provided, the component falls back to <meta name="vb:versions-manifest"> and fetches the URL listed there. The provenance build pipeline emits this tag from the page's versionsManifest frontmatter (per meta-tag-contract-v1).
<!-- in <head>: --><meta itemprop="version" content="v2.1"><meta name="vb:versions-manifest" content="/data/versions/api.json"> <!-- in <body>: just drop the element — it fetches the manifest --><version-switcher aria-label="API version"></version-switcher>
Set data-banner to render a full-width warning banner above the trigger when the current version is archived AND a non-archived "latest" version exists. The banner uses role="region" + aria-live="polite" so screen-reader users hear the notice when it appears.
<version-switcher data-banner data-versions='[ {"id":"v2.1","label":"v2.1","url":"/v2.1/api"}, {"id":"v1.0","label":"v1.0","url":"/v1/api","current":true,"archived":true}]'></version-switcher> <!-- Renders an aside above the trigger: "You're viewing v1.0 (archived). Latest: v2.1 →" -->
<page-info>Set data-page-info-target="ID" to render the version list as a section inside the named <page-info>'s expandable panel rather than as a standalone trigger. The standalone trigger is hidden in this mode — readers find versions inside the page-info panel alongside authorship + provenance.
<page-info id="docs-page-info"> <details> <summary>…</summary> <div class="page-info-panel">…</div> </details></page-info> <version-switcher data-page-info-target="docs-page-info" data-src="/data/versions/api.json"></version-switcher>
Pick the action via data-action. Each action operates on the current page's versioned region — an element matched by data-versioned-region (defaults to [data-versioned], main).
| Action | Behavior |
|---|---|
navigate (default) | Sets location.href to the picked entry's url. Cancellable via version-switcher:before-navigate. |
swap | Fetches the picked URL, extracts its versioned region, and replaces the current versioned region in place. Updates <meta name="vb:version"> with the picked id. Uses document.startViewTransition for a crossfade when supported. Emits version-switcher:before-swap (cancellable) then version-switcher:swap. |
diff | Fetches the picked URL, computes a line-level diff against the current versioned region, and mounts a <change-set> sibling containing the diff (use the change-set's tracking-view buttons to flip between final / original / both). data-diff-position="before|after" controls placement. Emits version-switcher:before-diff (cancellable) then version-switcher:diff. |
<version-switcher data-action="swap" data-versions='[…]'></version-switcher> <main data-versioned> <h1>Authentication API — v2.1</h1> <p>…</p></main>
<version-switcher data-action="diff" data-diff-position="before" data-versions='[…]'></version-switcher> <main data-versioned>…</main><!-- A <change-set class="version-switcher-diff-host"> appears here on diff -->
| Use this | When |
|---|---|
<version-switcher> | Switch between known versions of THIS page (releases or history snapshots). |
<page-info> | Show the current version + provenance + authors. Complementary — not the same. page-info answers "what version is this?"; version-switcher answers "what other versions exist?". |
<time-index> | Site-wide changelog timeline (releases of the whole project). |
<change-set> | Inline visual diff of authored markup (<ins>/<del>). version-switcher Phase 2's diff action will reuse this as its renderer. |
Inline the version list as JSON, either via the data-versions attribute or a <script type="application/json" data-versions> child.
<version-switcher data-versions='[ {"id":"v2.1","label":"v2.1","url":"/v2.1/api","date":"2026-05-01","summary":"Adds rate-limit headers","current":true}, {"id":"v2.0","label":"v2.0","url":"/v2/api","date":"2026-01-15","summary":"Breaking: auth flow renamed"}, {"id":"v1.4","label":"v1.4","url":"/v1.4/api","date":"2025-08-10","summary":"Last v1 release","archived":true} ]'></version-switcher>
<version-switcher> <script type="application/json" data-versions> [ {"id":"r-2026-05-12","label":"Latest revision","url":"/policy","date":"2026-05-12","author":"Ada","summary":"Clarified data-retention period.","current":true}, {"id":"r-2026-04-01","label":"April revision","url":"/policy","date":"2026-04-01","author":"Bob","summary":"Updated EU references."}, {"id":"r-2026-01-15","label":"Q1 baseline","url":"/policy","date":"2026-01-15","author":"Carol","summary":"Initial public version."} ] </script></version-switcher>
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | Stable identifier (semver, commit sha, "current", etc.). |
label | string | no | Display label (defaults to id). |
url | string | recommended | URL to navigate to. Required for the navigate action. |
date | string (ISO-8601) | no | Renders as relative time with absolute on hover. |
author | string | no | Useful in history mode. |
summary | string | no | One-line description (release-note excerpt or commit message). |
archived | boolean | no | Renders the "archived" badge and mutes the entry. |
draft | boolean | no | Renders the "draft" badge. |
current | boolean | no | Marks the current entry. If absent, derived from a matching <meta name="vb:version"> or the first entry. |
versionUrl | string | no | Optional link out to a changelog anchor (matches the vb:version-url meta tag semantics). |
const sw = document.querySelector('version-switcher'); sw.addEventListener('version-switcher:before-navigate', (e) => { if (formIsDirty()) { if (!confirm(`Discard changes and switch to ${e.detail.entry.label}?`)) { e.preventDefault(); } }}); // Programmaticsw.switchTo('v2.0');
aria-haspopup="dialog", aria-expanded tracks open state, aria-label describes the version (default "Version").role="dialog" rendered by <pop-over> in the top layer; light-dismiss via Escape and outside click.aria-label like v1.4, released 9 months ago, archived.
aria-current="true" + visual highlight; focused first when the picker opens.| Attribute | Type | Default | Description |
|---|---|---|---|
data-versions | string (JSON) | — | Inline JSON array of version entries. |
data-src | string (URL) | — | URL of a JSON manifest to fetch when no inline data is provided. Falls back to <meta name="vb:versions-manifest"> if neither is set. |
data-mode | string | derived | releases | history — override the auto-detected mode. |
data-action | string | navigate | navigate | swap | diff. |
data-versioned-region | string (CSS selector) | [data-versioned], main | Selector for the swappable / diffable region in this page AND in the fetched response document. |
data-diff-position | string | before | before | after — where to mount the diff render relative to the versioned region. |
data-banner | boolean | false | Render an archived-version warning banner above the trigger when the current entry is archived AND a non-archived "latest" exists. |
data-page-info-target | string (ID) | — | ID of a <page-info> to mount inside as a section in its expandable panel; the standalone trigger is hidden in this mode. |
aria-label | string | Version | Trigger / picker label. |
| Event | Bubbles | Detail |
|---|---|---|
version-switcher:open | yes | — |
version-switcher:close | yes | — |
version-switcher:select | yes | { entry } |
version-switcher:before-navigate | yes (cancellable) | { entry } |
version-switcher:before-swap | yes (cancellable) | { entry } |
version-switcher:swap | yes | { entry, previousId } |
version-switcher:before-diff | yes (cancellable) | { entry } |
version-switcher:diff | yes | { entry, previousId, diffElement, opCount } |
version-switcher:error | yes | { message, entry?, error? } |
| Member | Description |
|---|---|
versions | Resolved version entries (read-only). |
currentId | Id of the current entry. |
openPicker() / closePicker() | Programmatic picker control. |
switchTo(id) | Programmatic selection — honors data-action. |
refresh() | Re-resolve the data source and re-render. |
<page-info> — current-version provenance display (Phase 3 will mount switcher inside it).<change-set> — the diff renderer Phase 2 will compose.<time-index> — site-wide release timeline.<pop-over> — the picker surface.