@@ -40,12 +40,18 @@ const isError = computed(() => status.value === 'error')
4040
4141function 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