Feature Grid #13
@@ -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;
|
||||||
@@ -9,38 +9,116 @@ const ContentLockup = ({
|
|||||||
ctaText,
|
ctaText,
|
||||||
ctaHref,
|
ctaHref,
|
||||||
buttonClassName = "",
|
buttonClassName = "",
|
||||||
|
variant = "hero",
|
||||||
|
linkText,
|
||||||
|
linkHref,
|
||||||
|
alignment = "center", // center, left
|
||||||
}) => {
|
}) => {
|
||||||
|
// Variant-specific styling
|
||||||
|
const variantStyles = {
|
||||||
|
hero: {
|
||||||
|
container:
|
||||||
|
"flex flex-col gap-[var(--spacing-scale-006)] sm:gap-[var(--spacing-scale-012)] md:gap-[var(--spacing-scale-020)] lg:gap-[var(--spacing-scale-020)] relative z-10",
|
||||||
|
textContainer:
|
||||||
|
"flex flex-col md:gap-[var(--spacing-scale-004)] lg:gap-[var(--spacing-scale-008)] xl:gap-[var(--spacing-scale-020)]",
|
||||||
|
titleGroup: "flex flex-col xl:gap-0",
|
||||||
|
titleContainer:
|
||||||
|
"flex gap-[var(--spacing-scale-008)] xl:gap-[var(--spacing-scale-010)] items-center",
|
||||||
|
title:
|
||||||
|
"font-bricolage-grotesque font-medium text-[32px] leading-[32px] sm:text-[52px] sm:leading-[52px] md:text-[44px] md:leading-[44px] lg:text-[64px] lg:leading-[64px] xl:text-[96px] xl:leading-[110%] text-[var(--color-content-inverse-primary)]",
|
||||||
|
subtitle:
|
||||||
|
"font-bricolage-grotesque font-medium text-[32px] leading-[32px] sm:text-[52px] sm:leading-[52px] md:text-[44px] md:leading-[44px] lg:text-[64px] lg:leading-[64px] xl:text-[96px] xl:leading-[110%] text-[var(--color-content-inverse-primary)]",
|
||||||
|
description:
|
||||||
|
"font-inter font-normal text-[18px] leading-[130%] lg:text-[24px] lg:leading-[32px] xl:text-[32px] xl:leading-[40px] text-[var(--color-content-inverse-primary)]",
|
||||||
|
shape:
|
||||||
|
"w-[27.2px] h-[27.2px] md:w-[34px] md:h-[34px] lg:w-[50px] lg:h-[50px]",
|
||||||
|
},
|
||||||
|
feature: {
|
||||||
|
container: "flex flex-col gap-[var(--spacing-scale-012)] relative z-10",
|
||||||
|
textContainer: "flex flex-col gap-[var(--spacing-scale-012)]",
|
||||||
|
titleGroup: "flex flex-col gap-[var(--spacing-scale-012)]",
|
||||||
|
titleContainer: "flex gap-[var(--spacing-scale-008)] items-center",
|
||||||
|
title:
|
||||||
|
"font-bricolage-grotesque font-medium text-[32px] leading-[130%] tracking-[0] text-[var(--color-content-default-primary)]",
|
||||||
|
subtitle:
|
||||||
|
"font-space-grotesk font-normal text-[20px] leading-[130%] tracking-[0] text-[var(--color-content-default-primary)]",
|
||||||
|
description:
|
||||||
|
"font-inter font-normal text-[16px] leading-[140%] lg:text-[18px] lg:leading-[150%] xl:text-[20px] xl:leading-[160%] text-[var(--color-content-secondary)]",
|
||||||
|
shape:
|
||||||
|
"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;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-[var(--spacing-scale-006)] sm:gap-[var(--spacing-scale-012)] md:gap-[var(--spacing-scale-020)] lg:gap-[var(--spacing-scale-020)] relative z-10">
|
<div className={styles.container}>
|
||||||
{/* Text content container */}
|
{variant === "ask" ? (
|
||||||
<div className="flex flex-col md:gap-[var(--spacing-scale-004)] lg:gap-[var(--spacing-scale-008)] xl:gap-[var(--spacing-scale-020)]">
|
/* Simplified structure for ask variant */
|
||||||
{/* Title and subtitle group - no gap between them at xl */}
|
<div
|
||||||
<div className="flex flex-col xl:gap-0">
|
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>
|
||||||
|
</div>
|
||||||
|
<h2 className={styles.subtitle}>{subtitle}</h2>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
/* Full structure for other variants */
|
||||||
|
<div className={styles.textContainer}>
|
||||||
|
{/* Title and subtitle group */}
|
||||||
|
<div className={styles.titleGroup}>
|
||||||
{/* Title container */}
|
{/* Title container */}
|
||||||
<div className="flex gap-[var(--spacing-scale-008)] xl:gap-[var(--spacing-scale-010)] items-center">
|
<div className={styles.titleContainer}>
|
||||||
<h1 className="font-bricolage-grotesque font-medium text-[32px] leading-[32px] sm:text-[52px] sm:leading-[52px] md:text-[44px] md:leading-[44px] lg:text-[64px] lg:leading-[64px] xl:text-[96px] xl:leading-[110%] text-[var(--color-content-inverse-primary)]">
|
<h1 className={styles.title}>{title}</h1>
|
||||||
{title}
|
{variant === "hero" && (
|
||||||
</h1>
|
|
||||||
<img
|
<img
|
||||||
src="assets/Shapes_1.svg"
|
src="assets/Shapes_1.svg"
|
||||||
alt="Decorative shapes"
|
alt="Decorative shapes"
|
||||||
className="w-[27.2px] h-[27.2px] md:w-[34px] md:h-[34px] lg:w-[50px] lg:h-[50px]"
|
className={styles.shape}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Subtitle */}
|
{/* Subtitle */}
|
||||||
<h2 className="font-bricolage-grotesque font-medium text-[32px] leading-[32px] sm:text-[52px] sm:leading-[52px] md:text-[44px] md:leading-[44px] lg:text-[64px] lg:leading-[64px] xl:text-[96px] xl:leading-[110%] text-[var(--color-content-inverse-primary)]">
|
<h2 className={styles.subtitle}>{subtitle}</h2>
|
||||||
{subtitle}
|
|
||||||
</h2>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Description - 20px gap from subtitle at xl */}
|
{/* Description */}
|
||||||
<p className="font-inter font-normal text-[18px] leading-[130%] lg:text-[24px] lg:leading-[32px] xl:text-[32px] xl:leading-[40px] text-[var(--color-content-inverse-primary)]">
|
{description && <p className={styles.description}>{description}</p>}
|
||||||
{description}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Link for feature variant */}
|
||||||
|
{variant === "feature" && linkText && (
|
||||||
|
<a
|
||||||
|
href={linkHref || "#"}
|
||||||
|
className="font-inter font-medium text-[16px] leading-[20px] underline text-[var(--color-content-default-primary)] hover:text-gray-300 transition-colors focus:outline-none focus:ring-2 focus:ring-[var(--color-surface-default-brand-royal)] focus:ring-offset-2 focus:ring-offset-[#171717] rounded-sm px-1 py-0.5"
|
||||||
|
>
|
||||||
|
{linkText}
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* CTA Button */}
|
{/* CTA Button */}
|
||||||
|
{ctaText && (
|
||||||
<div className="flex justify-start">
|
<div className="flex justify-start">
|
||||||
{/* Small button for xsm and sm breakpoints */}
|
{/* Small button for xsm and sm breakpoints */}
|
||||||
<div className="block md:hidden">
|
<div className="block md:hidden">
|
||||||
@@ -61,6 +139,7 @@ const ContentLockup = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import ContentLockup from "./ContentLockup";
|
||||||
|
import MiniCard from "./MiniCard";
|
||||||
|
import Image from "next/image";
|
||||||
|
|
||||||
|
const FeatureGrid = ({ title, subtitle, className = "" }) => {
|
||||||
|
return (
|
||||||
|
<section
|
||||||
|
className={`p-0 lg:p-[var(--spacing-scale-064)] ${className}`}
|
||||||
|
aria-labelledby="feature-grid-headline"
|
||||||
|
role="region"
|
||||||
|
tabIndex={-1}
|
||||||
|
>
|
||||||
|
<div className="py-[var(--spacing-scale-032)] px-[var(--spacing-scale-020)] md:pt-[var(--spacing-scale-076)] md:pb-[var(--spacing-scale-048)] lg:pb-[var(--spacing-scale-076)] md:px-[var(--spacing-scale-048)] bg-[#171717] rounded-[var(--radius-measures-radius-xlarge)] focus-within:ring-2 focus-within:ring-[var(--color-surface-default-brand-royal)] focus-within:ring-offset-2">
|
||||||
|
<div className="w-full mx-auto gap-[var(--spacing-scale-048)] lg:flex lg:items-start lg:gap-[var(--spacing-scale-048)] [container-type:inline-size]">
|
||||||
|
{/* Feature Content Lockup */}
|
||||||
|
<div className="lg:shrink lg:min-w-0">
|
||||||
|
<ContentLockup
|
||||||
|
title={title}
|
||||||
|
subtitle={subtitle}
|
||||||
|
variant="feature"
|
||||||
|
linkText="Learn more"
|
||||||
|
linkHref="#"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* MiniCard Grid */}
|
||||||
|
<div
|
||||||
|
className="grid grid-cols-2 md:grid-cols-4 gap-[var(--spacing-scale-012)] mt-[var(--spacing-scale-048)] lg:mt-0 lg:flex-grow lg:shrink-0"
|
||||||
|
role="grid"
|
||||||
|
aria-label="Feature tools and services"
|
||||||
|
>
|
||||||
|
<MiniCard
|
||||||
|
backgroundColor="bg-[var(--color-surface-default-brand-royal)]"
|
||||||
|
labelLine1="Decision-making"
|
||||||
|
labelLine2="support"
|
||||||
|
panelContent="assets/Feature_Support.png"
|
||||||
|
ariaLabel="Decision-making support tools"
|
||||||
|
href="#decision-making"
|
||||||
|
/>
|
||||||
|
<MiniCard
|
||||||
|
backgroundColor="bg-[#D1FFE2]"
|
||||||
|
labelLine1="Values alignment"
|
||||||
|
labelLine2="exercises"
|
||||||
|
panelContent="assets/Feature_Exercises.png"
|
||||||
|
ariaLabel="Values alignment exercises"
|
||||||
|
href="#values-alignment"
|
||||||
|
/>
|
||||||
|
<MiniCard
|
||||||
|
backgroundColor="bg-[#F4CAFF]"
|
||||||
|
labelLine1="Membership"
|
||||||
|
labelLine2="guidance"
|
||||||
|
panelContent="assets/Feature_Guidance.png"
|
||||||
|
ariaLabel="Membership guidance resources"
|
||||||
|
href="#membership-guidance"
|
||||||
|
/>
|
||||||
|
<MiniCard
|
||||||
|
backgroundColor="bg-[#CBDDFF]"
|
||||||
|
labelLine1="Conflict resolution"
|
||||||
|
labelLine2="tools"
|
||||||
|
panelContent="assets/Feature_Tools.png"
|
||||||
|
ariaLabel="Conflict resolution tools"
|
||||||
|
href="#conflict-resolution"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FeatureGrid;
|
||||||
@@ -23,9 +23,9 @@ const HeroDecor = ({ className = "" }) => {
|
|||||||
{/* 1) make noise */}
|
{/* 1) make noise */}
|
||||||
<feTurbulence
|
<feTurbulence
|
||||||
type="fractalNoise"
|
type="fractalNoise"
|
||||||
baseFrequency="0.8"
|
baseFrequency="0.4"
|
||||||
numOctaves="2"
|
numOctaves="3"
|
||||||
seed="3"
|
seed="7"
|
||||||
stitchTiles="stitch"
|
stitchTiles="stitch"
|
||||||
result="noise"
|
result="noise"
|
||||||
/>
|
/>
|
||||||
@@ -35,10 +35,10 @@ const HeroDecor = ({ className = "" }) => {
|
|||||||
result="softNoise"
|
result="softNoise"
|
||||||
type="matrix"
|
type="matrix"
|
||||||
values="
|
values="
|
||||||
0 0 0 0 0
|
0.8 0 0 0 0.3
|
||||||
0 0 0 0 0
|
0 0.6 0 0 0.2
|
||||||
0 0 0 0 0
|
0 0 1.0 0 0.4
|
||||||
0 0 0 0.15 0"
|
0 0 0 0.25 0"
|
||||||
/>
|
/>
|
||||||
{/* 3) MASK noise to the element's alpha only */}
|
{/* 3) MASK noise to the element's alpha only */}
|
||||||
<feComposite
|
<feComposite
|
||||||
|
|||||||
@@ -0,0 +1,112 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import Image from "next/image";
|
||||||
|
|
||||||
|
const MiniCard = ({
|
||||||
|
children,
|
||||||
|
className = "",
|
||||||
|
backgroundColor = "bg-[var(--color-surface-default-brand-royal)]",
|
||||||
|
panelContent,
|
||||||
|
label,
|
||||||
|
labelLine1,
|
||||||
|
labelLine2,
|
||||||
|
onClick,
|
||||||
|
href,
|
||||||
|
ariaLabel,
|
||||||
|
}) => {
|
||||||
|
const cardContent = (
|
||||||
|
<div className={`h-[186px] flex flex-col gap-[7px] ${className}`}>
|
||||||
|
{/* Top part - Inner panel */}
|
||||||
|
<div
|
||||||
|
className={`flex-1 rounded-[var(--radius-measures-radius-xlarge)] border border-[1px] py-[var(--spacing-scale-032)] px-[var(--spacing-scale-024)] ${backgroundColor} flex items-center justify-center transition-all duration-200 hover:scale-[1.02] hover:shadow-lg`}
|
||||||
|
>
|
||||||
|
{/* Content for the inner panel */}
|
||||||
|
{panelContent && (
|
||||||
|
<div className="flex items-center justify-center w-full h-full">
|
||||||
|
<Image
|
||||||
|
src={panelContent}
|
||||||
|
alt={
|
||||||
|
ariaLabel ||
|
||||||
|
`${labelLine1} ${labelLine2}` ||
|
||||||
|
label ||
|
||||||
|
"Feature icon"
|
||||||
|
}
|
||||||
|
className="max-w-[58px] max-h-[58px] w-auto h-auto object-contain"
|
||||||
|
unoptimized
|
||||||
|
width={0}
|
||||||
|
height={0}
|
||||||
|
sizes="100vw"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Bottom part - Text container */}
|
||||||
|
<div className="font-inter font-medium text-[12px] leading-[14px] text-center text-[var(--color-content-default-primary)]">
|
||||||
|
{labelLine1 && labelLine2 ? (
|
||||||
|
<>
|
||||||
|
<div>{labelLine1}</div>
|
||||||
|
<div>{labelLine2}</div>
|
||||||
|
<div> </div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
label
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
// If href is provided, render as a link
|
||||||
|
if (href) {
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
href={href}
|
||||||
|
className="block focus:outline-none focus:ring-2 focus:ring-[var(--color-surface-default-brand-royal)] focus:ring-offset-2 rounded-[var(--radius-measures-radius-xlarge)] transition-all duration-200 hover:scale-[1.02]"
|
||||||
|
aria-label={
|
||||||
|
ariaLabel || `${labelLine1} ${labelLine2}` || label || "Feature card"
|
||||||
|
}
|
||||||
|
tabIndex={0}
|
||||||
|
>
|
||||||
|
{cardContent}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If onClick is provided, render as a button
|
||||||
|
if (onClick) {
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
onClick={onClick}
|
||||||
|
className="block w-full text-left focus:outline-none focus:ring-2 focus:ring-[var(--color-surface-default-brand-royal)] focus:ring-offset-2 rounded-[var(--radius-measures-radius-xlarge)] transition-all duration-200 hover:scale-[1.02]"
|
||||||
|
aria-label={
|
||||||
|
ariaLabel || `${labelLine1} ${labelLine2}` || label || "Feature card"
|
||||||
|
}
|
||||||
|
tabIndex={0}
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
if (e.key === "Enter" || e.key === " ") {
|
||||||
|
e.preventDefault();
|
||||||
|
onClick();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{cardContent}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default render as a div
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="block"
|
||||||
|
aria-label={
|
||||||
|
ariaLabel || `${labelLine1} ${labelLine2}` || label || "Feature card"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{cardContent}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MiniCard;
|
||||||
@@ -126,6 +126,15 @@ const QuoteBlock = ({
|
|||||||
<div
|
<div
|
||||||
className={`${config.card} bg-[var(--color-surface-default-brand-darker-accent)] relative overflow-hidden`}
|
className={`${config.card} bg-[var(--color-surface-default-brand-darker-accent)] relative overflow-hidden`}
|
||||||
>
|
>
|
||||||
|
{/* Background with noise texture */}
|
||||||
|
<div
|
||||||
|
className="absolute inset-0 bg-[var(--color-surface-default-brand-darker-accent)]"
|
||||||
|
style={{
|
||||||
|
filter:
|
||||||
|
'url(\'data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg"><defs><filter id="grain" filterUnits="objectBoundingBox" x="0" y="0" width="1" height="1" colorInterpolationFilters="sRGB"><feTurbulence type="fractalNoise" baseFrequency="0.4" numOctaves="3" seed="7" stitchTiles="stitch" result="noise"/><feColorMatrix in="noise" result="softNoise" type="matrix" values="0.8 0 0 0 0.3 0 0.6 0 0 0.2 0 0 1.0 0 0.4 0 0 0 0.25 0"/><feComposite in="softNoise" in2="SourceAlpha" operator="in" result="maskedNoise"/><feBlend in="SourceGraphic" in2="maskedNoise" mode="multiply"/></filter></defs></svg>#grain\')',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
{/* DECORATIONS (behind content) */}
|
{/* DECORATIONS (behind content) */}
|
||||||
{config.showDecor && (
|
{config.showDecor && (
|
||||||
<QuoteDecor
|
<QuoteDecor
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import HeroBanner from "./components/HeroBanner";
|
|||||||
import LogoWall from "./components/LogoWall";
|
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 AskOrganizer from "./components/AskOrganizer";
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
const heroBannerData = {
|
const heroBannerData = {
|
||||||
@@ -36,13 +38,28 @@ export default function Page() {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const featureGridData = {
|
||||||
|
title: "We've got your back, every step of the way",
|
||||||
|
subtitle:
|
||||||
|
"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} />
|
||||||
<LogoWall />
|
<LogoWall />
|
||||||
<NumberedCards {...numberedCardsData} />
|
<NumberedCards {...numberedCardsData} />
|
||||||
<RuleStack />
|
<RuleStack />
|
||||||
|
<FeatureGrid {...featureGridData} />
|
||||||
<QuoteBlock />
|
<QuoteBlock />
|
||||||
|
<AskOrganizer {...askOrganizerData} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 25 KiB |
@@ -0,0 +1,57 @@
|
|||||||
|
<svg width="47" height="46" viewBox="0 0 47 46" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<defs>
|
||||||
|
<filter
|
||||||
|
id="grain"
|
||||||
|
filterUnits="objectBoundingBox"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="1"
|
||||||
|
height="1"
|
||||||
|
colorInterpolationFilters="sRGB"
|
||||||
|
>
|
||||||
|
<feTurbulence
|
||||||
|
type="fractalNoise"
|
||||||
|
baseFrequency="0.8"
|
||||||
|
numOctaves="2"
|
||||||
|
seed="3"
|
||||||
|
stitchTiles="stitch"
|
||||||
|
result="noise1"
|
||||||
|
/>
|
||||||
|
<feTurbulence
|
||||||
|
type="fractalNoise"
|
||||||
|
baseFrequency="1.2"
|
||||||
|
numOctaves="1"
|
||||||
|
seed="7"
|
||||||
|
stitchTiles="stitch"
|
||||||
|
result="noise2"
|
||||||
|
/>
|
||||||
|
<feBlend in="noise1" in2="noise2" mode="multiply" result="combinedNoise" />
|
||||||
|
<feColorMatrix
|
||||||
|
in="combinedNoise"
|
||||||
|
result="coloredNoise"
|
||||||
|
type="matrix"
|
||||||
|
values="
|
||||||
|
0.8 0 0 0 0.3
|
||||||
|
0 0.6 0 0 0.2
|
||||||
|
0 0 1.0 0 0.4
|
||||||
|
0 0 0 0.8 0"
|
||||||
|
/>
|
||||||
|
<feComposite
|
||||||
|
in="coloredNoise"
|
||||||
|
in2="SourceAlpha"
|
||||||
|
operator="in"
|
||||||
|
result="maskedNoise"
|
||||||
|
/>
|
||||||
|
<feBlend in="SourceGraphic" in2="maskedNoise" mode="multiply" />
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<g filter="url(#grain)" fill="#787DFF">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.75 0C15.6109 0 16.3751 0.55086 16.6474 1.36754L19.3311 9.41886L27.3825 12.1026C28.1991 12.3749 28.75 13.1391 28.75 14C28.75 14.8609 28.1991 15.6251 27.3825 15.8974L19.3311 18.5811L16.6474 26.6325C16.3751 27.4491 15.6109 28 14.75 28C13.8891 28 13.1249 27.4491 12.8526 26.6325L10.1689 18.5811L2.11754 15.8974C1.30086 15.6251 0.75 14.8609 0.75 14C0.75 13.1391 1.30086 12.3749 2.11754 12.1026L10.1689 9.41886L12.8526 1.36754C13.1249 0.55086 13.8891 0 14.75 0ZM14.75 8.32456L13.6474 11.6325C13.4483 12.2297 12.9797 12.6983 12.3825 12.8974L9.07456 14L12.3825 15.1026C12.9797 15.3017 13.4483 15.7703 13.6474 16.3675L14.75 19.6754L15.8526 16.3675C16.0517 15.7703 16.5203 15.3017 17.1175 15.1026L20.4254 14L17.1175 12.8974C16.5203 12.6983 16.0517 12.2297 15.8526 11.6325L14.75 8.32456Z"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.75 0C15.6109 0 16.3751 0.55086 16.6474 1.36754L19.3311 9.41886L27.3825 12.1026C28.1991 12.3749 28.75 13.1391 28.75 14C28.75 14.8609 28.1991 15.6251 27.3825 15.8974L19.3311 18.5811L16.6474 26.6325C16.3751 27.4491 15.6109 28 14.75 28C13.8891 28 13.1249 27.4491 12.8526 26.6325L10.1689 18.5811L2.11754 15.8974C1.30086 15.6251 0.75 14.8609 0.75 14C0.75 13.1391 1.30086 12.3749 2.11754 12.1026L10.1689 9.41886L12.8526 1.36754C13.1249 0.55086 13.8891 0 14.75 0ZM14.75 8.32456L13.6474 11.6325C13.4483 12.2297 12.9797 12.6983 12.3825 12.8974L9.07456 14L12.3825 15.1026C12.9797 15.3017 13.4483 15.7703 13.6474 16.3675L14.75 19.6754L15.8526 16.3675C16.0517 15.7703 16.5203 15.3017 17.1175 15.1026L20.4254 14L17.1175 12.8974C16.5203 12.6983 16.0517 12.2297 15.8526 11.6325L14.75 8.32456Z"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M40.3358 13.5858C41.6691 12.2525 43.8309 12.2525 45.1642 13.5858C46.4975 14.9191 46.4975 17.0809 45.1642 18.4142L31.1642 32.4142C29.8309 33.7476 27.6691 33.7475 26.3358 32.4142C25.0025 31.0809 25.0025 28.9191 26.3358 27.5858L40.3358 13.5858Z"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M40.3358 13.5858C41.6691 12.2525 43.8309 12.2525 45.1642 13.5858C46.4975 14.9191 46.4975 17.0809 45.1642 18.4142L31.1642 32.4142C29.8309 33.7476 27.6691 33.7475 26.3358 32.4142C25.0025 31.0809 25.0025 28.9191 26.3358 27.5858L40.3358 13.5858Z"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.1901 41.5878C16.2564 42.0159 17.375 42.0924 18.4949 41.6362C19.8562 41.0817 20.3319 40.1783 20.4519 39.1811C20.5194 38.6201 20.4602 38.043 20.3153 37.5535C20.1693 37.06 19.9944 36.8418 19.9796 36.8234C19.5488 36.3895 19.2668 36.2284 19.0871 36.1528C18.9117 36.079 18.6307 36 18.0832 36C17.9448 36 17.6913 36.0219 17.3727 36.0946C17.0821 36.1608 16.8122 36.2523 16.5957 36.351C16.582 36.4548 16.5684 36.5592 16.5544 36.6678C16.5251 36.8943 16.4934 37.1385 16.4526 37.4303C16.3636 38.0671 16.2374 38.862 16.0013 39.6665C15.8122 40.3107 15.5511 40.9617 15.1901 41.5878ZM12.1566 44.5152C14.2352 45.7779 16.9714 46.5759 20.0039 45.3406C25.75 43 25.1049 36.3084 22.8174 34.0041C21.3978 32.5741 20.0039 32.0001 18.0833 32C16.1627 31.9999 13.0609 33.0512 12.75 35C12.6824 35.4235 12.6287 35.8361 12.5767 36.2352C12.3073 38.3037 12.0848 40.0115 10.2304 41.0095C9.58315 41.3578 9.29891 42.2089 9.83028 42.7167C10.4451 43.3043 11.2105 43.9332 12.0977 44.4792C12.1172 44.4912 12.137 44.5033 12.1566 44.5152Z"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.1901 41.5878C16.2564 42.0159 17.375 42.0924 18.4949 41.6362C19.8562 41.0817 20.3319 40.1783 20.4519 39.1811C20.5194 38.6201 20.4602 38.043 20.3153 37.5535C20.1693 37.06 19.9944 36.8418 19.9796 36.8234C19.5488 36.3895 19.2668 36.2284 19.0871 36.1528C18.9117 36.079 18.6307 36 18.0832 36C17.9448 36 17.6913 36.0219 17.3727 36.0946C17.0821 36.1608 16.8122 36.2523 16.5957 36.351C16.582 36.4548 16.5684 36.5592 16.5544 36.6678C16.5251 36.8943 16.4934 37.1385 16.4526 37.4303C16.3636 38.0671 16.2374 38.862 16.0013 39.6665C15.8122 40.3107 15.5511 40.9617 15.1901 41.5878ZM12.1566 44.5152C14.2352 45.7779 16.9714 46.5759 20.0039 45.3406C25.75 43 25.1049 36.3084 22.8174 34.0041C21.3978 32.5741 20.0039 32.0001 18.0833 32C16.1627 31.9999 13.0609 33.0512 12.75 35C12.6824 35.4235 12.6287 35.8361 12.5767 36.2352C12.3073 38.3037 12.0848 40.0115 10.2304 41.0095C9.58315 41.3578 9.29891 42.2089 9.83028 42.7167C10.4451 43.3043 11.2105 43.9332 12.0977 44.4792C12.1172 44.4912 12.137 44.5033 12.1566 44.5152Z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 42 KiB |
@@ -1 +0,0 @@
|
|||||||
<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 391 B |
@@ -1 +0,0 @@
|
|||||||
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.0 KiB |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -1 +0,0 @@
|
|||||||
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 128 B |
@@ -1 +0,0 @@
|
|||||||
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 385 B |
@@ -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),
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -5,44 +5,24 @@ export default {
|
|||||||
component: ContentLockup,
|
component: ContentLockup,
|
||||||
parameters: {
|
parameters: {
|
||||||
layout: "centered",
|
layout: "centered",
|
||||||
docs: {
|
|
||||||
description: {
|
|
||||||
component:
|
|
||||||
"A content lockup component that groups title, subtitle, description, and CTA button. Features responsive typography and spacing that adapts across breakpoints. Used within the HeroBanner component.",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
argTypes: {
|
argTypes: {
|
||||||
title: {
|
title: { control: { type: "text" } },
|
||||||
control: { type: "text" },
|
subtitle: { control: { type: "text" } },
|
||||||
description: "The main title text",
|
description: { control: { type: "text" } },
|
||||||
|
ctaText: { control: { type: "text" } },
|
||||||
|
ctaHref: { control: { type: "text" } },
|
||||||
|
buttonClassName: { control: { type: "text" } },
|
||||||
|
variant: {
|
||||||
|
control: { type: "select" },
|
||||||
|
options: ["hero", "feature", "ask"],
|
||||||
},
|
},
|
||||||
subtitle: {
|
linkText: { control: { type: "text" } },
|
||||||
control: { type: "text" },
|
linkHref: { control: { type: "text" } },
|
||||||
description: "The subtitle text",
|
|
||||||
},
|
},
|
||||||
description: {
|
|
||||||
control: { type: "text" },
|
|
||||||
description: "The description text",
|
|
||||||
},
|
|
||||||
ctaText: {
|
|
||||||
control: { type: "text" },
|
|
||||||
description: "The call-to-action button text",
|
|
||||||
},
|
|
||||||
ctaHref: {
|
|
||||||
control: { type: "text" },
|
|
||||||
description: "The call-to-action button link",
|
|
||||||
},
|
|
||||||
buttonClassName: {
|
|
||||||
control: { type: "text" },
|
|
||||||
description:
|
|
||||||
"Additional CSS classes to apply to the large button (md/lg breakpoints)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
tags: ["autodocs"],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Default = {
|
export const Hero = {
|
||||||
args: {
|
args: {
|
||||||
title: "Collaborate",
|
title: "Collaborate",
|
||||||
subtitle: "with clarity",
|
subtitle: "with clarity",
|
||||||
@@ -50,68 +30,37 @@ export const Default = {
|
|||||||
"Help your community make important decisions in a way that reflects its unique values.",
|
"Help your community make important decisions in a way that reflects its unique values.",
|
||||||
ctaText: "Learn how Community Rule works",
|
ctaText: "Learn how Community Rule works",
|
||||||
ctaHref: "#",
|
ctaHref: "#",
|
||||||
},
|
variant: "hero",
|
||||||
parameters: {
|
|
||||||
docs: {
|
|
||||||
description: {
|
|
||||||
story: "Default content lockup with standard Community Rule messaging.",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const LongDescription = {
|
export const Feature = {
|
||||||
args: {
|
args: {
|
||||||
title: "Collaborate",
|
title: "Build",
|
||||||
subtitle: "with clarity",
|
subtitle: "consensus",
|
||||||
description:
|
description:
|
||||||
"Help your community make important decisions in a way that reflects its unique values. Our platform provides the tools and frameworks needed to build successful, sustainable communities that can navigate complex challenges together.",
|
"Create structured decision-making processes that help your community reach agreement on important matters.",
|
||||||
ctaText: "Learn how Community Rule works",
|
ctaText: "Explore consensus methods",
|
||||||
ctaHref: "#",
|
ctaHref: "#",
|
||||||
},
|
variant: "feature",
|
||||||
parameters: {
|
|
||||||
docs: {
|
|
||||||
description: {
|
|
||||||
story:
|
|
||||||
"Content lockup with longer description text to test text wrapping.",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ShortContent = {
|
export const FeatureWithLink = {
|
||||||
args: {
|
args: {
|
||||||
title: "Simple",
|
title: "We've got your back, every step of the way",
|
||||||
subtitle: "solution",
|
subtitle:
|
||||||
description: "Easy community decision making.",
|
"Use our toolkit to improve, document, and evolve your organization.",
|
||||||
ctaText: "Try it",
|
variant: "feature",
|
||||||
ctaHref: "#",
|
linkText: "Learn more",
|
||||||
},
|
linkHref: "#",
|
||||||
parameters: {
|
|
||||||
docs: {
|
|
||||||
description: {
|
|
||||||
story: "Content lockup with minimal content to test compact layouts.",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CustomButtonStyling = {
|
export const Ask = {
|
||||||
args: {
|
args: {
|
||||||
title: "Collaborate",
|
title: "Still have questions?",
|
||||||
subtitle: "with clarity",
|
subtitle: "Get answers from an experienced organizer",
|
||||||
description:
|
variant: "ask",
|
||||||
"Help your community make important decisions in a way that reflects its unique values.",
|
|
||||||
ctaText: "Learn how Community Rule works",
|
|
||||||
ctaHref: "#",
|
|
||||||
buttonClassName: "shrink-0 whitespace-nowrap min-w-[280px]",
|
|
||||||
},
|
|
||||||
parameters: {
|
|
||||||
docs: {
|
|
||||||
description: {
|
|
||||||
story:
|
|
||||||
"Content lockup with custom button styling applied to the large button (md/lg breakpoints).",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
import FeatureGrid from "../app/components/FeatureGrid";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: "Components/FeatureGrid",
|
||||||
|
component: FeatureGrid,
|
||||||
|
parameters: {
|
||||||
|
layout: "fullscreen",
|
||||||
|
docs: {
|
||||||
|
description: {
|
||||||
|
component: `
|
||||||
|
A responsive feature grid component that displays organizational tools and services in a clean card-based layout with supportive messaging and categorized feature highlights.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Responsive Layout**: Adapts from 2x2 grid on mobile to 1x4 grid on tablet to horizontal layout on desktop
|
||||||
|
- **ContentLockup Integration**: Uses the feature variant with "Learn more" link
|
||||||
|
- **MiniCard Grid**: Four feature cards with color-coded backgrounds and icons
|
||||||
|
- **Accessibility**: Full keyboard navigation, focus indicators, and ARIA labels
|
||||||
|
- **Design System**: Uses design tokens for consistent spacing, colors, and typography
|
||||||
|
|
||||||
|
## Responsive Behavior
|
||||||
|
|
||||||
|
- **Mobile (< 768px)**: 2x2 grid layout with ContentLockup on top
|
||||||
|
- **Tablet (768px - 1024px)**: 1x4 grid layout with ContentLockup on top
|
||||||
|
- **Desktop (> 1024px)**: Horizontal layout with ContentLockup on left, 1x4 grid on right
|
||||||
|
|
||||||
|
## Interactive Elements
|
||||||
|
|
||||||
|
- **MiniCards**: Hover effects, focus indicators, and keyboard navigation
|
||||||
|
- **Learn More Link**: Underlined link with focus states
|
||||||
|
- **Color-coded Features**: Royal, green, pink, and blue backgrounds for categorization
|
||||||
|
|
||||||
|
## Accessibility
|
||||||
|
|
||||||
|
- WCAG 2.1 AA compliant
|
||||||
|
- Keyboard navigation support
|
||||||
|
- Screen reader friendly with proper ARIA labels
|
||||||
|
- Focus management with visible indicators
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
argTypes: {
|
||||||
|
title: {
|
||||||
|
control: { type: "text" },
|
||||||
|
description: "Main headline text for the ContentLockup",
|
||||||
|
},
|
||||||
|
subtitle: {
|
||||||
|
control: { type: "text" },
|
||||||
|
description: "Supporting subtitle text for the ContentLockup",
|
||||||
|
},
|
||||||
|
className: {
|
||||||
|
control: { type: "text" },
|
||||||
|
description: "Additional CSS classes for custom styling",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Default = {
|
||||||
|
args: {
|
||||||
|
title: "We've got your back, every step of the way",
|
||||||
|
subtitle:
|
||||||
|
"Use our toolkit to improve, document, and evolve your organization.",
|
||||||
|
},
|
||||||
|
parameters: {
|
||||||
|
docs: {
|
||||||
|
description: {
|
||||||
|
story: `
|
||||||
|
Default FeatureGrid with standard content. This component demonstrates:
|
||||||
|
|
||||||
|
- **ContentLockup**: Feature variant with title, subtitle, and "Learn more" link
|
||||||
|
- **MiniCard Grid**: Four feature cards with different colors and icons
|
||||||
|
- **Responsive Design**: Layout adapts across mobile, tablet, and desktop breakpoints
|
||||||
|
- **Interactive States**: Hover effects and focus indicators on all interactive elements
|
||||||
|
|
||||||
|
The component uses a dark background (#171717) with rounded corners and proper spacing using design tokens.
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import MiniCard from "../app/components/MiniCard";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: "Components/MiniCard",
|
||||||
|
component: MiniCard,
|
||||||
|
parameters: {
|
||||||
|
layout: "centered",
|
||||||
|
},
|
||||||
|
argTypes: {
|
||||||
|
backgroundColor: {
|
||||||
|
control: "select",
|
||||||
|
options: [
|
||||||
|
"bg-[var(--color-surface-default-brand-royal)]",
|
||||||
|
"bg-[#D1FFE2]",
|
||||||
|
"bg-[#F4CAFF]",
|
||||||
|
"bg-[#CBDDFF]",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
labelLine1: { control: "text" },
|
||||||
|
labelLine2: { control: "text" },
|
||||||
|
panelContent: { control: "text" },
|
||||||
|
href: { control: "text" },
|
||||||
|
onClick: { action: "clicked" },
|
||||||
|
ariaLabel: { control: "text" },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Default = {
|
||||||
|
args: {
|
||||||
|
backgroundColor: "bg-[var(--color-surface-default-brand-royal)]",
|
||||||
|
labelLine1: "Decision-making",
|
||||||
|
labelLine2: "support",
|
||||||
|
panelContent: "assets/Feature_Support.png",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ColorVariants = {
|
||||||
|
render: () => (
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<MiniCard
|
||||||
|
backgroundColor="bg-[var(--color-surface-default-brand-royal)]"
|
||||||
|
labelLine1="Decision-making"
|
||||||
|
labelLine2="support"
|
||||||
|
panelContent="assets/Feature_Support.png"
|
||||||
|
/>
|
||||||
|
<MiniCard
|
||||||
|
backgroundColor="bg-[#D1FFE2]"
|
||||||
|
labelLine1="Values alignment"
|
||||||
|
labelLine2="exercises"
|
||||||
|
panelContent="assets/Feature_Exercises.png"
|
||||||
|
/>
|
||||||
|
<MiniCard
|
||||||
|
backgroundColor="bg-[#F4CAFF]"
|
||||||
|
labelLine1="Membership"
|
||||||
|
labelLine2="guidance"
|
||||||
|
panelContent="assets/Feature_Guidance.png"
|
||||||
|
/>
|
||||||
|
<MiniCard
|
||||||
|
backgroundColor="bg-[#CBDDFF]"
|
||||||
|
labelLine1="Conflict resolution"
|
||||||
|
labelLine2="tools"
|
||||||
|
panelContent="assets/Feature_Tools.png"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const AsLink = {
|
||||||
|
args: {
|
||||||
|
backgroundColor: "bg-[var(--color-surface-default-brand-royal)]",
|
||||||
|
labelLine1: "Decision-making",
|
||||||
|
labelLine2: "support",
|
||||||
|
panelContent: "assets/Feature_Support.png",
|
||||||
|
href: "#decision-making",
|
||||||
|
ariaLabel: "Navigate to decision-making support tools",
|
||||||
|
},
|
||||||
|
};
|
||||||