11<script setup lang="ts">
2- import { computed , ref } from ' vue'
32import { encodePackageName } from ' #shared/utils/npm'
43
5- const props = withDefaults (
6- defineProps <{
7- packages? : string | string []
8- emptyDescription? : string
9- primaryColor? : string
10- }>(),
11- {
12- packages : () => [],
13- emptyDescription: ' Compare npm packages side-by-side' ,
14- primaryColor: ' #60a5fa' ,
15- },
16- )
4+ const { packages = [], emptyDescription = ' Compare npm packages side-by-side' } = defineProps <{
5+ packages? : string | string []
6+ emptyDescription? : string
7+ }>()
178
189const ACCENT_COLORS = [
1910 ' #60a5fa' ,
@@ -37,7 +28,7 @@ const GRID_MAX = 12
3728const SUMMARY_TOP_COUNT = 3
3829
3930const displayPackages = computed (() => {
40- const raw = props . packages
31+ const raw = packages
4132 return (typeof raw === ' string' ? raw .split (' ,' ) : raw ).map (p => p .trim ()).filter (Boolean )
4233})
4334
@@ -57,7 +48,7 @@ interface PkgStats {
5748 color: string
5849}
5950
60- const stats = ref <PkgStats []>([])
51+ const stats = shallowRef <PkgStats []>([])
6152
6253const FETCH_TIMEOUT_MS = 2500
6354
@@ -122,61 +113,27 @@ const summaryRemainder = computed(() =>
122113 </script >
123114
124115<template >
125- <div
126- class =" h-full w-full flex flex-col justify-center relative overflow-hidden bg-[#050505] text-[#fafafa] px-20"
127- style =" font-family : ' Geist Mono' , sans-serif "
128- >
129- <div class =" relative z-10 flex flex-col gap-5" >
130- <!-- Icon + title row -->
131- <div class =" flex items-start gap-4" >
132- <div
133- class =" flex items-center justify-center w-16 h-16 p-3.5 rounded-xl shadow-lg"
134- :style =" { background: `linear-gradient(to top right, #3b82f6, ${primaryColor})` }"
135- >
136- <svg
137- width =" 36"
138- height =" 36"
139- viewBox =" 0 0 24 24"
140- fill =" none"
141- stroke =" white"
142- stroke-width =" 2.5"
143- stroke-linecap =" round"
144- stroke-linejoin =" round"
145- >
146- <path d =" m7.5 4.27 9 5.15" />
147- <path
148- d =" M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z"
149- />
150- <path d =" m3.3 7 8.7 5 8.7-5" />
151- <path d =" M12 22V12" />
152- </svg >
153- </div >
116+ <OgLayout >
117+ <div class =" px-15 py-12 flex flex-col justify-center gap-10 h-full" >
118+ <OgBrand :height =" 48" />
154119
155- <h1 class =" text-7xl font-bold tracking-tight" >
156- <span
157- class =" opacity-80 tracking-[-0.1em]"
158- :style =" { color: primaryColor }"
159- style =" margin-right : 0.25rem "
160- >./</span
161- >compare
120+ <div class =" flex items-baseline gap-3" >
121+ <h1 class =" text-7xl font-mono tracking-tighter leading-none" >
122+ <span class =" opacity-50" >./</span >compare
162123 </h1 >
163124 </div >
164125
165126 <!-- Empty state -->
166- <div
167- v-if =" displayPackages.length === 0"
168- class =" text-4xl text-[#a3a3a3]"
169- style =" font-family : ' Geist' , sans-serif "
170- >
127+ <div v-if =" displayPackages.length === 0" class =" text-4xl text-fg-muted" >
171128 {{ emptyDescription }}
172129 </div >
173130
174131 <!-- FULL layout (1-4 packages): name + downloads + version badge + bar -->
175132 <div v-else-if =" layoutTier === 'full'" class =" flex flex-col gap-2" >
176133 <div v-for =" pkg in stats" :key =" pkg.name" class =" flex flex-col gap-1" >
177- <div class =" flex items-center gap-3" style = " font-family : ' Geist ' , sans-serif " >
134+ <div class =" flex items-center gap-3" >
178135 <span
179- class =" text-2xl font-semibold tracking-tight"
136+ class =" text-2xl font-semibold tracking-tight font-mono "
180137 :style =" {
181138 color: pkg.color,
182139 maxWidth: '400px',
@@ -189,7 +146,7 @@ const summaryRemainder = computed(() =>
189146 </span >
190147 <span
191148 v-if =" pkg.version"
192- class =" text-lg px-2 py-0.5 rounded-md border"
149+ class =" text-lg px-2 py-0.5 rounded-md border font-mono "
193150 :style =" {
194151 color: pkg.color,
195152 backgroundColor: pkg.color + '10',
@@ -198,7 +155,7 @@ const summaryRemainder = computed(() =>
198155 >
199156 {{ pkg.version }}
200157 </span >
201- <span class =" text-3xl font-bold text-[#fafafa] " >
158+ <span class =" text-3xl font-bold text-fg " >
202159 {{ formatDownloads(pkg.downloads) }}/wk
203160 </span >
204161 </div >
@@ -215,9 +172,9 @@ const summaryRemainder = computed(() =>
215172 <!-- COMPACT layout (5-6 packages): name + downloads + thinner bar, no version -->
216173 <div v-else-if =" layoutTier === 'compact'" class =" flex flex-col gap-2" >
217174 <div v-for =" pkg in stats" :key =" pkg.name" class =" flex flex-col gap-0.5" >
218- <div class =" flex items-center gap-2" style = " font-family : ' Geist ' , sans-serif " >
175+ <div class =" flex items-center gap-2" >
219176 <span
220- class =" text-xl font-semibold tracking-tight"
177+ class =" text-xl font-semibold tracking-tight font-mono "
221178 :style =" {
222179 color: pkg.color,
223180 maxWidth: '300px',
@@ -230,7 +187,7 @@ const summaryRemainder = computed(() =>
230187 </span >
231188 <span
232189 v-if =" pkg.version"
233- class =" text-sm px-1.5 py-0.5 rounded border"
190+ class =" text-sm px-1.5 py-0.5 rounded border font-mono "
234191 :style =" {
235192 color: pkg.color,
236193 backgroundColor: pkg.color + '10',
@@ -239,9 +196,7 @@ const summaryRemainder = computed(() =>
239196 >
240197 {{ pkg.version }}
241198 </span >
242- <span class =" text-xl font-bold text-[#fafafa]" >
243- {{ formatDownloads(pkg.downloads) }}/wk
244- </span >
199+ <span class =" text-xl font-bold text-fg" > {{ formatDownloads(pkg.downloads) }}/wk </span >
245200 </div >
246201 <div
247202 class =" h-3 rounded-sm"
@@ -261,7 +216,6 @@ const summaryRemainder = computed(() =>
261216 flexWrap: 'wrap',
262217 rowGap: 24,
263218 columnGap: 40,
264- fontFamily: 'Geist, sans-serif',
265219 }"
266220 >
267221 <span
@@ -275,7 +229,7 @@ const summaryRemainder = computed(() =>
275229 }"
276230 >
277231 <span
278- class =" font-semibold tracking-tight"
232+ class =" font-semibold tracking-tight font-mono "
279233 :style =" {
280234 fontSize: '18px',
281235 maxWidth: '220px',
@@ -287,25 +241,23 @@ const summaryRemainder = computed(() =>
287241 >{{ pkg.name }}</span
288242 >
289243 <span :style =" { display: 'flex', alignItems: 'baseline', gap: 2 }" >
290- <span class =" text-2xl font-bold text-[#e5e5e5]" >{{
291- formatDownloads(pkg.downloads)
292- }}</span >
293- <span class =" text-sm font-medium text-[#d4d4d4]" >/wk</span >
244+ <span class =" text-2xl font-bold text-fg" >{{ formatDownloads(pkg.downloads) }}</span >
245+ <span class =" text-sm font-medium text-fg-muted" >/wk</span >
294246 </span >
295247 </span >
296248 </div >
297249
298250 <!-- SUMMARY layout (13+ packages): package count + top names -->
299- <div v-else class =" flex flex-col gap-3" style = " font-family : ' Geist ' , sans-serif " >
300- <div class =" text-2xl text-[#a3a3a3] " >
301- <span class =" text-4xl font-bold text-[#fafafa] " >{{ displayPackages.length }}</span >
251+ <div v-else class =" flex flex-col gap-3" >
252+ <div class =" text-2xl text-fg-muted " >
253+ <span class =" text-4xl font-bold text-fg " >{{ displayPackages.length }}</span >
302254 packages
303255 </div >
304256 <div :style =" { display: 'flex', alignItems: 'baseline', gap: 8, whiteSpace: 'nowrap' }" >
305257 <span
306258 v-for =" (name, i) in summaryTopNames"
307259 :key =" name"
308- class =" text-xl font-semibold"
260+ class =" text-xl font-semibold font-mono "
309261 :style =" {
310262 color: ACCENT_COLORS[i % ACCENT_COLORS.length],
311263 maxWidth: '280px',
@@ -316,24 +268,11 @@ const summaryRemainder = computed(() =>
316268 }"
317269 >{{ name }}{{ i < summaryTopNames.length - 1 ? ',' : '' }}</span
318270 >
319- <span v-if =" summaryRemainder > 0" class =" text-xl text-[#737373] " >
271+ <span v-if =" summaryRemainder > 0" class =" text-xl text-fg-subtle " >
320272 +{{ summaryRemainder }} more
321273 </span >
322274 </div >
323275 </div >
324276 </div >
325-
326- <!-- Branding -->
327- <div
328- class =" absolute bottom-6 inset-ie-20 text-lg font-semibold tracking-tight text-[#525252]"
329- style =" font-family : ' Geist Mono' , sans-serif "
330- >
331- <span :style =" { color: primaryColor }" class =" opacity-80 tracking-[-0.1em]" >./</span >npmx
332- </div >
333-
334- <div
335- class =" absolute -top-32 -inset-ie-32 w-[550px] h-[550px] rounded-full blur-3xl"
336- :style =" { backgroundColor: primaryColor + '10' }"
337- />
338- </div >
277+ </OgLayout >
339278</template >
0 commit comments