Performance follow-ups

This commit is contained in:
adilallo
2026-05-26 07:24:36 -06:00
parent 3be188a3cc
commit eded97559d
16 changed files with 432 additions and 72 deletions
@@ -23,14 +23,13 @@ const ContentThumbnailTemplateContainer = memo<ContentThumbnailTemplateProps>(
}) => {
const variant = variantProp;
const sizing = sizingProp;
// Get article-specific background image from frontmatter
const getBackgroundImage = (
post: ContentThumbnailTemplateProps["post"],
variant: "vertical" | "horizontal",
orientation: "vertical" | "horizontal",
): string => {
if (post.frontmatter?.thumbnail) {
const imageName =
variant === "vertical"
orientation === "vertical"
? post.frontmatter.thumbnail.vertical
: post.frontmatter.thumbnail.horizontal;
@@ -47,12 +46,21 @@ const ContentThumbnailTemplateContainer = memo<ContentThumbnailTemplateProps>(
? slug
: contentCatalogSlugForFallback(slug);
return variant === "vertical"
return orientation === "vertical"
? contentBlogVerticalPath(resolvedSlug)
: contentBlogHorizontalPath(resolvedSlug);
};
const backgroundImage = getBackgroundImage(post, variant);
// For "responsive", emit both orientations so the <picture> source can
// swap at smd without a second card in the DOM.
const backgroundImage =
variant === "responsive"
? getBackgroundImage(post, "horizontal")
: getBackgroundImage(post, variant);
const backgroundImageSmd =
variant === "responsive"
? getBackgroundImage(post, "vertical")
: undefined;
return (
<ContentThumbnailTemplateView
@@ -61,6 +69,7 @@ const ContentThumbnailTemplateContainer = memo<ContentThumbnailTemplateProps>(
variant={variant}
sizing={sizing}
backgroundImage={backgroundImage}
backgroundImageSmd={backgroundImageSmd}
/>
);
},
@@ -1,6 +1,9 @@
import type { BlogPost } from "../../../../lib/content";
export type ContentThumbnailTemplateVariantValue = "vertical" | "horizontal";
export type ContentThumbnailTemplateVariantValue =
| "vertical"
| "horizontal"
| "responsive";
export type ContentThumbnailTemplateSizingValue = "fluid" | "fixed";
@@ -8,7 +11,8 @@ export interface ContentThumbnailTemplateProps {
post: BlogPost;
className?: string;
/**
* Content thumbnail variant.
* vertical | horizontal — single layout. responsive — horizontal at <smd,
* vertical at ≥smd (Learn grid); single card, viewport-swapped via <picture>.
*/
variant?: ContentThumbnailTemplateVariantValue;
/**
@@ -21,7 +25,9 @@ export interface ContentThumbnailTemplateProps {
export interface ContentThumbnailTemplateViewProps {
post: BlogPost;
className: string;
variant: "vertical" | "horizontal";
variant: ContentThumbnailTemplateVariantValue;
sizing: ContentThumbnailTemplateSizingValue;
backgroundImage: string;
/** Wide-viewport image source for variant="responsive" (≥smd). */
backgroundImageSmd?: string;
}
@@ -9,7 +9,41 @@ function ContentThumbnailTemplateView({
variant,
sizing,
backgroundImage,
backgroundImageSmd,
}: ContentThumbnailTemplateViewProps) {
if (variant === "responsive") {
// Single card; <picture> swaps the orientation-specific image at smd
// (530px), aspect-ratio and content positioning switch via Tailwind.
return (
<Link
href={`/blog/${post.slug}`}
className={`group block w-full transition-transform duration-200 hover:scale-[1.02] ${className}`}
>
<div className="relative aspect-[320/225.5] w-full overflow-hidden smd:aspect-[260/390]">
<div className="absolute inset-0 z-0">
<picture>
{backgroundImageSmd ? (
<source
media="(min-width: 530px)"
srcSet={backgroundImageSmd}
/>
) : null}
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={backgroundImage}
alt=""
className="pointer-events-none size-full object-cover"
/>
</picture>
</div>
<div className="absolute left-[4.375%] top-[6.099%] z-20 w-[71.875%] smd:left-[6.923%] smd:top-[4.615%] smd:w-[76.923%]">
<ContentContainer post={post} size="xs" />
</div>
</div>
</Link>
);
}
if (variant === "vertical") {
if (sizing === "fixed") {
return (