Cleanup pass 2

This commit is contained in:
adilallo
2026-05-22 13:30:47 -06:00
parent b7c804bac8
commit 753220f97b
76 changed files with 1338 additions and 1020 deletions
@@ -1,5 +1,8 @@
"use client";
/**
* Figma: "Sections / AskOrganizer" (see registry).
*/
import { memo, useCallback, useState } from "react";
import { useTranslation } from "../../../contexts/MessagesContext";
import { useAnalytics } from "../../../hooks";
@@ -43,7 +46,6 @@ const AskOrganizerContainer = memo<AskOrganizerProps>(
subtitle,
description,
buttonText,
buttonHref,
className = "",
variant: variantProp = "centered",
onContactClick,
@@ -51,7 +53,7 @@ const AskOrganizerContainer = memo<AskOrganizerProps>(
const variant = variantProp;
const t = useTranslation();
const defaultButtonText = buttonText ?? t("askOrganizer.buttonText");
const analyticsHref = buttonHref ?? "modal";
const ctaAriaLabel = t("askOrganizer.ariaLabel");
const { trackEvent, trackCustomEvent } = useAnalytics();
const [inquiryOpen, setInquiryOpen] = useState(false);
@@ -74,11 +76,9 @@ const AskOrganizerContainer = memo<AskOrganizerProps>(
const labelledBy = title ? "ask-organizer-headline" : undefined;
const handleContactClick = (
event: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>,
) => {
if (buttonHref) {
// Legacy link CTA: do not intercept navigation.
const handleContactClick = useCallback(
(event: React.MouseEvent<HTMLButtonElement>) => {
event.preventDefault();
trackEvent({
event: "contact_button_click",
category: "engagement",
@@ -86,46 +86,30 @@ const AskOrganizerContainer = memo<AskOrganizerProps>(
component: "AskOrganizer",
variant: resolvedVariant,
});
trackCustomEvent(
"contact_button_click",
{
component: "AskOrganizer",
variant: resolvedVariant,
buttonText: defaultButtonText,
buttonHref: analyticsHref,
buttonHref: "modal",
},
onContactClick as
| ((_data: Record<string, unknown>) => void)
| undefined,
);
return event;
}
event.preventDefault();
trackEvent({
event: "contact_button_click",
category: "engagement",
label: "ask_organizer",
component: "AskOrganizer",
variant: resolvedVariant,
});
trackCustomEvent(
"contact_button_click",
{
component: "AskOrganizer",
variant: resolvedVariant,
buttonText: defaultButtonText,
buttonHref: analyticsHref,
},
onContactClick as
| ((_data: Record<string, unknown>) => void)
| undefined,
);
setInquiryOpen(true);
return event;
};
setInquiryOpen(true);
},
[
defaultButtonText,
onContactClick,
resolvedVariant,
trackCustomEvent,
trackEvent,
],
);
const closeInquiry = useCallback(() => {
setInquiryOpen(false);
@@ -138,7 +122,7 @@ const AskOrganizerContainer = memo<AskOrganizerProps>(
subtitle={subtitle}
description={description}
buttonText={defaultButtonText}
buttonHref={buttonHref}
ctaAriaLabel={ctaAriaLabel}
className={className}
sectionPadding={sectionPadding}
contentGap={`${contentGap} ${styles.container}`}
@@ -12,10 +12,6 @@ export interface AskOrganizerProps {
subtitle?: string;
description?: string;
buttonText?: string;
/**
* @deprecated Modal-only flow (CR-107). Omit; kept optional for Storybook overrides.
*/
buttonHref?: string;
className?: string;
/**
* Ask organizer variant.
@@ -26,7 +22,6 @@ export interface AskOrganizerProps {
component: string;
variant: string;
buttonText: string;
buttonHref?: string;
timestamp: string;
}) => void;
}
@@ -36,7 +31,7 @@ export interface AskOrganizerViewProps {
subtitle?: string;
description?: string;
buttonText: string;
buttonHref?: string;
ctaAriaLabel: string;
className: string;
sectionPadding: string;
contentGap: string;
@@ -44,6 +39,6 @@ export interface AskOrganizerViewProps {
variant: AskOrganizerVariant;
labelledBy?: string;
onContactClick: (
_event: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>,
_event: React.MouseEvent<HTMLButtonElement>,
) => void;
}
@@ -1,6 +1,5 @@
"use client";
import { useTranslation } from "../../../contexts/MessagesContext";
import ContentLockup from "../../type/ContentLockup";
import Button from "../../buttons/Button";
import type { AskOrganizerViewProps } from "./AskOrganizer.types";
@@ -10,7 +9,7 @@ function AskOrganizerView({
subtitle,
description,
buttonText,
buttonHref,
ctaAriaLabel,
className,
sectionPadding,
contentGap,
@@ -19,8 +18,6 @@ function AskOrganizerView({
labelledBy,
onContactClick,
}: AskOrganizerViewProps) {
const t = useTranslation();
const ariaLabel = t("askOrganizer.ariaLabel");
const isUseCaseDetail = variant === "use-case-detail";
const lockupVariant =
variant === "inverse" || isUseCaseDetail ? "ask-inverse" : "ask";
@@ -33,14 +30,13 @@ function AskOrganizerView({
<section
className={`${sectionPadding} ${className}`}
aria-labelledby={labelledBy}
aria-label={labelledBy ? undefined : ariaLabel}
aria-label={labelledBy ? undefined : ctaAriaLabel}
tabIndex={-1}
data-figma-node={isUseCaseDetail ? "22015-42624" : "18116-15960"}
>
<div
className={`mx-auto flex w-full min-w-0 max-w-[1280px] flex-col md:min-w-[358px] ${contentGap} ${isUseCaseDetail ? "items-center" : ""}`}
>
{/* Content Lockup */}
<ContentLockup
title={title}
subtitle={subtitle}
@@ -50,18 +46,16 @@ function AskOrganizerView({
titleId={labelledBy}
/>
{/* Button */}
<div
className={`${buttonContainerClass} flex-wrap gap-y-[var(--spacing-scale-016)]`}
>
<Button
{...(buttonHref ? { href: buttonHref } : {})}
size="small"
buttonType="filled"
palette={buttonPalette}
className="!px-[var(--spacing-scale-010)] md:!px-[var(--spacing-scale-016)] md:!py-[var(--spacing-scale-012)] md:!text-[16px] md:!leading-[20px]"
onClick={onContactClick}
ariaLabel={ariaLabel}
ariaLabel={ctaAriaLabel}
data-testid="ask-organizer-cta"
>
{buttonText}
@@ -1,6 +1,7 @@
"use client";
import { memo } from "react";
import { useTranslation } from "../../../contexts/MessagesContext";
import {
ASSETS,
getAssetPath,
@@ -23,6 +24,14 @@ const ContentBannerContainer = memo<ContentBannerProps>(
contentTone,
}) => {
const variant = variantProp;
const tUseCase = useTranslation("pages.useCasesCompletedRule");
const ruleCardLinkAriaLabel =
variant === "useCase" && rulePreview?.href
? tUseCase("ruleCardLinkAriaLabel").replace(
"{title}",
rulePreview.title,
)
: undefined;
const resolveHorizontalImage = (blogPost: BlogPost): string => {
if (blogPost.frontmatter?.thumbnail?.horizontal) {
@@ -71,6 +80,7 @@ const ContentBannerContainer = memo<ContentBannerProps>(
backgroundImageSection={backgroundImageSection}
rulePreview={rulePreview}
contentTone={contentTone}
ruleCardLinkAriaLabel={ruleCardLinkAriaLabel}
/>
);
},
@@ -41,4 +41,6 @@ export interface ContentBannerViewProps {
backgroundImageSection?: string;
rulePreview?: ContentBannerRulePreview;
contentTone?: ContentContainerToneValue;
/** `useCase` only: aria-label for linked rule preview. */
ruleCardLinkAriaLabel?: string;
}
@@ -3,7 +3,6 @@
import Image from "next/image";
import Link from "next/link";
import { memo } from "react";
import { useTranslation } from "../../../contexts/MessagesContext";
import ContentContainer from "../../content/ContentContainer";
import Rule from "../../cards/Rule";
import {
@@ -155,6 +154,7 @@ function ContentBannerUseCaseView({
contentTone = "inverse",
leadingImageSrc,
leadingImageAlt,
ruleCardLinkAriaLabel,
}: Pick<
ContentBannerViewProps,
| "post"
@@ -162,8 +162,8 @@ function ContentBannerUseCaseView({
| "contentTone"
| "leadingImageSrc"
| "leadingImageAlt"
| "ruleCardLinkAriaLabel"
>) {
const t = useTranslation("pages.useCasesCompletedRule");
if (!rulePreview) {
return null;
}
@@ -198,10 +198,7 @@ function ContentBannerUseCaseView({
<Link
href={rulePreview.href}
className="block w-full rounded-[24px] outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-border-default-brand-primary)] focus-visible:ring-offset-2"
aria-label={t("ruleCardLinkAriaLabel").replace(
"{title}",
rulePreview.title,
)}
aria-label={ruleCardLinkAriaLabel ?? rulePreview.title}
>
<Rule
title={rulePreview.title}
@@ -6,6 +6,7 @@
import { memo, useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { useTranslation } from "../../../contexts/MessagesContext";
import { logger } from "../../../../lib/logger";
import { prepareFreshCreateFlowEntry } from "../../../(app)/create/utils/prepareFreshCreateFlowEntry";
import {
@@ -34,6 +35,8 @@ declare global {
const RuleStackContainer = memo<RuleStackProps>(
({ className = "", initialGridEntries, translationNamespace, twoColumnsFromMd }) => {
const router = useRouter();
const namespace = translationNamespace ?? "pages.home.ruleStack";
const t = useTranslation(namespace);
const [gridEntries, setGridEntries] = useState<TemplateGridCardEntry[] | null>(
() => initialGridEntries ?? null,
);
@@ -107,7 +110,9 @@ const RuleStackContainer = memo<RuleStackProps>(
className={className}
onTemplateClick={handleTemplateClick}
gridEntries={gridEntries}
translationNamespace={translationNamespace ?? "pages.home.ruleStack"}
sectionTitle={t("title")}
sectionSubtitle={t("subtitle")}
seeAllTemplatesLabel={t("button.seeAllTemplates")}
twoColumnsFromMd={twoColumnsFromMd}
/>
);
@@ -23,6 +23,8 @@ export interface RuleStackViewProps {
onTemplateClick: (_slug: string) => void;
/** `null` while loading curated templates from the API. */
gridEntries: TemplateGridCardEntry[] | null;
translationNamespace: string;
sectionTitle: string;
sectionSubtitle: string;
seeAllTemplatesLabel: string;
twoColumnsFromMd?: boolean;
}
@@ -1,6 +1,5 @@
"use client";
import { useTranslation } from "../../../contexts/MessagesContext";
import SectionHeader from "../../type/SectionHeader";
import Button from "../../buttons/Button";
import { GovernanceTemplateGrid } from "../GovernanceTemplateGrid";
@@ -12,12 +11,11 @@ export function RuleStackView({
className,
onTemplateClick,
gridEntries,
translationNamespace,
sectionTitle,
sectionSubtitle,
seeAllTemplatesLabel,
twoColumnsFromMd = false,
}: RuleStackViewProps) {
const t = useTranslation(translationNamespace);
const buttonText = t("button.seeAllTemplates");
return (
<section
data-figma-node="22085-860413"
@@ -35,8 +33,8 @@ export function RuleStackView({
`}
>
<SectionHeader
title={t("title")}
subtitle={t("subtitle")}
title={sectionTitle}
subtitle={sectionSubtitle}
variant="multi-line"
ruleStackDesktopTypeScale
twoColumnsFromMd={twoColumnsFromMd}
@@ -69,7 +67,7 @@ export function RuleStackView({
size="large"
href="/templates"
>
{buttonText}
{seeAllTemplatesLabel}
</Button>
</div>
</section>