Skip to content

Commit e9c4e4e

Browse files
committed
feat: add extra wide layout to package page
1 parent 64d0bc6 commit e9c4e4e

3 files changed

Lines changed: 97 additions & 37 deletions

File tree

app/pages/[...package].vue

Lines changed: 93 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -295,12 +295,15 @@ defineOgImageComponent('Package', {
295295
</script>
296296

297297
<template>
298-
<main class="container py-8 sm:py-12 overflow-hidden w-full">
299-
<PackageSkeleton v-if="status === 'pending'" />
298+
<main class="package-page container">
299+
<PackageSkeleton v-if="status === 'pending'" class="col-span-full row-span-full" />
300300

301-
<article v-else-if="status === 'success' && pkg" class="motion-safe:animate-fade-in min-w-0">
301+
<article
302+
v-else-if="status === 'success' && pkg"
303+
class="motion-safe:animate-fade-in contents animate-fade-in"
304+
>
302305
<!-- Package header -->
303-
<header class="mb-8 pb-8 border-b border-border">
306+
<header class="area-header pb-8 border-b border-border">
304307
<div class="mb-4">
305308
<!-- Package name and version -->
306309
<div class="flex items-baseline gap-2 mb-1.5 sm:gap-3 sm:mb-2 flex-wrap min-w-0">
@@ -660,10 +663,11 @@ defineOgImageComponent('Package', {
660663
v-if="displayVersion"
661664
:package-name="pkg.name"
662665
:version="displayVersion.version"
666+
class="area-vulns"
663667
/>
664668

665669
<!-- Install command with package manager selector -->
666-
<section aria-labelledby="install-heading" class="mb-8">
670+
<section aria-labelledby="install-heading" class="area-install">
667671
<div class="flex flex-wrap items-center justify-between mb-3">
668672
<h2 id="install-heading" class="text-xs text-fg-subtle uppercase tracking-wider">
669673
{{ $t('package.install.title') }}
@@ -763,35 +767,28 @@ defineOgImageComponent('Package', {
763767
</div>
764768
</section>
765769

766-
<!-- Two column layout for sidebar content -->
767-
<div class="grid lg:grid-cols-3 gap-8">
768-
<!-- Main content (README) -->
769-
<div class="lg:col-span-2 order-2 lg:order-1 min-w-0">
770-
<section aria-labelledby="readme-heading">
771-
<h2 id="readme-heading" class="text-xs text-fg-subtle uppercase tracking-wider mb-4">
772-
{{ $t('package.readme.title') }}
773-
</h2>
774-
<!-- eslint-disable vue/no-v-html -- HTML is sanitized server-side -->
775-
<div
776-
v-if="readmeData?.html"
777-
class="readme-content prose prose-invert max-w-none"
778-
v-html="readmeData.html"
779-
/>
780-
<p v-else class="text-fg-subtle italic">
781-
{{ $t('package.readme.no_readme') }}
782-
<a
783-
v-if="repositoryUrl"
784-
:href="repositoryUrl"
785-
rel="noopener noreferrer"
786-
class="link"
787-
>{{ $t('package.readme.view_on_github') }}</a
788-
>
789-
</p>
790-
</section>
791-
</div>
770+
<!-- README -->
771+
<section aria-labelledby="readme-heading" class="area-readme min-w-0">
772+
<h2 id="readme-heading" class="text-xs text-fg-subtle uppercase tracking-wider mb-4">
773+
{{ $t('package.readme.title') }}
774+
</h2>
775+
<!-- eslint-disable vue/no-v-html -- HTML is sanitized server-side -->
776+
<div
777+
v-if="readmeData?.html"
778+
class="readme-content prose prose-invert max-w-70ch"
779+
v-html="readmeData.html"
780+
/>
781+
<p v-else class="text-fg-subtle italic">
782+
{{ $t('package.readme.no_readme') }}
783+
<a v-if="repositoryUrl" :href="repositoryUrl" rel="noopener noreferrer" class="link">{{
784+
$t('package.readme.view_on_github')
785+
}}</a>
786+
</p>
787+
</section>
792788

789+
<div class="area-sidebar">
793790
<!-- Sidebar -->
794-
<div class="order-1 lg:order-2 space-y-6 sm:space-y-8 min-w-0 overflow-hidden">
791+
<aside class="sticky top-20 space-y-6 sm:space-y-8 min-w-0 overflow-hidden">
795792
<!-- Maintainers (with admin actions when connected) -->
796793
<PackageMaintainers :package-name="pkg.name" :maintainers="pkg.maintainers" />
797794

@@ -882,12 +879,16 @@ defineOgImageComponent('Package', {
882879
:peer-dependencies-meta="displayVersion?.peerDependenciesMeta"
883880
:optional-dependencies="displayVersion?.optionalDependencies"
884881
/>
885-
</div>
882+
</aside>
886883
</div>
887884
</article>
888885

889886
<!-- Error state -->
890-
<div v-else-if="status === 'error'" role="alert" class="py-20 text-center">
887+
<div
888+
v-else-if="status === 'error'"
889+
role="alert"
890+
class="col-span-full flex flex-col items-center py-20 text-center"
891+
>
891892
<h1 class="font-mono text-2xl font-medium mb-4">{{ $t('package.not_found') }}</h1>
892893
<p class="text-fg-muted mb-8">
893894
{{ error?.message ?? $t('package.not_found_message') }}
@@ -896,3 +897,61 @@ defineOgImageComponent('Package', {
896897
</div>
897898
</main>
898899
</template>
900+
901+
<style scoped>
902+
.package-page {
903+
display: grid;
904+
padding: 2rem 1rem;
905+
gap: 2rem;
906+
907+
/* Mobile: single column, sidebar above readme */
908+
grid-template-columns: 1fr;
909+
grid-template-areas:
910+
'header'
911+
'install'
912+
'vulns'
913+
'sidebar'
914+
'readme';
915+
}
916+
917+
/* Tablet/medium: header/install/vulns full width, readme+sidebar side by side */
918+
@media (min-width: 1024px) {
919+
.package-page {
920+
padding: 3rem 1.5rem;
921+
grid-template-columns: 2fr 1fr;
922+
grid-template-areas:
923+
'header header'
924+
'install install'
925+
'vulns vulns'
926+
'readme sidebar';
927+
}
928+
}
929+
930+
/* Desktop: floating sidebar alongside all content */
931+
@media (min-width: 1280px) {
932+
.package-page {
933+
grid-template-columns: 1fr 320px;
934+
grid-template-areas:
935+
'header sidebar'
936+
'install sidebar'
937+
'vulns sidebar'
938+
'readme sidebar';
939+
}
940+
}
941+
942+
.area-header {
943+
grid-area: header;
944+
}
945+
.area-install {
946+
grid-area: install;
947+
}
948+
.area-vulns {
949+
grid-area: vulns;
950+
}
951+
.area-readme {
952+
grid-area: readme;
953+
}
954+
.area-sidebar {
955+
grid-area: sidebar;
956+
}
957+
</style>

app/pages/search.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,7 @@ defineOgImageComponent('Default', {
701701
<main class="overflow-x-hidden">
702702
<!-- Sticky search header - positioned below AppHeader (h-14 = 56px) -->
703703
<header class="sticky top-14 z-40 bg-bg/95 backdrop-blur-sm border-b border-border">
704-
<div class="container py-4">
704+
<div class="container-sm py-4">
705705
<h1 class="font-mono text-xl sm:text-2xl font-medium mb-4">search</h1>
706706

707707
<search>
@@ -756,7 +756,7 @@ defineOgImageComponent('Default', {
756756
</header>
757757

758758
<!-- Results area with container padding -->
759-
<div class="container pt-20 pb-6">
759+
<div class="container-sm pt-20 pb-6">
760760
<section v-if="query" aria-label="Search results" @keydown="handleResultsKeydown">
761761
<!-- Initial loading (only after user interaction, not during view transition) -->
762762
<LoadingSpinner v-if="showSearching" :text="$t('search.searching')" />

uno.config.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ export default defineConfig({
9898
} satisfies Theme,
9999
shortcuts: [
100100
// Layout
101-
['container', 'max-w-4xl mx-auto px-4 sm:px-6'],
101+
['container', 'max-w-6xl mx-auto px-4 sm:px-6'],
102+
['container-sm', 'max-w-4xl mx-auto px-4 sm:px-6'],
102103

103104
// Focus states - subtle but accessible
104105
['focus-ring', 'outline-none focus-visible:(ring-2 ring-fg/10 ring-offset-2)'],

0 commit comments

Comments
 (0)