Match the Learn guide grid to the frames, and put the tag and small Rule on the guide card.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
adilalloandCursor committed 2026-11-03 21:00:12 -07:00
1 parent 9ea3f9fd0a
commit 4b0d15e89b
8 files changed
+99 -12

No files matched your search

+16 -2
View File
@@ -32,6 +32,20 @@ export const metadata: Metadata = routeMetadata("/learn", {
const CASE_STUDY_TILE_RADIUS_CLASS = "rounded-[23.093px]";
/** Figma card grid: 1 column below 640, 2 from 640, 3 from 1024, 4 from 1440. */
const ARTICLE_GRID_CLASS = [
"flex flex-col gap-[var(--space-050)]",
"md:flex-row md:flex-wrap md:justify-center md:gap-[var(--space-400)]",
"md:px-[var(--space-1200)] md:py-[var(--space-600)]",
"lg:px-[var(--space-1800)] lg:pt-[var(--space-800)] lg:pb-[var(--space-1800)]",
"[&>*]:min-w-0 [&>*]:w-full",
"md:[&>*]:w-[calc((100%-var(--space-400))/2)]",
"lg:[&>*]:w-[calc((100%-2*var(--space-400))/3)]",
"xl:[&>*]:w-[calc((100%-3*var(--space-400))/4)]",
].join(" ");
const GUIDE_TAG_SRC = "/content/blog/how-communityrule-works-tag.svg";
const CASE_STUDY_LINK_CLASS = [
CASE_STUDY_TILE_RADIUS_CLASS,
"block shrink-0 cursor-pointer outline-none transition-[opacity,transform] duration-200",
@@ -163,14 +177,14 @@ export default function LearnPage() {
<div
data-testid="learn-article-grid"
className="flex flex-col space-y-[var(--space-050)] sm:space-y-[var(--space-200)] sm:px-[var(--space-500)] sm:pt-[var(--space-600)] sm:pb-[var(--space-600)] smd:flex-row smd:flex-wrap smd:justify-center smd:gap-[var(--space-200)] smd:space-y-0 smd:px-[var(--space-500)] smd:pt-[var(--space-600)] smd:pb-[var(--space-600)] md:gap-[var(--space-400)] md:px-[var(--space-800)] xmd:gap-[var(--space-300)] lg:gap-[var(--space-400)] lg:px-[var(--space-1800)] lg:pt-[var(--space-800)] lg:pb-[var(--space-1800)] lg2:gap-x-[var(--space-400)] lg2:gap-y-[var(--space-600)] xl:gap-x-[var(--space-400)] xl:gap-y-[var(--space-400)] [&>*]:min-w-0 [&>*]:w-full smd:[&>*]:w-[calc((100%-var(--space-200))/2)] md:[&>*]:w-[calc((100%-var(--space-400))/2)] xmd:[&>*]:w-[calc((100%-2*var(--space-300))/3)] lg:[&>*]:w-[calc((100%-2*var(--space-400))/3)] lg2:[&>*]:w-[calc((100%-3*var(--space-400))/4)] xl:[&>*]:w-[calc((100%-4*var(--space-400))/5)]"
className={ARTICLE_GRID_CLASS}
>
<ContentThumbnailTemplate
post={guidePost}
variant="responsive"
href={page.guideCard.href}
showByline={false}
showLeadingImage={false}
leadingImageSrc={GUIDE_TAG_SRC}
leadingImageAlt=""
/>
{articlePosts.map((post) => (
@@ -24,6 +24,7 @@ const ContentThumbnailTemplateContainer = memo<ContentThumbnailTemplateProps>(
showByline = true,
showLeadingImage = true,
leadingImageAlt,
leadingImageSrc,
}) => {
const variant = variantProp;
const sizing = sizingProp;
@@ -56,7 +57,7 @@ const ContentThumbnailTemplateContainer = memo<ContentThumbnailTemplateProps>(
};
// For "responsive", emit both orientations so the <picture> source can
// swap at smd without a second card in the DOM.
// swap at md (640px) without a second card in the DOM.
const backgroundImage =
variant === "responsive"
? getBackgroundImage(post, "horizontal")
@@ -78,6 +79,7 @@ const ContentThumbnailTemplateContainer = memo<ContentThumbnailTemplateProps>(
showByline={showByline}
showLeadingImage={showLeadingImage}
leadingImageAlt={leadingImageAlt}
leadingImageSrc={leadingImageSrc}
/>
);
},
@@ -11,8 +11,8 @@ export interface ContentThumbnailTemplateProps {
post: BlogPost;
className?: string;
/**
* vertical | horizontal — single layout. responsive — horizontal at <smd,
* vertical at ≥smd (Learn grid); single card, viewport-swapped via <picture>.
* vertical | horizontal — single layout. responsive — horizontal below md
* (640px), vertical from md up (Learn grid); one card, swapped via <picture>.
*/
variant?: ContentThumbnailTemplateVariantValue;
/**
@@ -28,6 +28,8 @@ export interface ContentThumbnailTemplateProps {
showLeadingImage?: boolean;
/** Alt for the tag mark. Empty when the mark repeats the title. */
leadingImageAlt?: string;
/** Tag mark source. Falls back to the catalog tag for the post slug. */
leadingImageSrc?: string;
}
export interface ContentThumbnailTemplateViewProps {
@@ -42,4 +44,5 @@ export interface ContentThumbnailTemplateViewProps {
showByline: boolean;
showLeadingImage: boolean;
leadingImageAlt?: string;
leadingImageSrc?: string;
}
@@ -14,18 +14,19 @@ function ContentThumbnailTemplateView({
showByline,
showLeadingImage,
leadingImageAlt,
leadingImageSrc,
}: ContentThumbnailTemplateViewProps) {
if (variant === "responsive") {
// Single card; <picture> swaps the orientation-specific image at smd
// (530px), aspect-ratio and content positioning switch via Tailwind.
// Single card; <picture> swaps to the vertical image at md (640px),
// which is where Learn's grid goes from one landscape card to two.
return (
<Link href={href} className={`group block w-full ${className}`}>
<div className="relative aspect-[320/225.5] w-full overflow-hidden smd:aspect-[260/390]">
<div className="relative aspect-[320/225.5] w-full overflow-hidden md:aspect-[260/390]">
<div className="absolute inset-0 z-0">
<picture>
{backgroundImageSmd ? (
<source
media="(min-width: 530px)"
media="(min-width: 640px)"
srcSet={backgroundImageSmd}
/>
) : null}
@@ -37,13 +38,14 @@ function ContentThumbnailTemplateView({
/>
</picture>
</div>
<div className="absolute left-[4.375%] top-[6.099%] z-20 w-[71.875%] max-h-[48%] overflow-hidden smd:left-[6.923%] smd:top-[4.615%] smd:w-[76.923%]">
<div className="absolute left-[4.375%] top-[6.099%] z-20 w-[71.875%] max-h-[68%] overflow-hidden md:left-[6.923%] md:top-[4.615%] md:max-h-[48%] md:w-[76.923%]">
<ContentContainer
post={post}
size="xs"
showByline={showByline}
showLeadingImage={showLeadingImage}
leadingImageAlt={leadingImageAlt}
leadingImageSrc={leadingImageSrc}
/>
</div>
</div>
@@ -72,6 +74,7 @@ function ContentThumbnailTemplateView({
showByline={showByline}
showLeadingImage={showLeadingImage}
leadingImageAlt={leadingImageAlt}
leadingImageSrc={leadingImageSrc}
/>
</div>
</div>
@@ -97,6 +100,7 @@ function ContentThumbnailTemplateView({
showByline={showByline}
showLeadingImage={showLeadingImage}
leadingImageAlt={leadingImageAlt}
leadingImageSrc={leadingImageSrc}
/>
</div>
</div>
@@ -124,6 +128,7 @@ function ContentThumbnailTemplateView({
showByline={showByline}
showLeadingImage={showLeadingImage}
leadingImageAlt={leadingImageAlt}
leadingImageSrc={leadingImageSrc}
/>
</div>
</div>
@@ -149,6 +154,7 @@ function ContentThumbnailTemplateView({
showByline={showByline}
showLeadingImage={showLeadingImage}
leadingImageAlt={leadingImageAlt}
leadingImageSrc={leadingImageSrc}
/>
</div>
</div>