[READ-ONLY] a fast, modern browser for the npm registry

fix: use css modules for package page (#1242)

authored by

Daniel Roe and committed by
GitHub
27a9e772 02151303

+60 -62
+60 -62
app/pages/package/[[org]]/[name].vue
··· 517 517 <main class="container flex-1 w-full py-8"> 518 518 <PackageSkeleton v-if="status === 'pending'" /> 519 519 520 - <article v-else-if="status === 'success' && pkg" class="package-page"> 520 + <article v-else-if="status === 'success' && pkg" :class="$style.packagePage"> 521 521 <!-- Package header --> 522 522 <header 523 - class="area-header sticky top-14 z-1 bg-[--bg] py-2 border-border" 523 + class="sticky top-14 z-1 bg-[--bg] py-2 border-border" 524 524 ref="header" 525 - :class="{ 'border-b': isHeaderPinned }" 525 + :class="[$style.areaHeader, { 'border-b': isHeaderPinned }]" 526 526 > 527 527 <!-- Package name and version --> 528 528 <div class="flex items-baseline gap-x-2 gap-y-1 sm:gap-x-3 flex-wrap min-w-0"> ··· 545 545 <button 546 546 type="button" 547 547 @click="copyPkgName()" 548 - class="copy-button absolute z-20 inset-is-0 top-full inline-flex items-center gap-1 px-2 py-1 rounded border text-xs font-mono whitespace-nowrap transition-all duration-150 opacity-0 -translate-y-1 pointer-events-none group-hover:opacity-100 group-hover:translate-y-0 group-hover:pointer-events-auto focus-visible:opacity-100 focus-visible:translate-y-0 focus-visible:pointer-events-auto" 549 - :class=" 550 - copiedPkgName ? 'text-accent bg-accent/10' : 'text-fg-muted bg-bg border-border' 551 - " 548 + class="absolute z-20 inset-is-0 top-full inline-flex items-center gap-1 px-2 py-1 rounded border text-xs font-mono whitespace-nowrap transition-all duration-150 opacity-0 -translate-y-1 pointer-events-none group-hover:opacity-100 group-hover:translate-y-0 group-hover:pointer-events-auto focus-visible:opacity-100 focus-visible:translate-y-0 focus-visible:pointer-events-auto" 549 + :class="[ 550 + $style.copyButton, 551 + copiedPkgName ? 'text-accent bg-accent/10' : 'text-fg-muted bg-bg border-border', 552 + ]" 552 553 :aria-label="copiedPkgName ? $t('common.copied') : $t('package.copy_name')" 553 554 > 554 555 <span ··· 610 611 v-if="resolvedVersion" 611 612 as="nav" 612 613 :aria-label="$t('package.navigation')" 613 - class="package-nav hidden sm:flex max-sm:flex max-sm:fixed max-sm:z-40 max-sm:inset-is-50% max-sm:-translate-x-50% max-sm:bg-[--bg]/90 max-sm:backdrop-blur-md max-sm:border max-sm:border-border max-sm:rounded-md max-sm:shadow-md" 614 + class="hidden sm:flex max-sm:flex max-sm:fixed max-sm:z-40 max-sm:inset-is-50% max-sm:-translate-x-50% max-sm:bg-[--bg]/90 max-sm:backdrop-blur-md max-sm:border max-sm:border-border max-sm:rounded-md max-sm:shadow-md" 615 + :class="$style.packageNav" 614 616 > 615 617 <LinkBase 616 618 variant="button-secondary" ··· 701 703 </header> 702 704 703 705 <!-- Package details --> 704 - <section class="area-details"> 706 + <section :class="$style.areaDetails"> 705 707 <div class="mb-4"> 706 708 <!-- Description container with min-height to prevent CLS --> 707 709 <div class="max-w-2xl min-h-[4.5rem]"> ··· 978 980 </section> 979 981 980 982 <!-- Binary-only packages: Show only execute command (no install) --> 981 - <section v-if="isBinaryOnly" class="area-install scroll-mt-20"> 983 + <section v-if="isBinaryOnly" class="scroll-mt-20" :class="$style.areaInstall"> 982 984 <div class="flex flex-wrap items-center justify-between mb-3"> 983 985 <h2 id="run-heading" class="text-xs text-fg-subtle uppercase tracking-wider"> 984 986 {{ $t('package.run.title') }} ··· 1000 1002 </section> 1001 1003 1002 1004 <!-- Regular packages: Install command with optional run command --> 1003 - <section v-else id="get-started" class="area-install scroll-mt-20"> 1005 + <section v-else id="get-started" class="scroll-mt-20" :class="$style.areaInstall"> 1004 1006 <div class="flex flex-wrap items-center justify-between mb-3"> 1005 1007 <h2 1006 1008 id="get-started-heading" ··· 1029 1031 </div> 1030 1032 </section> 1031 1033 1032 - <div class="area-vulns space-y-6"> 1034 + <div class="space-y-6" :class="$style.areaVulns"> 1033 1035 <!-- Bad package warning --> 1034 1036 <PackageReplacement v-if="moduleReplacement" :replacement="moduleReplacement" /> 1035 1037 <!-- Vulnerability scan --> ··· 1049 1051 </div> 1050 1052 1051 1053 <!-- README --> 1052 - <section id="readme" class="area-readme min-w-0 scroll-mt-20"> 1054 + <section id="readme" class="min-w-0 scroll-mt-20" :class="$style.areaReadme"> 1053 1055 <div class="flex flex-wrap items-center justify-between mb-3 px-1"> 1054 1056 <h2 id="readme-heading" class="group text-xs text-fg-subtle uppercase tracking-wider"> 1055 1057 <LinkBase to="#readme"> ··· 1129 1131 </section> 1130 1132 </section> 1131 1133 1132 - <PackageSidebar class="area-sidebar"> 1134 + <PackageSidebar :class="$style.areaSidebar"> 1133 1135 <div class="flex flex-col gap-4 sm:gap-6 xl:(pt-2)"> 1134 1136 <!-- Team access controls (for scoped packages when connected) --> 1135 1137 <ClientOnly> ··· 1212 1214 </main> 1213 1215 </template> 1214 1216 1215 - <style scoped> 1216 - .package-page { 1217 + <style module> 1218 + .packagePage { 1217 1219 display: grid; 1218 1220 gap: 2rem; 1221 + word-wrap: break-word; 1222 + overflow-wrap: break-word; 1223 + max-width: 100%; 1219 1224 1220 1225 /* Mobile: single column, sidebar above readme */ 1221 1226 grid-template-columns: minmax(0, 1fr); ··· 1230 1235 1231 1236 /* Tablet/medium: header/install/vulns full width, readme+sidebar side by side */ 1232 1237 @media (min-width: 1024px) { 1233 - .package-page { 1238 + .packagePage { 1234 1239 grid-template-columns: 2fr 1fr; 1235 1240 grid-template-areas: 1236 1241 'header header' ··· 1244 1249 1245 1250 /* Desktop: floating sidebar alongside all content */ 1246 1251 @media (min-width: 1280px) { 1247 - .package-page { 1252 + .packagePage { 1248 1253 grid-template-columns: 1fr 20rem; 1249 1254 grid-template-areas: 1250 1255 'header sidebar' ··· 1255 1260 } 1256 1261 } 1257 1262 1258 - .area-header { 1259 - grid-area: header; 1260 - } 1261 - 1262 - .area-details { 1263 - grid-area: details; 1264 - } 1265 - 1266 - .area-install { 1267 - grid-area: install; 1268 - } 1269 - 1270 - .area-vulns { 1271 - grid-area: vulns; 1272 - overflow-x: hidden; 1273 - } 1274 - 1275 - .area-readme { 1276 - grid-area: readme; 1277 - } 1278 - 1279 - .area-readme > .readme { 1280 - overflow-x: hidden; 1263 + /* Ensure all children respect max-width */ 1264 + .packagePage > * { 1265 + max-width: 100%; 1266 + min-width: 0; 1281 1267 } 1282 1268 1283 - .area-sidebar { 1284 - grid-area: sidebar; 1269 + .areaHeader { 1270 + grid-area: header; 1285 1271 } 1286 1272 1287 1273 /* Improve package name wrapping for narrow screens */ 1288 - .area-header h1 { 1274 + .areaHeader h1 { 1289 1275 overflow-wrap: anywhere; 1290 1276 } 1291 1277 1292 1278 /* Ensure description text wraps properly */ 1293 - .area-header p { 1279 + .areaHeader p { 1294 1280 word-wrap: break-word; 1295 1281 overflow-wrap: break-word; 1296 1282 word-break: break-word; 1297 1283 } 1298 1284 1285 + .areaDetails { 1286 + grid-area: details; 1287 + } 1288 + 1289 + .areaInstall { 1290 + grid-area: install; 1291 + } 1292 + 1299 1293 /* Allow install command text to break on narrow screens */ 1300 - .area-install code { 1294 + .areaInstall code { 1301 1295 word-break: break-word; 1302 1296 overflow-wrap: anywhere; 1303 1297 white-space: pre-wrap; 1304 1298 } 1305 1299 1306 - /* Ensure all text content wraps on narrow screens */ 1307 - .package-page { 1308 - word-wrap: break-word; 1309 - overflow-wrap: break-word; 1310 - max-width: 100%; 1300 + .areaVulns { 1301 + grid-area: vulns; 1302 + overflow-x: hidden; 1303 + } 1304 + 1305 + .areaReadme { 1306 + grid-area: readme; 1311 1307 } 1312 1308 1313 - /* Ensure all children respect max-width */ 1314 - .package-page > * { 1315 - max-width: 100%; 1316 - min-width: 0; 1309 + .areaReadme > :global(.readme) { 1310 + overflow-x: hidden; 1317 1311 } 1318 1312 1319 - .copy-button { 1313 + .areaSidebar { 1314 + grid-area: sidebar; 1315 + } 1316 + 1317 + .copyButton { 1320 1318 clip: rect(0 0 0 0); 1321 1319 clip-path: inset(50%); 1322 1320 height: 1px; ··· 1331 1329 width 0.01s 0.34s allow-discrete; 1332 1330 } 1333 1331 1334 - .group:hover .copy-button, 1335 - .copy-button:focus-visible { 1332 + :global(.group):hover .copyButton, 1333 + .copyButton:focus-visible { 1336 1334 clip: auto; 1337 1335 clip-path: none; 1338 1336 height: auto; ··· 1344 1342 } 1345 1343 1346 1344 @media (hover: none) { 1347 - .copy-button { 1345 + .copyButton { 1348 1346 display: none; 1349 1347 } 1350 1348 } 1351 1349 1352 1350 /* Mobile floating nav: safe-area positioning + kbd hiding */ 1353 1351 @media (max-width: 639.9px) { 1354 - .package-nav { 1352 + .packageNav { 1355 1353 bottom: calc(1.25rem + env(safe-area-inset-bottom, 0px)); 1356 1354 } 1357 1355 1358 - .package-nav > :deep(a kbd) { 1356 + .packageNav > :global(a kbd) { 1359 1357 display: none; 1360 1358 } 1361 1359 1362 - .package-page { 1360 + .packagePage { 1363 1361 padding-bottom: calc(4.5rem + env(safe-area-inset-bottom, 0px)); 1364 1362 } 1365 1363 }