Skip to content

Commit 88bc6b1

Browse files
fix(ui): address review feedback on health score widget
- Wrap component in CollapsibleSection for proper sidebar alignment - Fix footer link to point to npm Pulse homepage (not raw JSON API) - Add algorithm subtitle showing weights inline for transparency - Add a11y test for PackageHealthScore - Fix formatting to pass vp fmt check - Remove BOM from locale files to fix i18n validator
1 parent bcf3455 commit 88bc6b1

File tree

6 files changed

+1654
-1709
lines changed

6 files changed

+1654
-1709
lines changed

app/components/Package/HealthScore.vue

Lines changed: 55 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,18 @@ const isError = computed(() => status.value === 'error')
4040
4141
function gradeColor(grade: string | undefined): string {
4242
switch (grade) {
43-
case 'A': return 'text-emerald-500'
44-
case 'B': return 'text-lime-500'
45-
case 'C': return 'text-amber-500'
46-
case 'D': return 'text-orange-500'
47-
case 'F': return 'text-red-500'
48-
default: return 'text-fg-subtle'
43+
case 'A':
44+
return 'text-emerald-500'
45+
case 'B':
46+
return 'text-lime-500'
47+
case 'C':
48+
return 'text-amber-500'
49+
case 'D':
50+
return 'text-orange-500'
51+
case 'F':
52+
return 'text-red-500'
53+
default:
54+
return 'text-fg-subtle'
4955
}
5056
}
5157
@@ -61,39 +67,51 @@ const dimensions = computed(() => {
6167
if (!data.value?.dimensions) return []
6268
const d = data.value.dimensions
6369
return [
64-
{ key: 'maintenance', label: $t('package.health_score.dimension_maintenance'), score: d.maintenance?.score ?? 0, weight: d.maintenance?.weight ?? 0 },
65-
{ key: 'quality', label: $t('package.health_score.dimension_quality'), score: d.quality?.score ?? 0, weight: d.quality?.weight ?? 0 },
66-
{ key: 'security', label: $t('package.health_score.dimension_security'), score: d.security?.score ?? 0, weight: d.security?.weight ?? 0 },
67-
{ key: 'popularity', label: $t('package.health_score.dimension_popularity'), score: d.popularity?.score ?? 0, weight: d.popularity?.weight ?? 0 },
70+
{
71+
key: 'maintenance',
72+
label: $t('package.health_score.dimension_maintenance'),
73+
score: d.maintenance?.score ?? 0,
74+
weight: d.maintenance?.weight ?? 0,
75+
},
76+
{
77+
key: 'quality',
78+
label: $t('package.health_score.dimension_quality'),
79+
score: d.quality?.score ?? 0,
80+
weight: d.quality?.weight ?? 0,
81+
},
82+
{
83+
key: 'security',
84+
label: $t('package.health_score.dimension_security'),
85+
score: d.security?.score ?? 0,
86+
weight: d.security?.weight ?? 0,
87+
},
88+
{
89+
key: 'popularity',
90+
label: $t('package.health_score.dimension_popularity'),
91+
score: d.popularity?.score ?? 0,
92+
weight: d.popularity?.weight ?? 0,
93+
},
6894
]
6995
})
7096
</script>
7197

7298
<template>
73-
<section aria-labelledby="health-score-heading">
74-
<h2
75-
id="health-score-heading"
76-
class="text-xs text-fg-subtle uppercase tracking-wider mb-3 flex items-center gap-1.5"
77-
>
78-
<span class="i-lucide:activity w-3.5 h-3.5" aria-hidden="true" />
79-
{{ $t('package.health_score.title') }}
80-
</h2>
81-
82-
<!-- Loading state -->
83-
<div v-if="isLoading" class="flex items-center gap-2 text-fg-subtle text-sm">
84-
<span class="i-svg-spinners:ring-resize w-4 h-4" aria-hidden="true" />
85-
<span>{{ $t('package.health_score.loading') }}</span>
86-
</div>
87-
99+
<CollapsibleSection
100+
:title="$t('package.health_score.title')"
101+
:subtitle="$t('package.health_score.algorithm_subtitle')"
102+
:is-loading="isLoading"
103+
icon="i-lucide:activity"
104+
id="health-score"
105+
>
88106
<!-- Error state -->
89-
<div v-else-if="isError" class="flex items-center gap-2 text-fg-subtle text-sm">
107+
<div v-if="isError" class="flex items-center gap-2 text-fg-subtle text-sm">
90108
<span class="i-lucide:circle-alert w-4 h-4" aria-hidden="true" />
91109
<span>{{ $t('package.health_score.error') }}</span>
92110
</div>
93111

94112
<!-- Score display -->
95113
<div v-else-if="data" class="space-y-3">
96-
<!-- Score header: large score + grade badge -->
114+
<!-- Score + grade -->
97115
<div class="flex items-center gap-3">
98116
<TooltipApp :text="$t('package.health_score.score_tooltip')" strategy="fixed">
99117
<div class="flex items-baseline gap-1 cursor-default" tabindex="0">
@@ -102,10 +120,7 @@ const dimensions = computed(() => {
102120
</div>
103121
</TooltipApp>
104122

105-
<TooltipApp
106-
:text="$t('package.health_score.grade_tooltip', { grade: data.grade })"
107-
strategy="fixed"
108-
>
123+
<TooltipApp :text="$t('package.health_score.grade_tooltip', { grade: data.grade })" strategy="fixed">
109124
<TagStatic
110125
tabindex="0"
111126
:class="gradeColor(data.grade)"
@@ -118,13 +133,13 @@ const dimensions = computed(() => {
118133
</div>
119134

120135
<!-- Dimension bars -->
121-
<ul
122-
class="space-y-2 list-none m-0 p-0"
123-
:aria-label="$t('package.health_score.dimensions_label')"
124-
>
136+
<ul class="space-y-2 list-none m-0 p-0" :aria-label="$t('package.health_score.dimensions_label')">
125137
<li v-for="dim in dimensions" :key="dim.key">
126138
<div class="flex items-center justify-between mb-0.5">
127-
<span class="text-xs text-fg-subtle">{{ dim.label }}</span>
139+
<span class="text-xs text-fg-subtle">
140+
{{ dim.label }}
141+
<span class="text-fg-muted">({{ dim.weight }}%)</span>
142+
</span>
128143
<span class="font-mono text-xs text-fg-muted">{{ dim.score }}</span>
129144
</div>
130145
<div
@@ -145,9 +160,9 @@ const dimensions = computed(() => {
145160
</li>
146161
</ul>
147162

148-
<!-- Footer link -->
163+
<!-- Footer: link to npm Pulse (homepage, not raw JSON) -->
149164
<a
150-
:href="`https://npm-pulse.vercel.app/api/v1/score/${props.packageName}`"
165+
href="https://npm-pulse.vercel.app"
151166
target="_blank"
152167
rel="noopener noreferrer"
153168
class="inline-flex items-center gap-1 text-xs text-fg-subtle hover:text-fg transition-colors duration-150 underline underline-offset-2 decoration-fg-subtle/40"
@@ -156,5 +171,5 @@ const dimensions = computed(() => {
156171
<span class="i-lucide:external-link w-3 h-3" aria-hidden="true" />
157172
</a>
158173
</div>
159-
</section>
160-
</template>
174+
</CollapsibleSection>
175+
</template>

0 commit comments

Comments
 (0)