1- import { ArrowUpRight , Github } from 'lucide-react'
1+ import { ArrowRight , Github } from 'lucide-react'
22
33import { InstallCommand , ProjectLink } from '@/components/catalog-row'
44import { Button } from '@/components/ui/button'
55import type { CatalogProject } from '@/data/projects'
6+ import { formatRelativeTime } from '@/lib/format'
7+
8+ const projectArtwork = {
9+ 'period-space' : '/project-emblems/period-space.webp' ,
10+ pastebridge : '/project-emblems/pastebridge.webp' ,
11+ 'mmf-golden-gate-fixer' : '/project-emblems/mmf-golden-gate-fixer.webp' ,
12+ } as const
13+
14+ function ProjectArtwork ( { id } : { id : string } ) {
15+ const src =
16+ projectArtwork [ id as keyof typeof projectArtwork ] ??
17+ projectArtwork [ 'period-space' ]
18+
19+ return (
20+ < img
21+ src = { src }
22+ alt = ""
23+ width = "800"
24+ height = "800"
25+ loading = "lazy"
26+ decoding = "async"
27+ className = "h-full w-full object-cover"
28+ />
29+ )
30+ }
631
732export function ProjectPreviewCard ( { project } : { project : CatalogProject } ) {
833 const githubUrl = project . githubUrl ?? project . href
@@ -11,44 +36,63 @@ export function ProjectPreviewCard({ project }: { project: CatalogProject }) {
1136 )
1237
1338 return (
14- < article className = "flex min-h-64 flex-col justify-between overflow-hidden rounded-3xl border bg-card p-6 shadow-sm sm:p-8" >
15- < div >
16- < h3 className = "max-w-3xl font-display text-3xl font-semibold tracking-[-0.035em] text-balance sm:text-4xl" >
39+ < article className = "group flex min-h-full flex-col overflow-hidden rounded-[1.75rem] border border-black/[0.06] bg-card shadow-[0_1px_2px_rgba(0,0,0,0.03)] transition-[transform,box-shadow] duration-500 ease-out hover:-translate-y-1 hover:shadow-[0_24px_60px_-30px_rgba(15,23,42,0.35)] motion-reduce:transform-none motion-reduce:transition-none dark:border-white/[0.08] dark:shadow-none dark:hover:shadow-[0_24px_60px_-30px_rgba(0,0,0,0.8)]" >
40+ < div className = "relative h-56 overflow-hidden bg-muted sm:h-64" >
41+ < div className = "absolute inset-0 transition-transform duration-700 ease-out group-hover:scale-[1.025] motion-reduce:transform-none" >
42+ < ProjectArtwork id = { project . id } />
43+ </ div >
44+ </ div >
45+
46+ < div className = "flex flex-1 flex-col p-6 sm:p-7" >
47+ < div className = "mb-5 flex min-h-5 items-center gap-2 text-xs text-muted-foreground" >
48+ { project . language ? < span > { project . language } </ span > : null }
49+ { project . language && project . updatedAt ? (
50+ < span aria-hidden = "true" > ·</ span >
51+ ) : null }
52+ { project . updatedAt ? (
53+ < span > Updated { formatRelativeTime ( project . updatedAt ) } </ span >
54+ ) : null }
55+ </ div >
56+
57+ < h3 className = "font-display text-2xl font-semibold tracking-[-0.035em] text-balance sm:text-[1.75rem]" >
1758 { project . name }
1859 </ h3 >
19- < p className = "mt-3 max-w-2xl text-base leading-relaxed text-muted-foreground sm:text-lg " >
60+ < p className = "mt-3 text-[0.9375rem] leading-6 text-muted-foreground sm:text-base " >
2061 { project . description }
2162 </ p >
22- </ div >
2363
24- < div className = "mt-8 flex flex-col gap-5 lg:flex-row lg:items-end lg:justify-between" >
2564 { project . installCommand ? (
26- < div className = "min-w-0 max -w-2xl flex-1 " >
65+ < div className = "mt-6 min -w-0 " >
2766 < InstallCommand command = { project . installCommand } />
2867 </ div >
2968 ) : null }
3069
31- < div className = "flex shrink-0 flex-wrap items-center gap-2" >
70+ < div className = "mt-auto flex flex -wrap items-center gap-2 pt-7 " >
3271 { hasProjectView ? (
33- < Button asChild >
72+ < Button asChild className = "rounded-full px-5" >
3473 { project . homepageUrl && ! project . to ? (
3574 < a href = { project . homepageUrl } target = "_blank" rel = "noreferrer" >
36- View project
37- < ArrowUpRight data-icon = "inline-end" />
75+ Explore project
76+ < ArrowRight data-icon = "inline-end" />
3877 </ a >
3978 ) : (
4079 < ProjectLink project = { project } >
41- View project
42- < ArrowUpRight data-icon = "inline-end" />
80+ Explore project
81+ < ArrowRight data-icon = "inline-end" />
4382 </ ProjectLink >
4483 ) }
4584 </ Button >
4685 ) : null }
4786 { githubUrl ? (
48- < Button asChild variant = "outline" >
87+ < Button
88+ asChild
89+ variant = "ghost"
90+ size = "icon"
91+ className = "rounded-full"
92+ >
4993 < a href = { githubUrl } target = "_blank" rel = "noreferrer" >
50- < Github data-icon = "inline-start" />
51- Source
94+ < Github />
95+ < span className = "sr-only" > View { project . name } source </ span >
5296 </ a >
5397 </ Button >
5498 ) : null }
0 commit comments