Feature Grid #13

Merged
an.di merged 17 commits from adilallo/component/FeatureGrid into main 2025-08-28 20:30:26 +00:00
4 changed files with 120 additions and 14 deletions
Showing only changes of commit 6a66f5f61f - Show all commits
+62 -3
View File
@@ -11,30 +11,89 @@ const AskOrganizer = ({
buttonText = "Ask an organizer", buttonText = "Ask an organizer",
buttonHref = "#", buttonHref = "#",
className = "", className = "",
variant = "centered", // centered, left-aligned, compact
onContactClick, // Analytics callback
}) => { }) => {
// Analytics tracking for contact button clicks
const handleContactClick = (event) => {
// Track contact button interaction
if (onContactClick) {
onContactClick({
event: "contact_button_click",
component: "AskOrganizer",
variant,
buttonText,
buttonHref,
timestamp: new Date().toISOString(),
});
}
// Additional analytics tracking (can be expanded)
if (typeof window !== "undefined" && window.gtag) {
window.gtag("event", "contact_button_click", {
event_category: "engagement",
event_label: "ask_organizer",
value: 1,
});
}
};
// Variant-specific styling
const variantStyles = {
centered: {
container: "text-center",
buttonContainer: "flex justify-center",
},
"left-aligned": {
container: "text-left",
buttonContainer: "flex justify-start",
},
compact: {
container: "text-center",
buttonContainer: "flex justify-center",
},
};
const styles = variantStyles[variant] || variantStyles.centered;
// Section padding based on variant
const sectionPadding =
variant === "compact"
? "py-[var(--spacing-scale-016)] px-[var(--spacing-scale-016)] md:py-[var(--spacing-scale-032)] md:px-[var(--spacing-scale-032)]"
: "py-[var(--spacing-scale-032)] px-[var(--spacing-scale-032)] md:py-[var(--spacing-scale-096)] md:px-[var(--spacing-scale-064)]";
// Gap between content and button based on variant
const contentGap =
variant === "compact"
? "gap-[var(--spacing-scale-020)]"
: "gap-[var(--spacing-scale-040)]";
return ( return (
<section <section
className={`py-[var(--spacing-scale-032)] px-[var(--spacing-scale-032)] md:py-[var(--spacing-scale-096)] md:px-[var(--spacing-scale-064)] ${className}`} className={`${sectionPadding} ${className}`}
aria-labelledby="ask-organizer-headline" aria-labelledby="ask-organizer-headline"
role="region" role="region"
tabIndex={-1} tabIndex={-1}
> >
<div className="flex flex-col gap-[var(--spacing-scale-040)]"> <div className={`flex flex-col ${contentGap} ${styles.container}`}>
{/* Content Lockup */} {/* Content Lockup */}
<ContentLockup <ContentLockup
title={title} title={title}
subtitle={subtitle} subtitle={subtitle}
description={description} description={description}
variant="ask" variant="ask"
alignment={variant === "left-aligned" ? "left" : "center"}
/> />
{/* Button */} {/* Button */}
<div className="flex justify-center"> <div className={styles.buttonContainer}>
<Button <Button
href={buttonHref} href={buttonHref}
size="large" size="large"
variant="default" variant="default"
className="xl:!px-[var(--spacing-scale-020)] xl:!py-[var(--spacing-scale-012)] xl:!text-[24px] xl:!leading-[28px]" className="xl:!px-[var(--spacing-scale-020)] xl:!py-[var(--spacing-scale-012)] xl:!text-[24px] xl:!leading-[28px]"
onClick={handleContactClick}
aria-label={`${buttonText} - Contact an organizer for help`}
> >
{buttonText} {buttonText}
</Button> </Button>
+14 -6
View File
@@ -12,6 +12,7 @@ const ContentLockup = ({
variant = "hero", variant = "hero",
linkText, linkText,
linkHref, linkHref,
alignment = "center", // center, left
}) => { }) => {
// Variant-specific styling // Variant-specific styling
const variantStyles = { const variantStyles = {
@@ -50,12 +51,11 @@ const ContentLockup = ({
container: "flex flex-col gap-[var(--spacing-scale-008)] relative z-10", container: "flex flex-col gap-[var(--spacing-scale-008)] relative z-10",
textContainer: "flex flex-col gap-[var(--spacing-scale-008)]", textContainer: "flex flex-col gap-[var(--spacing-scale-008)]",
titleGroup: "flex flex-col gap-[var(--spacing-scale-008)]", titleGroup: "flex flex-col gap-[var(--spacing-scale-008)]",
titleContainer: titleContainer: "flex gap-[var(--spacing-scale-008)] items-center",
"flex gap-[var(--spacing-scale-008)] items-center justify-center",
title: title:
"font-bricolage-grotesque font-medium text-[36px] leading-[110%] tracking-[0] md:text-[44px] md:leading-[110%] xl:text-[52px] xl:leading-[110%] text-[var(--color-content-default-brand-primary)] text-center", "font-bricolage-grotesque font-medium text-[36px] leading-[110%] tracking-[0] md:text-[44px] md:leading-[110%] xl:text-[52px] xl:leading-[110%] text-[var(--color-content-default-brand-primary)]",
subtitle: subtitle:
"font-inter font-normal text-[18px] leading-[130%] tracking-[0] md:text-[24px] md:leading-[32px] text-[var(--color-content-default-primary)] text-center", "font-inter font-normal text-[18px] leading-[130%] tracking-[0] md:text-[24px] md:leading-[32px] text-[var(--color-content-default-primary)]",
shape: shape:
"w-[16px] h-[16px] md:w-[20px] md:h-[20px] lg:w-[24px] lg:h-[24px]", "w-[16px] h-[16px] md:w-[20px] md:h-[20px] lg:w-[24px] lg:h-[24px]",
}, },
@@ -67,8 +67,16 @@ const ContentLockup = ({
<div className={styles.container}> <div className={styles.container}>
{variant === "ask" ? ( {variant === "ask" ? (
/* Simplified structure for ask variant */ /* Simplified structure for ask variant */
<div className={styles.titleGroup}> <div
<div className={styles.titleContainer}> className={`${styles.titleGroup} ${
alignment === "left" ? "text-left" : "text-center"
}`}
>
<div
className={`${styles.titleContainer} ${
alignment === "left" ? "justify-start" : "justify-center"
}`}
>
<h1 className={styles.title}>{title}</h1> <h1 className={styles.title}>{title}</h1>
</div> </div>
<h2 className={styles.subtitle}>{subtitle}</h2> <h2 className={styles.subtitle}>{subtitle}</h2>
+35 -4
View File
@@ -32,16 +32,47 @@ export default {
control: "text", control: "text",
description: "URL for the button link", description: "URL for the button link",
}, },
variant: {
control: { type: "select" },
options: ["centered", "left-aligned", "compact"],
description: "Layout variant for the component",
},
onContactClick: {
action: "contact clicked",
description: "Analytics callback for contact button clicks",
},
}, },
}; };
export const Default = { export const Default = {
args: { args: {
title: "Need help getting started?", title: "Still have questions?",
subtitle: "Our organizers are here to support you", subtitle: "Get answers from an experienced organizer",
description:
"Whether you're forming a new community or improving an existing one, our experienced organizers can provide guidance tailored to your specific needs.",
buttonText: "Ask an organizer", buttonText: "Ask an organizer",
buttonHref: "#contact", buttonHref: "#contact",
variant: "centered",
onContactClick: (data) => console.log("Contact clicked:", data),
},
};
export const LeftAligned = {
args: {
title: "Still have questions?",
subtitle: "Get answers from an experienced organizer",
buttonText: "Ask an organizer",
buttonHref: "#contact",
variant: "left-aligned",
onContactClick: (data) => console.log("Contact clicked:", data),
},
};
export const Compact = {
args: {
title: "Still have questions?",
subtitle: "Get answers from an experienced organizer",
buttonText: "Ask an organizer",
buttonHref: "#contact",
variant: "compact",
onContactClick: (data) => console.log("Contact clicked:", data),
}, },
}; };
+9 -1
View File
@@ -15,7 +15,7 @@ export default {
buttonClassName: { control: { type: "text" } }, buttonClassName: { control: { type: "text" } },
variant: { variant: {
control: { type: "select" }, control: { type: "select" },
options: ["hero", "feature"], options: ["hero", "feature", "ask"],
}, },
linkText: { control: { type: "text" } }, linkText: { control: { type: "text" } },
linkHref: { control: { type: "text" } }, linkHref: { control: { type: "text" } },
@@ -56,3 +56,11 @@ export const FeatureWithLink = {
linkHref: "#", linkHref: "#",
}, },
}; };
export const Ask = {
args: {
title: "Still have questions?",
subtitle: "Get answers from an experienced organizer",
variant: "ask",
},
};