Skip to content

Commit 1df3da5

Browse files
committed
fix(provenance): a11y and hydration issues
1 parent 86530fc commit 1df3da5

1 file changed

Lines changed: 57 additions & 46 deletions

File tree

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

Lines changed: 57 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ watch(
113113
},
114114
)
115115
116-
// Fetch provenance details when the displayed version has attestations
117116
const {
118117
data: provenanceData,
119118
status: provenanceStatus,
@@ -130,15 +129,18 @@ const {
130129
immediate: false,
131130
},
132131
)
133-
watch(
134-
() => [displayVersion.value?.version, hasProvenance(displayVersion.value)],
135-
() => {
132+
if (import.meta.client) {
133+
watchEffect(() => {
136134
if (displayVersion.value && hasProvenance(displayVersion.value)) {
137135
fetchProvenance()
138136
}
139-
},
140-
{ immediate: true },
141-
)
137+
})
138+
}
139+
140+
const provenanceBadgeMounted = ref(false)
141+
onMounted(() => {
142+
provenanceBadgeMounted.value = true
143+
})
142144
143145
// Keep latestVersion for comparison (to show "(latest)" badge)
144146
const latestVersion = computed(() => {
@@ -294,8 +296,6 @@ function getDependencyCount(version: PackumentVersion | null): number {
294296
return Object.keys(version.dependencies).length
295297
}
296298
297-
// Check if a version has provenance/attestations
298-
// The dist object may have attestations that aren't in the base type
299299
function hasProvenance(version: PackumentVersion | null): boolean {
300300
if (!version?.dist) return false
301301
const dist = version.dist as NpmVersionDist
@@ -440,40 +440,48 @@ function handleClick(event: MouseEvent) {
440440
>
441441
<span v-else>v{{ displayVersion.version }}</span>
442442

443-
<AppPopover v-if="hasProvenance(displayVersion)" position="bottom">
444-
<template #content>
445-
<p class="flex items-center gap-2 text-fg m-0">
446-
<span
447-
class="i-solar-shield-check-outline w-3.5 h-3.5 shrink-0 text-emerald-500"
448-
aria-hidden="true"
449-
/>
450-
<span>{{
451-
provenanceData
452-
? $t('package.provenance_section.built_and_signed_on', {
453-
provider: provenanceData.providerLabel,
454-
})
455-
: $t('package.verified_provenance')
456-
}}</span>
457-
</p>
458-
<a href="#provenance" class="block mt-1.5 link font-medium">
459-
{{ $t('package.provenance_section.view_more_details') }}
460-
</a>
461-
</template>
462-
<template #default="{ popoverVisible }">
463-
<a
464-
:href="`https://www.npmjs.com/package/${pkg.name}/v/${displayVersion.version}#provenance`"
465-
target="_blank"
466-
rel="noopener noreferrer"
467-
class="inline-flex items-center justify-center gap-1.5 text-fg-muted hover:text-emerald-500 transition-colors duration-200 min-w-6 min-h-6"
468-
:class="popoverVisible && 'text-emerald-500'"
469-
>
470-
<span
471-
class="i-solar-shield-check-outline w-3.5 h-3.5 shrink-0"
472-
aria-hidden="true"
473-
/>
474-
</a>
475-
</template>
476-
</AppPopover>
443+
<template v-if="hasProvenance(displayVersion) && provenanceBadgeMounted">
444+
<div class="relative inline-flex">
445+
<AppPopover position="bottom">
446+
<template #content>
447+
<p class="flex items-center gap-2 text-fg m-0">
448+
<span
449+
class="i-solar-shield-check-outline w-3.5 h-3.5 shrink-0 text-emerald-500"
450+
aria-hidden="true"
451+
/>
452+
<span>{{
453+
provenanceData && provenanceStatus !== 'pending'
454+
? $t('package.provenance_section.built_and_signed_on', {
455+
provider: provenanceData.providerLabel,
456+
})
457+
: $t('package.verified_provenance')
458+
}}</span>
459+
</p>
460+
<a href="#provenance" class="block mt-1.5 link font-medium">
461+
{{ $t('package.provenance_section.view_more_details') }}
462+
</a>
463+
</template>
464+
<template #default="{ popoverVisible, popoverId }">
465+
<a
466+
:href="`https://www.npmjs.com/package/${pkg.name}/v/${displayVersion.version}#provenance`"
467+
target="_blank"
468+
rel="noopener noreferrer"
469+
:aria-label="$t('package.provenance_section.view_more_details')"
470+
:aria-expanded="popoverVisible"
471+
aria-haspopup="true"
472+
:aria-controls="popoverVisible ? popoverId : undefined"
473+
class="inline-flex items-center justify-center gap-1.5 text-fg-muted hover:text-emerald-500 transition-colors duration-200 min-w-6 min-h-6"
474+
:class="popoverVisible && 'text-emerald-500'"
475+
>
476+
<span
477+
class="i-solar-shield-check-outline w-3.5 h-3.5 shrink-0"
478+
aria-hidden="true"
479+
/>
480+
</a>
481+
</template>
482+
</AppPopover>
483+
</div>
484+
</template>
477485
<span
478486
v-if="
479487
requestedVersion &&
@@ -951,8 +959,11 @@ function handleClick(event: MouseEvent) {
951959
}}</a>
952960
</p>
953961

954-
<!-- Provenance details (when version has attestations) -->
955-
<template v-if="hasProvenance(displayVersion)">
962+
<section
963+
v-if="hasProvenance(displayVersion) && provenanceBadgeMounted"
964+
id="provenance"
965+
class="scroll-mt-20"
966+
>
956967
<div
957968
v-if="provenanceStatus === 'pending'"
958969
class="mt-8 flex items-center gap-2 text-fg-subtle text-sm"
@@ -970,7 +981,7 @@ function handleClick(event: MouseEvent) {
970981
:version="displayVersion?.version"
971982
class="mt-8"
972983
/>
973-
</template>
984+
</section>
974985
</section>
975986

976987
<div class="area-sidebar">

0 commit comments

Comments
 (0)