Registry-ready release timeline
Ship a portable timeline block with app-owned release data, display dates, and body rendering.
- Accept app-owned release items instead of GitHub API responses.
- Render rich release notes through a scoped slot.
Overview
Latest release
Ship a portable timeline block with app-owned release data, display dates, and body rendering.
Improve install examples and clarify which data stays inside the consuming app.
Align public template metadata, screenshots, and cross-template navigation.
pnpm dlx shadcn-vue@latest add "https://ui.stackhacker.io/r/changelog-timeline.json"
<script setup lang="ts">
import { ChangelogTimeline, type ChangelogTimelineItem } from "@/components/changelog-timeline";
const releases: ChangelogTimelineItem[] = [
{
id: "2026-06-27",
tag: "v1.4.0",
title: "Registry-ready release timeline",
dateLabel: "Jun 27, 2026",
date: "2026-06-27",
body: "Ship a portable timeline block with app-owned release data.",
},
];
</script>
<template>
<ChangelogTimeline :items="releases" />
</template>ChangelogTimeline owns the timeline layout, latest marker, body slot boundary, and lightweight presentational states. Your app owns release fetching, repository configuration, normalization, caching, refresh lifecycle, date formatting, markdown rendering, and analytics.
The component intentionally does not import Nuxt MDC, parse markdown, call useFetch, know about ungh.cc, or require a GitHub release response shape. Pass app-shaped items with an already formatted dateLabel. Use the optional raw date only when you want the rendered time element to include a machine-readable datetime value.
Use the item slot when your app wants rich release notes. The slot receives item, index, and latest, so the consuming app can render MDC, prose components, custom HTML, or plain Vue markup without turning that renderer into a registry dependency.
<ChangelogTimeline :items="releases">
<template #item="{ item, latest }">
<article class="space-y-3">
<p>{{ item.body }}</p>
<p v-if="latest" class="font-medium">
This is the latest release.
</p>
</article>
</template>
</ChangelogTimeline>Keep GitHub release fetching in app code. Map your release source into ChangelogTimelineItem before passing it to the component.
| Source field | Timeline item field |
|---|---|
tag | tag and fallback key |
name or tag | title |
publishedAt | raw date plus app-formatted dateLabel |
markdown | body or slot-rendered rich content |
This keeps the generated registry item independent from network clients, API providers, and markdown modules.
Latest release
Ship a portable timeline block with app-owned release data, display dates, and body rendering.
Improve install examples and clarify which data stays inside the consuming app.
Align public template metadata, screenshots, and cross-template navigation.
<ChangelogTimeline loading /><ChangelogTimeline
:items="[]"
empty-title="No public releases"
empty-description="Connect your app-owned release source when you are ready to publish."
/><ChangelogTimeline
error="The release source did not respond."
show-retry
@retry="refreshReleases"
/>| Prop | Type | Default | Description |
|---|---|---|---|
items | ChangelogTimelineItem[] | [] | Release items supplied by your app. |
loading | boolean | false | Shows loading skeletons when no items are present. |
error | boolean | string | false | Shows an error state. A string is rendered as supporting error copy. |
latestLabel | string | "Latest release" | Label shown for the latest item. |
emptyTitle | string | "No releases yet" | Empty state title. |
emptyDescription | string | "Published releases will appear here as changelog entries." | Empty state description. |
errorTitle | string | "Could not load releases" | Error state title. |
errorDescription | string | "Check the release source or try loading the changelog again." | Error state description used when error is true. |
retryLabel | string | "Try again" | Retry button label. |
showRetry | boolean | false | Shows a native retry button in the error state. |
ariaLabel | string | "Changelog timeline" | Accessible label for the timeline list. |
class | HTMLAttributes["class"] | — | Additional CSS classes for the root element. |
| Field | Type | Description |
|---|---|---|
id | string | Stable item id. Falls back to tag or title-derived key when omitted. |
tag | string | Optional release tag supplied by your app. |
title | string | Release title. |
dateLabel | string | App-formatted display date. |
date | string | Optional machine-readable date for the datetime attribute. |
body | string | Optional plain text fallback body. |
latest | boolean | Marks this item as latest. Defaults to the first item when no item sets latest. |
| Slot | Props | Description |
|---|---|---|
item | { item, index, latest } | Rich body renderer for each release item. Falls back to item.body. |
| Event | Description |
|---|---|
retry | Emitted when the optional retry button is clicked. The app owns refresh behavior. |