Skip to content

Commit c2a3acc

Browse files
authored
chore: improve package details page design (#1036)
1 parent 6795c2d commit c2a3acc

File tree

1 file changed

+268
-69
lines changed
  • app/packages/[group]/[name]/_components

1 file changed

+268
-69
lines changed
Lines changed: 268 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,25 @@
1-
import { Chip, Code, Divider, Link } from "@heroui/react";
1+
import {
2+
faBookOpen,
3+
faBox,
4+
faCalendarAlt,
5+
faCode,
6+
faCodeBranch,
7+
faCube,
8+
faDownload,
9+
faGavel,
10+
faHome,
11+
faTag,
12+
} from "@fortawesome/free-solid-svg-icons";
13+
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
14+
import {
15+
Button,
16+
Card,
17+
CardBody,
18+
CardHeader,
19+
Chip,
20+
Code,
21+
Link,
22+
} from "@heroui/react";
223
import ReactMarkdown from "react-markdown";
324
import { format } from "timeago.js";
425
import type { GetPackageByNameAndVersionQuery } from "~/graphql";
@@ -11,78 +32,256 @@ export function Pack({
1132
numVersion: number;
1233
}) {
1334
return (
14-
<div className="flex flex-col justify-center items-center gap-4 m-4">
15-
<div className="flex justify-center items-center gap-4">
16-
<h1 className="text-3xl font-bold">{pack.name}</h1>
17-
<h2 className="text-lg text-white/50">v{pack.version}</h2>
18-
<Chip>C++{pack.edition.toString().slice(-2)}</Chip>
19-
</div>
20-
<h3 className="text-xl text-white/50">{pack.description}</h3>
21-
<div className="flex flex-col lg:flex-row justify-start gap-4 items-start">
22-
<div className="flex flex-row justify-center gap-1 max-w-[200px]">
23-
<Chip>{numVersion}</Chip>
24-
<h4 className="text-lg font-bold">Versions</h4>
25-
</div>
26-
<div className="flex flex-row justify-center gap-1 max-w-[200px]">
27-
<Chip>{pack.metadata.dependencies?.length ?? 0}</Chip>
28-
<h4 className="text-lg font-bold">Dependencies</h4>
35+
<div className="container mx-auto max-w-7xl px-6 py-8">
36+
{/* Hero Section */}
37+
<div className="mb-8">
38+
<div className="flex flex-col gap-4">
39+
<div className="flex flex-col sm:flex-row sm:items-center gap-4">
40+
<div className="flex items-center gap-3">
41+
<div className="flex items-center justify-center w-12 h-12 bg-gradient-to-br from-primary-500 to-secondary-500 rounded-lg">
42+
<FontAwesomeIcon
43+
icon={faCube}
44+
className="text-white text-lg"
45+
/>
46+
</div>
47+
<div>
48+
<h1 className="text-3xl md:text-4xl font-bold">
49+
{pack.name}
50+
</h1>
51+
<div className="flex items-center gap-2 mt-1">
52+
<FontAwesomeIcon
53+
icon={faTag}
54+
className="text-default-500 text-sm"
55+
/>
56+
<span className="text-lg text-default-500">
57+
v{pack.version}
58+
</span>
59+
</div>
60+
</div>
61+
</div>
62+
<div className="sm:ml-auto">
63+
<Chip
64+
color="primary"
65+
variant="flat"
66+
startContent={
67+
<FontAwesomeIcon
68+
icon={faCode}
69+
className="text-sm"
70+
/>
71+
}
72+
>
73+
C++{pack.edition.toString().slice(-2)}
74+
</Chip>
75+
</div>
76+
</div>
77+
{pack.description && (
78+
<p className="text-xl text-default-600 max-w-3xl">
79+
{pack.description}
80+
</p>
81+
)}
2982
</div>
30-
<div className="flex flex-col justify-center gap-1 max-w-[200px]">
31-
<h4 className="text-lg font-bold">Metadata</h4>
32-
<Chip>{format(pack.published_at)}</Chip>
33-
<Link
34-
isExternal
35-
href={`https://choosealicense.com/licenses/${pack.license.toLowerCase()}/`}
36-
>
37-
{pack.license}
38-
</Link>
83+
</div>
84+
85+
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
86+
{/* Main Content */}
87+
<div className="lg:col-span-2 space-y-6">
88+
{/* Installation */}
89+
<Card className="w-full">
90+
<CardHeader className="pb-3">
91+
<div className="flex items-center gap-2">
92+
<FontAwesomeIcon
93+
icon={faDownload}
94+
className="text-success text-lg"
95+
/>
96+
<h2 className="text-xl font-semibold">
97+
Installation
98+
</h2>
99+
</div>
100+
</CardHeader>
101+
<CardBody className="pt-0">
102+
<p className="text-default-600 mb-3">
103+
Add the following line to your{" "}
104+
<code className="text-sm bg-default-100 px-1 py-0.5 rounded">
105+
cabin.toml
106+
</code>{" "}
107+
file:
108+
</p>
109+
<Code
110+
size="lg"
111+
className="w-full"
112+
>{`"${pack.name}" = "${pack.version}"`}</Code>
113+
</CardBody>
114+
</Card>
115+
116+
{/* README */}
117+
<Card className="w-full">
118+
<CardHeader className="pb-3">
119+
<div className="flex items-center gap-2">
120+
<FontAwesomeIcon
121+
icon={faBookOpen}
122+
className="text-primary text-lg"
123+
/>
124+
<h2 className="text-xl font-semibold">
125+
README
126+
</h2>
127+
</div>
128+
</CardHeader>
129+
<CardBody className="pt-0">
130+
{pack.readme ? (
131+
<div className="prose dark:prose-invert max-w-none">
132+
<ReactMarkdown skipHtml>
133+
{pack.readme}
134+
</ReactMarkdown>
135+
</div>
136+
) : (
137+
<div className="text-center py-8">
138+
<FontAwesomeIcon
139+
icon={faBookOpen}
140+
className="text-default-300 text-3xl mb-3"
141+
/>
142+
<p className="text-default-500">
143+
No README available for this package
144+
</p>
145+
</div>
146+
)}
147+
</CardBody>
148+
</Card>
39149
</div>
40-
<div className="flex flex-col justify-center gap-1 max-w-[200px] break-words">
41-
<h4 className="text-lg font-bold">Install</h4>
42-
<p className="text-xs">
43-
Add the following line to your cabin.toml file:
44-
</p>
45-
<Code>{`"${pack.name}" = "${pack.version}"`}</Code>
150+
151+
{/* Sidebar */}
152+
<div className="space-y-6">
153+
{/* Package Stats */}
154+
<Card>
155+
<CardHeader className="pb-3">
156+
<h3 className="text-lg font-semibold">
157+
Package Info
158+
</h3>
159+
</CardHeader>
160+
<CardBody className="pt-0 space-y-4">
161+
<div className="flex items-center justify-between">
162+
<div className="flex items-center gap-2">
163+
<FontAwesomeIcon
164+
icon={faBox}
165+
className="text-default-500"
166+
/>
167+
<span className="text-default-600">
168+
Versions
169+
</span>
170+
</div>
171+
<Chip size="sm" variant="flat">
172+
{numVersion}
173+
</Chip>
174+
</div>
175+
<div className="flex items-center justify-between">
176+
<div className="flex items-center gap-2">
177+
<FontAwesomeIcon
178+
icon={faCodeBranch}
179+
className="text-default-500"
180+
/>
181+
<span className="text-default-600">
182+
Dependencies
183+
</span>
184+
</div>
185+
<Chip size="sm" variant="flat">
186+
{pack.metadata.dependencies?.length ?? 0}
187+
</Chip>
188+
</div>
189+
<div className="flex items-center justify-between">
190+
<div className="flex items-center gap-2">
191+
<FontAwesomeIcon
192+
icon={faCalendarAlt}
193+
className="text-default-500"
194+
/>
195+
<span className="text-default-600">
196+
Published
197+
</span>
198+
</div>
199+
<Chip size="sm" variant="flat">
200+
{format(pack.published_at)}
201+
</Chip>
202+
</div>
203+
<div className="flex items-center justify-between">
204+
<div className="flex items-center gap-2">
205+
<FontAwesomeIcon
206+
icon={faGavel}
207+
className="text-default-500"
208+
/>
209+
<span className="text-default-600">
210+
License
211+
</span>
212+
</div>
213+
<Link
214+
isExternal
215+
href={`https://choosealicense.com/licenses/${pack.license.toLowerCase()}/`}
216+
size="sm"
217+
>
218+
{pack.license}
219+
</Link>
220+
</div>
221+
</CardBody>
222+
</Card>
223+
224+
{/* Links */}
225+
<Card>
226+
<CardHeader className="pb-3">
227+
<h3 className="text-lg font-semibold">Links</h3>
228+
</CardHeader>
229+
<CardBody className="pt-0 space-y-3">
230+
{pack.metadata.package.homepage && (
231+
<Button
232+
as={Link}
233+
href={pack.metadata.package.homepage}
234+
isExternal
235+
variant="flat"
236+
className="w-full justify-start"
237+
startContent={
238+
<FontAwesomeIcon
239+
icon={faHome}
240+
className="text-sm"
241+
/>
242+
}
243+
>
244+
Homepage
245+
</Button>
246+
)}
247+
{pack.metadata.package.documentation && (
248+
<Button
249+
as={Link}
250+
href={pack.metadata.package.documentation}
251+
isExternal
252+
variant="flat"
253+
className="w-full justify-start"
254+
startContent={
255+
<FontAwesomeIcon
256+
icon={faBookOpen}
257+
className="text-sm"
258+
/>
259+
}
260+
>
261+
Documentation
262+
</Button>
263+
)}
264+
{pack.metadata.package.repository && (
265+
<Button
266+
as={Link}
267+
href={pack.metadata.package.repository}
268+
isExternal
269+
variant="flat"
270+
className="w-full justify-start"
271+
startContent={
272+
<FontAwesomeIcon
273+
icon={faCodeBranch}
274+
className="text-sm"
275+
/>
276+
}
277+
>
278+
Repository
279+
</Button>
280+
)}
281+
</CardBody>
282+
</Card>
46283
</div>
47-
{pack.metadata.package.homepage && (
48-
<div className="flex flex-col justify-center gap-1 max-w-[200px] break-all">
49-
<h4 className="text-lg font-bold">Homepage</h4>
50-
<Link isExternal href={pack.metadata.package.homepage}>
51-
{pack.metadata.package.homepage}
52-
</Link>
53-
</div>
54-
)}
55-
{pack.metadata.package.documentation && (
56-
<div className="flex flex-col justify-center gap-1 max-w-[200px] break-all">
57-
<h4 className="text-lg font-bold">Documentation</h4>
58-
<Link
59-
isExternal
60-
href={pack.metadata.package.documentation}
61-
>
62-
{pack.metadata.package.documentation}
63-
</Link>
64-
</div>
65-
)}
66-
{pack.metadata.package.repository && (
67-
<div className="flex flex-col justify-center gap-1 max-w-[200px] break-all">
68-
<h4 className="text-lg font-bold">Repository</h4>
69-
<Link
70-
isExternal
71-
href={pack.metadata.package.repository}
72-
>
73-
{pack.metadata.package.repository}
74-
</Link>
75-
</div>
76-
)}
77284
</div>
78-
<Divider />
79-
{pack.readme ? (
80-
<div className="prose dark:prose-invert">
81-
<ReactMarkdown skipHtml>{pack.readme}</ReactMarkdown>
82-
</div>
83-
) : (
84-
<p className="text-white/50">no readme found</p>
85-
)}
86285
</div>
87286
);
88287
}

0 commit comments

Comments
 (0)