Files
community-rule/app/components/content/ContentContainer/ContentContainer.container.tsx
T
adilalloandCursor c180e79c38 Give every public route its own description, and keep canonicals and structured data on the host that serves the page.
Decorative images on the marketing pages stay quiet, and every dialog close button is named Close.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-11-04 11:04:52 -07:00

140 lines
5.3 KiB
TypeScript

"use client";
/**
* Figma: "Components" / Container (19614-14838, 19003-23432).
* XS thumbnail copy: title 18/22, description 12/16, metadata 10/14.
*/
import { memo } from "react";
import {
contentBlogTagPath,
contentCatalogSlugForFallback,
CONTENT_CATALOG_SLUG_ORDER,
} from "../../../../lib/assetUtils";
import ContentContainerView from "./ContentContainer.view";
import type { ContentContainerProps } from "./ContentContainer.types";
const ContentContainerContainer = memo<ContentContainerProps>(
({
post,
width: widthProp,
size: sizeProp = "responsive",
tone: toneProp = "inverse",
leadingImageSrc,
leadingImageAlt,
showLeadingImage: showLeadingImageProp = true,
showByline: showBylineProp = true,
}) => {
const size = sizeProp;
const tone = toneProp;
const showLeadingImage = showLeadingImageProp;
const showByline = showBylineProp;
const width =
widthProp ?? (size === "useCase" ? "100%" : "200px");
const onLight = tone === "onLight";
const titleColor = onLight
? "text-[var(--color-content-default-primary)] group-hover:text-[var(--color-content-default-brand-primary)]"
: "text-[var(--color-content-invert-brand-royal)] group-hover:text-blue-200";
const bodyColor = onLight
? "text-[var(--color-content-default-secondary)]"
: "text-[var(--color-content-invert-brand-royal)]";
const getIconImage = (slug: string): string => {
const resolvedSlug =
CONTENT_CATALOG_SLUG_ORDER.indexOf(
slug as (typeof CONTENT_CATALOG_SLUG_ORDER)[number],
) >= 0
? slug
: contentCatalogSlugForFallback(slug);
return contentBlogTagPath(resolvedSlug);
};
const iconImage = leadingImageSrc ?? getIconImage(post.slug);
const iconAlt = leadingImageAlt ?? "";
const formattedDate = new Date(post.frontmatter.date).toLocaleDateString(
"en-US",
{
year: "numeric",
month: "long",
},
);
const isUseCase = size === "useCase";
const containerClasses =
size === "xs"
? "relative z-20 flex h-full flex-col gap-[var(--space-300)]"
: isUseCase
? "relative z-20 flex h-full w-full min-w-0 flex-col gap-[var(--space-600)]"
: "relative z-20 h-full flex flex-col gap-[var(--space-300)] sm:gap-[var(--space-400)] md:gap-[18px] lg:gap-[var(--space-600)]";
const contentGapClasses =
size === "xs"
? "flex flex-col gap-[var(--space-200)]"
: isUseCase
? "flex w-full min-w-0 flex-col gap-[var(--space-400)]"
: "flex flex-col gap-[var(--space-200)] sm:gap-[var(--space-300)] md:gap-[var(--space-200)] lg:gap-[var(--space-400)] xl:gap-[var(--space-100)]";
const textGapClasses =
size === "xs"
? "flex flex-col gap-[var(--space-100)]"
: isUseCase
? "flex w-full min-w-0 flex-col gap-[var(--space-100)]"
: "flex flex-col gap-[var(--space-100)] md:gap-[var(--space-050)] lg:gap-[var(--space-100)]";
const titleClasses =
size === "xs"
? `font-bricolage-grotesque font-medium text-[18px] leading-[22px] transition-colors ${titleColor}`
: isUseCase
? `w-full font-bricolage-grotesque font-medium text-[32px] leading-[110%] lg:text-medium-display transition-colors ${titleColor}`
: `font-bricolage-grotesque font-medium text-xx-small-display sm:text-x-small-display md:text-[32px] md:leading-[110%] lg:text-medium-display xl:text-x-large-display transition-colors ${titleColor}`;
const descriptionClasses =
size === "xs"
? `text-x-small-paragraph max-w-md ${bodyColor}`
: isUseCase
? `w-full text-small-paragraph lg:text-large-paragraph ${bodyColor}`
: `text-x-small-paragraph sm:text-small-paragraph md:text-small-paragraph lg:text-large-paragraph xl:text-x-large-paragraph ${bodyColor}`;
const authorClasses =
size === "xs"
? `overflow-hidden text-ellipsis whitespace-nowrap text-xx-small-paragraph ${bodyColor}`
: isUseCase
? `overflow-hidden text-ellipsis whitespace-nowrap text-x-small-paragraph lg:text-small-paragraph ${bodyColor}`
: `text-xx-small-paragraph md:text-x-small-paragraph lg:text-small-paragraph xl:text-large-paragraph ${bodyColor}`;
const dateClasses =
size === "xs"
? `overflow-hidden text-ellipsis whitespace-nowrap text-xx-small-paragraph ${bodyColor}`
: isUseCase
? `overflow-hidden text-ellipsis whitespace-nowrap text-x-small-paragraph lg:text-small-paragraph ${bodyColor}`
: `text-xx-small-paragraph md:text-x-small-paragraph lg:text-small-paragraph xl:text-large-paragraph ${bodyColor}`;
return (
<ContentContainerView
post={post}
width={width}
size={size}
tone={tone}
iconImage={iconImage}
iconAlt={iconAlt}
showLeadingImage={showLeadingImage}
showByline={showByline}
containerClasses={containerClasses}
contentGapClasses={contentGapClasses}
textGapClasses={textGapClasses}
titleClasses={titleClasses}
descriptionClasses={descriptionClasses}
authorClasses={authorClasses}
dateClasses={dateClasses}
formattedDate={formattedDate}
/>
);
},
);
ContentContainerContainer.displayName = "ContentContainer";
export default ContentContainerContainer;