Skip to content

Commit 38960e2

Browse files
rshiggdanielroe
andauthored
feat: add extra wide layout to package page (#200)
Co-authored-by: Daniel Roe <daniel@roe.dev>
1 parent 33d8e09 commit 38960e2

3 files changed

Lines changed: 94 additions & 36 deletions

File tree

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

Lines changed: 90 additions & 33 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">
298+
<main class="container py-8 xl:py-12">
299299
<PackageSkeleton v-if="status === 'pending'" />
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="package-page motion-safe: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') }}
@@ -764,35 +768,28 @@ defineOgImageComponent('Package', {
764768
</div>
765769
</section>
766770

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

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

@@ -883,12 +880,16 @@ defineOgImageComponent('Package', {
883880
:peer-dependencies-meta="displayVersion?.peerDependenciesMeta"
884881
:optional-dependencies="displayVersion?.optionalDependencies"
885882
/>
886-
</div>
883+
</aside>
887884
</div>
888885
</article>
889886

890887
<!-- Error state -->
891-
<div v-else-if="status === 'error'" role="alert" class="py-20 text-center">
888+
<div
889+
v-else-if="status === 'error'"
890+
role="alert"
891+
class="flex flex-col items-center py-20 text-center"
892+
>
892893
<h1 class="font-mono text-2xl font-medium mb-4">{{ $t('package.not_found') }}</h1>
893894
<p class="text-fg-muted mb-8">
894895
{{ error?.message ?? $t('package.not_found_message') }}
@@ -897,3 +898,59 @@ defineOgImageComponent('Package', {
897898
</div>
898899
</main>
899900
</template>
901+
902+
<style scoped>
903+
.package-page {
904+
display: grid;
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+
grid-template-columns: 2fr 1fr;
921+
grid-template-areas:
922+
'header header'
923+
'install install'
924+
'vulns vulns'
925+
'readme sidebar';
926+
}
927+
}
928+
929+
/* Desktop: floating sidebar alongside all content */
930+
@media (min-width: 1280px) {
931+
.package-page {
932+
grid-template-columns: 1fr 20rem;
933+
grid-template-areas:
934+
'header sidebar'
935+
'install sidebar'
936+
'vulns sidebar'
937+
'readme sidebar';
938+
}
939+
}
940+
941+
.area-header {
942+
grid-area: header;
943+
}
944+
.area-install {
945+
grid-area: install;
946+
}
947+
.area-vulns {
948+
grid-area: vulns;
949+
}
950+
.area-readme {
951+
grid-area: readme;
952+
}
953+
.area-sidebar {
954+
grid-area: sidebar;
955+
}
956+
</style>

app/pages/search.vue

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

708708
<search>
@@ -757,7 +757,7 @@ defineOgImageComponent('Default', {
757757
</header>
758758

759759
<!-- Results area with container padding -->
760-
<div class="container pt-20 pb-6">
760+
<div class="container-sm pt-20 pb-6">
761761
<section v-if="query" aria-label="Search results" @keydown="handleResultsKeydown">
762762
<!-- Initial loading (only after user interaction, not during view transition) -->
763763
<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
@@ -99,7 +99,8 @@ export default defineConfig({
9999
} satisfies Theme,
100100
shortcuts: [
101101
// Layout
102-
['container', 'max-w-4xl mx-auto px-4 sm:px-6'],
102+
['container', 'max-w-6xl mx-auto px-4 sm:px-6'],
103+
['container-sm', 'max-w-4xl mx-auto px-4 sm:px-6'],
103104

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

0 commit comments

Comments
 (0)