Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 35 additions & 91 deletions apps/blog/src/components/PostCard.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
'use client';
"use client";

import Image from "next/image";
import Link from "next/link";
import { Badge, Card } from "@prisma/eclipse";
import { cn } from "@prisma-docs/ui/lib/cn";

import { AuthorAvatarGroup } from "@/components/AuthorAvatarGroup";
import {
PostCard as SharedPostCard,
type PostCardItem as SharedPostCardItem,
} from "@prisma-docs/ui/components/post-card";
import { type AuthorProfile } from "@prisma-docs/ui/components/author-avatar-group";
import { getAuthorProfiles } from "@/lib/authors";
import { formatDate, formatTag } from "@/lib/format";
import { withBlogBasePathForImageSrc } from "@/lib/url";

Expand All @@ -30,91 +30,35 @@ export function PostCard({
currentCategory: string;
featured?: boolean;
}) {
const isFeatured = featured;
const imageSizes = isFeatured ? "(min-width: 640px) 50vw, 100vw" : "384px";

const containerClassName = cn(
"group grid overflow-hidden",
isFeatured
? "grid-cols-1 md:grid-cols-2 gap-4 bg-background-default rounded-square border border-stroke-neutral shadow-box-low"
: "sm:grid-cols-[1fr_384px] border-b pb-4 sm:pb-6 border-stroke-neutral gap-8",
);
const imageClassName = cn(
"object-cover transition-transform duration-300 group-hover:scale-[1.02]",
!isFeatured && "rounded-square",
);
const imageWrapperClassName = cn(
"relative aspect-video w-full h-full",
isFeatured ? "order-1" : "order-2 max-w-96 hidden sm:block",
);

const titleClassName = cn(
"text-foreground-neutral font-mona-sans mt-4 mb-2",
isFeatured
? "text-2xl font-bold"
: "text-md md:text-lg font-[650] sm:font-bold",
);
const excerptClassName = cn(
"text-sm text-foreground-neutral-weak line-clamp-2",
isFeatured && "leading-[20px]!",
);
const authorClassName = cn(
"items-center gap-2 font-semibold text-sm mt-4 md:mt-0",
isFeatured ? "flex" : "hidden sm:flex",
);

const postBody = (
<>
<div>
<div className="eyebrow flex gap-2 items-center">
{post.tags && post.tags.length > 0 && (
<Badge
color="success"
label={formatTag(
currentCategory !== "show-all" ? currentCategory : post.tags[0],
)}
className="w-fit"
/>
)}
{post.date && (
<span className="text-xs text-foreground-neutral-weak">
{formatDate(new Date(post.date).toISOString())}
</span>
)}
</div>
{post.title && <h2 className={titleClassName}>{post.title}</h2>}
{post.excerpt && <p className={excerptClassName}>{post.excerpt}</p>}
// Transform blog-specific post data to shared component format
const authorProfiles = post.author ? getAuthorProfiles([post.author]) : [];
const author: AuthorProfile | null =
authorProfiles.length > 0
? {
name: authorProfiles[0].name,
imageSrc: authorProfiles[0].imageSrc
? withBlogBasePathForImageSrc(authorProfiles[0].imageSrc)
: null,
}
: null;

const badge =
post.tags && post.tags.length > 0
? formatTag(
currentCategory !== "show-all" ? currentCategory : post.tags[0],
)
: null;

</div>
{post.author && (
<AuthorAvatarGroup authors={[post.author]} className={authorClassName} />
)}
</>
);
const sharedPost: SharedPostCardItem = {
url: post.url,
title: post.title,
date: formatDate(new Date(post.date).toISOString()),
excerpt: post.excerpt,
author,
imageSrc: post.imageSrc ? withBlogBasePathForImageSrc(post.imageSrc) : null,
imageAlt: post.imageAlt,
badge,
};

return (
<Link href={post.url} className={containerClassName}>
{post.imageSrc && (
<div className={imageWrapperClassName}>
<Image
src={withBlogBasePathForImageSrc(post.imageSrc as string)}
alt={post.imageAlt ?? post.title}
fill
sizes={imageSizes}
className={imageClassName}
loading={isFeatured ? "eager" : undefined}
priority={isFeatured}
/>
</div>
)}
{isFeatured ? (
<Card className="order-2 rounded-none! border-none! gap-0 bg-background-default flex flex-col justify-between">
{postBody}
</Card>
) : (
<div className="order-1 flex flex-col justify-between">{postBody}</div>
)}
</Link>
);
return <SharedPostCard post={sharedPost} featured={featured} />;
}
11 changes: 7 additions & 4 deletions apps/site/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,20 @@
},
"dependencies": {
"@base-ui/react": "catalog:",
"@prisma/eclipse": "workspace:^",
"@prisma-docs/ui": "workspace:*",
"@prisma/eclipse": "workspace:^",
"cors": "^2.8.6",
"html-react-parser": "^5.2.17",
"lucide-react": "catalog:",
"next": "catalog:",
"npm-to-yarn": "catalog:",
"posthog-js": "catalog:",
"react": "catalog:",
"react-dom": "catalog:",
"react-tweet": "catalog:",
"posthog-js": "catalog:",
"remark-directive": "catalog:",
"shiki": "3.22.0",
"tailwind-merge": "catalog:",
"zod": "catalog:"
},
"devDependencies": {
Expand All @@ -32,11 +35,11 @@
"@types/node": "catalog:",
"@types/react": "catalog:",
"@types/react-dom": "catalog:",
"babel-plugin-react-compiler": "catalog:",
"next-validate-link": "catalog:",
"postcss": "catalog:",
"tailwindcss": "catalog:",
"tsx": "catalog:",
"typescript": "catalog:",
"babel-plugin-react-compiler": "catalog:"
"typescript": "catalog:"
}
}
10 changes: 10 additions & 0 deletions apps/site/public/icons/technologies/nextjs-light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions apps/site/public/icons/technologies/nextjs.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions apps/site/public/icons/technologies/prisma.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions apps/site/public/icons/technologies/prisma_light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading