Skip to content

Commit deec5b5

Browse files
authored
feat: add version history page (#2025)
1 parent 105898a commit deec5b5

File tree

7 files changed

+803
-45
lines changed

7 files changed

+803
-45
lines changed

app/components/Package/Versions.vue

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,14 @@ function versionRoute(version: string): RouteLocationRaw {
9595
return packageRoute(props.packageName, version)
9696
}
9797
98+
// Route to the full versions history page
99+
const versionsPageRoute = computed((): RouteLocationRaw => {
100+
const [org, name = ''] = props.packageName.startsWith('@')
101+
? props.packageName.split('/')
102+
: ['', props.packageName]
103+
return { name: 'package-versions', params: { org, name } }
104+
})
105+
98106
// Version to tags lookup (supports multiple tags per version)
99107
const versionToTags = computed(() => buildVersionToTagsMap(props.distTags))
100108
@@ -521,15 +529,27 @@ function majorGroupContainsCurrent(group: (typeof otherMajorGroups.value)[0]): b
521529
id="versions"
522530
>
523531
<template #actions>
524-
<ButtonBase
525-
variant="secondary"
526-
class="text-fg-subtle hover:text-fg transition-colors min-w-6 min-h-6 -m-1 p-1 rounded"
527-
:title="$t('package.downloads.community_distribution')"
528-
classicon="i-lucide:file-stack"
529-
@click="openDistributionModal"
530-
>
531-
<span class="sr-only">{{ $t('package.downloads.community_distribution') }}</span>
532-
</ButtonBase>
532+
<div class="flex items-center gap-3">
533+
<LinkBase
534+
:to="versionsPageRoute"
535+
variant="button-secondary"
536+
class="text-fg-subtle hover:text-fg transition-colors min-w-6 min-h-6 p-1 rounded"
537+
:title="$t('package.versions.view_all_versions')"
538+
classicon="i-lucide:history"
539+
data-testid="view-all-versions-link"
540+
>
541+
<span class="sr-only">{{ $t('package.versions.view_all_versions') }}</span>
542+
</LinkBase>
543+
<ButtonBase
544+
variant="secondary"
545+
class="text-fg-subtle hover:text-fg transition-colors min-w-6 min-h-6 -m-1 p-1 rounded"
546+
:title="$t('package.downloads.community_distribution')"
547+
classicon="i-lucide:file-stack"
548+
@click="openDistributionModal"
549+
>
550+
<span class="sr-only">{{ $t('package.downloads.community_distribution') }}</span>
551+
</ButtonBase>
552+
</div>
533553
</template>
534554
<div class="space-y-0.5 min-w-0">
535555
<!-- Semver range filter -->

app/pages/package/[[org]]/[name].vue

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,9 @@ const { diff: sizeDiff } = useInstallSizeDiff(packageName, resolvedVersion, pkg,
211211
// → Preserve the server-rendered DOM, don't flash to skeleton.
212212
const nuxtApp = useNuxtApp()
213213
const route = useRoute()
214+
// Gates template rendering only — data fetches intentionally still run.
215+
// immediate is set once at mount — skipped requests won't re-fire on navigation, leaving data permanently missing.
216+
const isVersionsRoute = computed(() => route.name === 'package-versions')
214217
const hasEmptyPayload =
215218
import.meta.client &&
216219
nuxtApp.payload.serverRendered &&
@@ -479,7 +482,8 @@ const showSkeleton = shallowRef(false)
479482
</script>
480483

481484
<template>
482-
<DevOnly>
485+
<NuxtPage v-if="isVersionsRoute" />
486+
<DevOnly v-else>
483487
<ButtonBase
484488
class="fixed bottom-4 inset-is-4 z-50 shadow-lg rounded-full! px-3! py-2!"
485489
classicon="i-simple-icons:skeleton"
@@ -491,7 +495,7 @@ const showSkeleton = shallowRef(false)
491495
<span class="text-xs">Skeleton</span>
492496
</ButtonBase>
493497
</DevOnly>
494-
<main class="flex-1 pb-8">
498+
<main v-if="!isVersionsRoute" class="flex-1 pb-8">
495499
<!-- Scenario 1: SPA fallback — show skeleton (no real content to preserve) -->
496500
<!-- Scenario 2: SSR with missing payload — preserve server DOM, skip skeleton -->
497501
<PackageSkeleton

0 commit comments

Comments
 (0)