@@ -20,82 +20,132 @@ const emit = defineEmits<{
2020
2121<template >
2222 <article
23- class =" group card-interactive scroll-mt-48 scroll-mb-6"
23+ class =" group card-interactive scroll-mt-48 scroll-mb-6 relative focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-bg focus-within:ring-offset-2 focus-within:ring-fg/50 "
2424 :class =" { 'bg-bg-muted border-border-hover': selected }"
2525 >
26- <NuxtLink
27- :to = " { name: 'package', params: { package: result.package.name.split('/') } } "
28- :prefetch-on = " prefetch ? 'visibility' : 'interaction '"
29- class =" block focus:outline-none decoration-none scroll-mt-48 scroll-mb-6 "
30- :data-result-index = " index "
31- @focus = " index != null && emit('focus', index) "
32- @mouseenter = " index != null && emit('focus', index) "
33- >
34- < header class =" flex items-start justify-between gap-2 sm:gap-4 mb-2 " >
35- < component
36- :is = " headingLevel ?? 'h3' "
37- class = " font-mono text-sm sm:text-base font-medium text-fg group-hover:text-fg transition-colors duration-200 min-w-0 break-words "
26+ <div class = " mb-2 flex items-baseline justify-between gap-2 " >
27+ < component
28+ :is = " headingLevel ?? 'h3 '"
29+ class =" font-mono text-sm sm:text-base font-medium text-fg group-hover:text-fg transition-colors duration-200 min-w-0 break-all "
30+ >
31+ < NuxtLink
32+ :to = " { name: 'package', params: { package: result.package.name.split('/') } } "
33+ :prefetch-on = " prefetch ? 'visibility' : 'interaction' "
34+ class =" focus-visible:outline-none decoration-none scroll-mt-48 scroll-mb-6 after:content-[''] after:absolute after:inset-0 "
35+ :data-result-index = " index "
36+ @focus = " index != null && emit('focus', index) "
37+ @mouseenter = " index != null && emit('focus', index) "
3838 >
3939 {{ result.package.name }}
40- </component >
41- <div class =" flex items-center gap-1.5 shrink-0" >
40+ </NuxtLink >
41+ </component >
42+ <!-- Mobile: version next to package name -->
43+ <div class =" sm:hidden text-fg-subtle flex items-center gap-1.5 shrink-0" >
44+ <span
45+ v-if =" result.package.version"
46+ class =" font-mono text-xs truncate max-w-20"
47+ :title =" result.package.version"
48+ >
49+ v{{ result.package.version }}
50+ </span >
51+ <ProvenanceBadge
52+ v-if =" result.package.publisher?.trustedPublisher"
53+ :provider =" result.package.publisher.trustedPublisher.id"
54+ :package-name =" result.package.name"
55+ :version =" result.package.version"
56+ :linked =" false"
57+ compact
58+ />
59+ </div >
60+ </div >
61+ <div class =" flex justify-between items-start gap-4 sm:gap-8" >
62+ <div class =" min-w-0" >
63+ <p
64+ v-if =" result.package.description"
65+ class =" text-fg-muted text-xs sm:text-sm line-clamp-2 mb-2 sm:mb-3"
66+ >
67+ <MarkdownText :text =" result.package.description" />
68+ </p >
69+ <div class =" flex flex-wrap items-center gap-x-3 sm:gap-x-4 gap-y-2 text-xs text-fg-subtle" >
70+ <dl v-if =" showPublisher || result.package.date" class =" flex items-center gap-4 m-0" >
71+ <div
72+ v-if =" showPublisher && result.package.publisher?.username"
73+ class =" flex items-center gap-1.5"
74+ >
75+ <dt class =" sr-only" >Publisher</dt >
76+ <dd class =" font-mono" >@{{ result.package.publisher.username }}</dd >
77+ </div >
78+ <div v-if =" result.package.date" class =" flex items-center gap-1.5" >
79+ <dt class =" sr-only" >Updated</dt >
80+ <dd >
81+ <NuxtTime
82+ :datetime =" result.package.date"
83+ year =" numeric"
84+ month =" short"
85+ day =" numeric"
86+ />
87+ </dd >
88+ </div >
89+ </dl >
90+ </div >
91+ <!-- Mobile: downloads on separate row -->
92+ <dl
93+ v-if =" result.downloads?.weekly"
94+ class =" sm:hidden flex items-center gap-4 mt-2 text-xs text-fg-subtle m-0"
95+ >
96+ <div class =" flex items-center gap-1.5" >
97+ <dt class =" sr-only" >Weekly downloads</dt >
98+ <dd class =" flex items-center gap-1.5" >
99+ <span class =" i-carbon-chart-line w-3.5 h-3.5 inline-block" aria-hidden =" true" />
100+ <span class =" font-mono" >{{ formatNumber(result.downloads.weekly) }}/w</span >
101+ </dd >
102+ </div >
103+ </dl >
104+ </div >
105+ <!-- Desktop: version and downloads on right side -->
106+ <div class =" hidden sm:flex flex-col gap-2 shrink-0" >
107+ <div class =" text-fg-subtle flex items-start gap-2 justify-end" >
42108 <span
43109 v-if =" result.package.version"
44- class =" font-mono text-xs text-fg-subtle truncate max-w-20 sm: max-w-32"
110+ class =" font-mono text-xs truncate max-w-32"
45111 :title =" result.package.version"
46112 >
47113 v{{ result.package.version }}
48114 </span >
49- <ProvenanceBadge
50- v-if =" result.package.publisher?.trustedPublisher"
51- :provider =" result.package.publisher.trustedPublisher.id"
52- :package-name =" result.package.name"
53- :version =" result.package.version"
54- compact
55- />
56- </div >
57- </header >
58-
59- <p
60- v-if =" result.package.description"
61- class =" text-fg-muted text-xs sm:text-sm line-clamp-2 mb-2 sm:mb-3"
62- >
63- <MarkdownText :text =" result.package.description" />
64- </p >
65-
66- <footer class =" flex flex-wrap items-center gap-x-3 sm:gap-x-4 gap-y-2 text-xs text-fg-subtle" >
67- <dl v-if =" showPublisher || result.package.date" class =" flex items-center gap-4 m-0" >
68115 <div
69- v-if =" showPublisher && result.package.publisher?.username "
70- class =" flex items-center gap-1.5"
116+ v-if =" result.package.publisher?.trustedPublisher "
117+ class =" flex items-center gap-1.5 shrink-0 max-w-32 "
71118 >
72- <dt class =" sr-only" >Publisher</dt >
73- <dd class =" font-mono" >@{{ result.package.publisher.username }}</dd >
74- </div >
75- <div v-if =" result.package.date" class =" flex items-center gap-1.5" >
76- <dt class =" sr-only" >Updated</dt >
77- <dd >
78- <NuxtTime
79- :datetime =" result.package.date"
80- year =" numeric"
81- month =" short"
82- day =" numeric"
83- />
84- </dd >
119+ <ProvenanceBadge
120+ :provider =" result.package.publisher.trustedPublisher.id"
121+ :package-name =" result.package.name"
122+ :version =" result.package.version"
123+ :linked =" false"
124+ compact
125+ />
85126 </div >
86- </dl >
87- </footer >
88- </NuxtLink >
127+ </div >
128+ <div
129+ v-if =" result.downloads?.weekly"
130+ class =" text-fg-subtle gap-2 flex items-center justify-end"
131+ >
132+ <span class =" i-carbon-chart-line w-3.5 h-3.5 inline-block" aria-hidden =" true" />
133+ <span class =" font-mono text-xs" >
134+ {{ formatNumber(result.downloads.weekly) }} / week
135+ </span >
136+ </div >
137+ </div >
138+ </div >
89139
90140 <ul
91141 v-if =" result.package.keywords?.length"
92142 aria-label =" Keywords"
93- class =" flex flex-wrap gap-1.5 mt-3 pt-3 border-t border-border list-none m-0 p-0"
143+ class =" relative z-10 flex flex-wrap gap-1.5 mt-3 pt-3 border-t border-border list-none m-0 p-0"
94144 >
95145 <li v-for =" keyword in result.package.keywords.slice(0, 5)" :key =" keyword" >
96146 <NuxtLink
97147 :to =" { name: 'search', query: { q: `keywords:${keyword}` } }"
98- class =" tag decoration-none"
148+ class =" tag decoration-none focus-visible:ring-2 focus-visible:ring-fg/50 focus-visible:outline-none "
99149 >
100150 {{ keyword }}
101151 </NuxtLink >
0 commit comments