Merge pull request 'adilallo/component/AskOrganizer' (#14) from adilallo/component/AskOrganizer into adilallo/component/FeatureGrid

Reviewed-on: #14
This commit was merged in pull request #14.
This commit is contained in:
2025-08-28 20:29:44 +00:00
7 changed files with 258 additions and 20 deletions
+106
View File
@@ -0,0 +1,106 @@
"use client";
import React from "react";
import ContentLockup from "./ContentLockup";
import Button from "./Button";
const AskOrganizer = ({
title,
subtitle,
description,
buttonText = "Ask an organizer",
buttonHref = "#",
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 (
<section
className={`${sectionPadding} ${className}`}
aria-labelledby="ask-organizer-headline"
role="region"
tabIndex={-1}
>
<div className={`flex flex-col ${contentGap} ${styles.container}`}>
{/* Content Lockup */}
<ContentLockup
title={title}
subtitle={subtitle}
description={description}
variant="ask"
alignment={variant === "left-aligned" ? "left" : "center"}
/>
{/* Button */}
<div className={styles.buttonContainer}>
<Button
href={buttonHref}
size="large"
variant="default"
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}
</Button>
</div>
</div>
</section>
);
};
export default AskOrganizer;
+49 -18
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 = {
@@ -46,35 +47,65 @@ const ContentLockup = ({
shape: shape:
"w-[20px] h-[20px] md:w-[24px] md:h-[24px] lg:w-[28px] lg:h-[28px]", "w-[20px] h-[20px] md:w-[24px] md:h-[24px] lg:w-[28px] lg:h-[28px]",
}, },
ask: {
container: "flex flex-col gap-[var(--spacing-scale-008)] relative z-10",
textContainer: "flex flex-col gap-[var(--spacing-scale-008)]",
titleGroup: "flex flex-col gap-[var(--spacing-scale-008)]",
titleContainer: "flex gap-[var(--spacing-scale-008)] items-center",
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)]",
subtitle:
"font-inter font-normal text-[18px] leading-[130%] tracking-[0] md:text-[24px] md:leading-[32px] text-[var(--color-content-default-primary)]",
shape:
"w-[16px] h-[16px] md:w-[20px] md:h-[20px] lg:w-[24px] lg:h-[24px]",
},
}; };
const styles = variantStyles[variant] || variantStyles.hero; const styles = variantStyles[variant] || variantStyles.hero;
return ( return (
<div className={styles.container}> <div className={styles.container}>
{/* Text content container */} {variant === "ask" ? (
<div className={styles.textContainer}> /* Simplified structure for ask variant */
{/* Title and subtitle group */} <div
<div className={styles.titleGroup}> className={`${styles.titleGroup} ${
{/* Title container */} alignment === "left" ? "text-left" : "text-center"
<div className={styles.titleContainer}> }`}
>
<div
className={`${styles.titleContainer} ${
alignment === "left" ? "justify-start" : "justify-center"
}`}
>
<h1 className={styles.title}>{title}</h1> <h1 className={styles.title}>{title}</h1>
{variant === "hero" && (
<img
src="assets/Shapes_1.svg"
alt="Decorative shapes"
className={styles.shape}
/>
)}
</div> </div>
{/* Subtitle */}
<h2 className={styles.subtitle}>{subtitle}</h2> <h2 className={styles.subtitle}>{subtitle}</h2>
</div> </div>
) : (
/* Full structure for other variants */
<div className={styles.textContainer}>
{/* Title and subtitle group */}
<div className={styles.titleGroup}>
{/* Title container */}
<div className={styles.titleContainer}>
<h1 className={styles.title}>{title}</h1>
{variant === "hero" && (
<img
src="assets/Shapes_1.svg"
alt="Decorative shapes"
className={styles.shape}
/>
)}
</div>
{/* Description */} {/* Subtitle */}
{description && <p className={styles.description}>{description}</p>} <h2 className={styles.subtitle}>{subtitle}</h2>
</div> </div>
{/* Description */}
{description && <p className={styles.description}>{description}</p>}
</div>
)}
{/* Link for feature variant */} {/* Link for feature variant */}
{variant === "feature" && linkText && ( {variant === "feature" && linkText && (
+1
View File
@@ -3,6 +3,7 @@
import React from "react"; import React from "react";
import ContentLockup from "./ContentLockup"; import ContentLockup from "./ContentLockup";
import MiniCard from "./MiniCard"; import MiniCard from "./MiniCard";
import Image from "next/image";
const FeatureGrid = ({ title, subtitle, className = "" }) => { const FeatureGrid = ({ title, subtitle, className = "" }) => {
return ( return (
+6 -1
View File
@@ -1,6 +1,7 @@
"use client"; "use client";
import React from "react"; import React from "react";
import Image from "next/image";
const MiniCard = ({ const MiniCard = ({
children, children,
@@ -23,7 +24,7 @@ const MiniCard = ({
{/* Content for the inner panel */} {/* Content for the inner panel */}
{panelContent && ( {panelContent && (
<div className="flex items-center justify-center w-full h-full"> <div className="flex items-center justify-center w-full h-full">
<img <Image
src={panelContent} src={panelContent}
alt={ alt={
ariaLabel || ariaLabel ||
@@ -32,6 +33,10 @@ const MiniCard = ({
"Feature icon" "Feature icon"
} }
className="max-w-[58px] max-h-[58px] w-auto h-auto object-contain" className="max-w-[58px] max-h-[58px] w-auto h-auto object-contain"
unoptimized
width={0}
height={0}
sizes="100vw"
/> />
</div> </div>
)} )}
+9
View File
@@ -4,6 +4,7 @@ import LogoWall from "./components/LogoWall";
import RuleStack from "./components/RuleStack"; import RuleStack from "./components/RuleStack";
import QuoteBlock from "./components/QuoteBlock"; import QuoteBlock from "./components/QuoteBlock";
import FeatureGrid from "./components/FeatureGrid"; import FeatureGrid from "./components/FeatureGrid";
import AskOrganizer from "./components/AskOrganizer";
export default function Page() { export default function Page() {
const heroBannerData = { const heroBannerData = {
@@ -43,6 +44,13 @@ export default function Page() {
"Use our toolkit to improve, document, and evolve your organization.", "Use our toolkit to improve, document, and evolve your organization.",
}; };
const askOrganizerData = {
title: "Still have questions?",
subtitle: "Get answers from an experienced organizer",
buttonText: "Ask an organizer",
buttonHref: "#contact",
};
return ( return (
<div> <div>
<HeroBanner {...heroBannerData} /> <HeroBanner {...heroBannerData} />
@@ -51,6 +59,7 @@ export default function Page() {
<RuleStack /> <RuleStack />
<FeatureGrid {...featureGridData} /> <FeatureGrid {...featureGridData} />
<QuoteBlock /> <QuoteBlock />
<AskOrganizer {...askOrganizerData} />
</div> </div>
); );
} }
+78
View File
@@ -0,0 +1,78 @@
import AskOrganizer from "../app/components/AskOrganizer";
export default {
title: "Components/AskOrganizer",
component: AskOrganizer,
parameters: {
docs: {
description: {
component:
"The AskOrganizer component provides clear pathways for user inquiries. This component serves as a conversion point throughout the platform.",
},
},
},
argTypes: {
title: {
control: "text",
description: "The main title for the ask organizer section",
},
subtitle: {
control: "text",
description: "The subtitle text",
},
description: {
control: "text",
description: "Additional description text",
},
buttonText: {
control: "text",
description: "Text for the call-to-action button",
},
buttonHref: {
control: "text",
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 = {
args: {
title: "Still have questions?",
subtitle: "Get answers from an experienced organizer",
buttonText: "Ask an organizer",
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",
},
};