-
Notifications
You must be signed in to change notification settings - Fork 355
Expand file tree
/
Copy pathindex.tsx
More file actions
93 lines (83 loc) · 2.91 KB
/
Copy pathindex.tsx
File metadata and controls
93 lines (83 loc) · 2.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import { clsx } from 'clsx';
import { Image } from '~/components/image';
import { Link } from '~/components/link';
export interface BlogPostCardBlogPost {
id: string;
author?: string | null;
content: string;
date: string;
image?: {
src: string;
alt: string;
};
href: string;
title: string;
}
interface Props {
blogPost: BlogPostCardBlogPost;
className?: string;
}
export function BlogPostCard({ blogPost, className }: Props) {
const { author, content, date, href, image, title } = blogPost;
return (
<Link
className={clsx(
'group max-w-full rounded-b-lg rounded-t-2xl text-foreground ring-primary ring-offset-4 @container focus:outline-0 focus-visible:ring-2',
className,
)}
href={href}
>
<div className="aspect-h-3 aspect-w-4 relative mb-4 w-full overflow-hidden rounded-2xl bg-contrast-100">
{image?.src != null && image.src !== '' ? (
<Image
alt={image.alt}
className="object-cover transition-transform duration-500 ease-out group-hover:scale-110"
fill
sizes="(min-width: 80rem) 25vw, (min-width: 56rem) 33vw, (min-width: 28rem) 50vw, 100vw"
src={image.src}
/>
) : (
<div className="p-4 text-5xl font-bold leading-none tracking-tighter text-foreground/15">
{title}
</div>
)}
</div>
<div className="text-lg font-medium leading-snug">{title}</div>
<p className="mb-3 mt-1.5 line-clamp-3 text-sm font-normal text-contrast-400">{content}</p>
<div className="text-sm">
<time dateTime={date}>
{new Date(date).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric',
})}
</time>
{date !== '' && author != null && author !== '' && (
<span className="after:mx-2 after:content-['•']" />
)}
{author != null && author !== '' && <span>{author}</span>}
</div>
</Link>
);
}
export function BlogPostCardSkeleton({ className }: { className?: string }) {
return (
<div className={clsx('flex max-w-md animate-pulse flex-col gap-2 rounded-xl', className)}>
{/* Image */}
<div className="aspect-h-3 aspect-w-4 overflow-hidden rounded-xl bg-contrast-100" />
{/* Title */}
<div className="h-4 w-24 rounded-lg bg-contrast-100" />
{/* Content */}
<div className="h-3 w-full rounded-lg bg-contrast-100" />
<div className="h-3 w-full rounded-lg bg-contrast-100" />
<div className="h-3 w-1/2 rounded-lg bg-contrast-100" />
<div className="flex flex-wrap items-center">
{/* Date */}
<div className="h-4 w-16 rounded-lg bg-contrast-100" />
<span className="after:mx-2 after:text-contrast-100 after:content-['•']" />
{/* Author */}
<div className="h-4 w-20 rounded-lg bg-contrast-100" />
</div>
</div>
);
}