[READ-ONLY] a fast, modern browser for the npm registry
at main 154 lines 4.9 kB view raw
1<script setup lang="ts"> 2import type { ModuleReplacement } from 'module-replacements' 3 4export interface ComparisonGridColumn { 5 name: string 6 version?: string 7 /** Module replacement data for this package (if available) */ 8 replacement?: ModuleReplacement | null 9} 10 11const props = defineProps<{ 12 /** Column definitions for each package being compared */ 13 columns: ComparisonGridColumn[] 14 /** Whether to show the "no dependency" baseline as the last column */ 15 showNoDependency?: boolean 16}>() 17 18/** Total column count including the optional no-dep column */ 19const totalColumns = computed(() => props.columns.length + (props.showNoDependency ? 1 : 0)) 20 21/** Compute plain-text tooltip for a replacement column */ 22function getReplacementTooltip(col: ComparisonGridColumn): string { 23 if (!col.replacement) return '' 24 25 return [$t('package.replacement.title'), $t('package.replacement.learn_more_above')].join(' ') 26} 27</script> 28 29<template> 30 <div class="overflow-x-auto"> 31 <div 32 class="comparison-grid" 33 :class="[totalColumns === 4 ? 'min-w-[800px]' : 'min-w-[600px]', `columns-${totalColumns}`]" 34 :style="{ '--columns': totalColumns }" 35 > 36 <!-- Header row --> 37 <div class="comparison-header"> 38 <div class="comparison-label" /> 39 40 <!-- Package columns --> 41 <div v-for="col in columns" :key="col.name" class="comparison-cell comparison-cell-header"> 42 <span class="inline-flex items-center gap-1.5 truncate"> 43 <LinkBase 44 :to="packageRoute(col.name, col.version)" 45 class="text-sm truncate" 46 block 47 :title="col.version ? `${col.name}@${col.version}` : col.name" 48 > 49 {{ col.name }}<template v-if="col.version">@{{ col.version }}</template> 50 </LinkBase> 51 <TooltipApp v-if="col.replacement" :text="getReplacementTooltip(col)" position="bottom"> 52 <span 53 class="i-lucide:lightbulb w-3.5 h-3.5 text-amber-500 shrink-0 cursor-help" 54 role="img" 55 :aria-label="$t('package.replacement.title')" 56 /> 57 </TooltipApp> 58 </span> 59 </div> 60 61 <!-- "No dep" column (always last) --> 62 <div 63 v-if="showNoDependency" 64 class="comparison-cell comparison-cell-header comparison-cell-nodep" 65 > 66 <span 67 class="inline-flex items-center gap-1.5 text-sm font-medium text-accent italic truncate" 68 > 69 {{ $t('compare.no_dependency.label') }} 70 <TooltipApp interactive position="bottom"> 71 <span 72 class="i-lucide:lightbulb w-3.5 h-3.5 text-amber-500 shrink-0 cursor-help" 73 role="img" 74 :aria-label="$t('compare.no_dependency.tooltip_title')" 75 /> 76 <template #content> 77 <p class="text-sm font-medium text-fg mb-1"> 78 {{ $t('compare.no_dependency.tooltip_title') }} 79 </p> 80 <p class="text-xs text-fg-muted"> 81 <i18n-t keypath="compare.no_dependency.tooltip_description" tag="span"> 82 <template #link> 83 <LinkBase to="https://e18e.dev/docs/replacements/">{{ 84 $t('compare.no_dependency.e18e_community') 85 }}</LinkBase> 86 </template> 87 </i18n-t> 88 </p> 89 </template> 90 </TooltipApp> 91 </span> 92 </div> 93 </div> 94 95 <!-- Facet rows --> 96 <slot /> 97 </div> 98 </div> 99</template> 100 101<style scoped> 102.comparison-grid { 103 display: grid; 104 gap: 0; 105} 106 107.comparison-grid.columns-2 { 108 grid-template-columns: minmax(120px, 180px) repeat(2, 1fr); 109} 110 111.comparison-grid.columns-3 { 112 grid-template-columns: minmax(120px, 160px) repeat(3, 1fr); 113} 114 115.comparison-grid.columns-4 { 116 grid-template-columns: minmax(100px, 140px) repeat(4, 1fr); 117} 118 119.comparison-header { 120 display: contents; 121} 122 123.comparison-header > .comparison-label { 124 padding: 0.75rem 1rem; 125 border-bottom: 1px solid var(--color-border); 126} 127 128.comparison-header > .comparison-cell-header { 129 padding: 0.75rem 1rem; 130 background: var(--color-bg-subtle); 131 border-bottom: 1px solid var(--color-border); 132 text-align: center; 133} 134 135/* "No dep" column styling */ 136.comparison-header > .comparison-cell-header.comparison-cell-nodep { 137 background: linear-gradient( 138 135deg, 139 var(--color-bg-subtle) 0%, 140 color-mix(in srgb, var(--color-accent) 8%, var(--color-bg-subtle)) 100% 141 ); 142 border-bottom-color: color-mix(in srgb, var(--color-accent) 30%, var(--color-border)); 143} 144 145/* First header cell rounded top-start */ 146.comparison-header > .comparison-cell-header:first-of-type { 147 border-start-start-radius: 0.5rem; 148} 149 150/* Last header cell rounded top-end */ 151.comparison-header > .comparison-cell-header:last-of-type { 152 border-start-end-radius: 0.5rem; 153} 154</style>