Feature Grid #13
@@ -9,58 +9,104 @@ const ContentLockup = ({
|
||||
ctaText,
|
||||
ctaHref,
|
||||
buttonClassName = "",
|
||||
variant = "hero",
|
||||
linkText,
|
||||
linkHref,
|
||||
}) => {
|
||||
// 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]",
|
||||
},
|
||||
};
|
||||
|
||||
const styles = variantStyles[variant] || variantStyles.hero;
|
||||
|
||||
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 */}
|
||||
<div className="flex flex-col md:gap-[var(--spacing-scale-004)] lg:gap-[var(--spacing-scale-008)] xl:gap-[var(--spacing-scale-020)]">
|
||||
{/* Title and subtitle group - no gap between them at xl */}
|
||||
<div className="flex flex-col xl:gap-0">
|
||||
<div className={styles.textContainer}>
|
||||
{/* Title and subtitle group */}
|
||||
<div className={styles.titleGroup}>
|
||||
{/* Title container */}
|
||||
<div className="flex gap-[var(--spacing-scale-008)] xl:gap-[var(--spacing-scale-010)] items-center">
|
||||
<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)]">
|
||||
{title}
|
||||
</h1>
|
||||
<div className={styles.titleContainer}>
|
||||
<h1 className={styles.title}>{title}</h1>
|
||||
<img
|
||||
src="assets/Shapes_1.svg"
|
||||
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>
|
||||
|
||||
{/* 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)]">
|
||||
{subtitle}
|
||||
</h2>
|
||||
<h2 className={styles.subtitle}>{subtitle}</h2>
|
||||
</div>
|
||||
|
||||
{/* Description - 20px gap from subtitle at xl */}
|
||||
<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>
|
||||
{/* Description */}
|
||||
{description && <p className={styles.description}>{description}</p>}
|
||||
</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"
|
||||
>
|
||||
{linkText}
|
||||
</a>
|
||||
)}
|
||||
|
||||
{/* CTA Button */}
|
||||
<div className="flex justify-start">
|
||||
{/* Small button for xsm and sm breakpoints */}
|
||||
<div className="block md:hidden">
|
||||
<Button variant="primary" size="small">
|
||||
{ctaText}
|
||||
</Button>
|
||||
{ctaText && (
|
||||
<div className="flex justify-start">
|
||||
{/* Small button for xsm and sm breakpoints */}
|
||||
<div className="block md:hidden">
|
||||
<Button variant="primary" size="small">
|
||||
{ctaText}
|
||||
</Button>
|
||||
</div>
|
||||
{/* Large button for md and lg breakpoints */}
|
||||
<div className="hidden md:block xl:hidden">
|
||||
<Button variant="primary" size="large" className={buttonClassName}>
|
||||
{ctaText}
|
||||
</Button>
|
||||
</div>
|
||||
{/* XLarge button for xl breakpoint */}
|
||||
<div className="hidden xl:block">
|
||||
<Button variant="primary" size="xlarge">
|
||||
{ctaText}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
{/* Large button for md and lg breakpoints */}
|
||||
<div className="hidden md:block xl:hidden">
|
||||
<Button variant="primary" size="large" className={buttonClassName}>
|
||||
{ctaText}
|
||||
</Button>
|
||||
</div>
|
||||
{/* XLarge button for xl breakpoint */}
|
||||
<div className="hidden xl:block">
|
||||
<Button variant="primary" size="xlarge">
|
||||
{ctaText}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import ContentLockup from "./ContentLockup";
|
||||
import MiniCard from "./MiniCard";
|
||||
|
||||
const FeatureGrid = ({ title, subtitle, className = "" }) => {
|
||||
return (
|
||||
<section
|
||||
className={`py-[var(--spacing-scale-032)] px-[var(--spacing-scale-020)] bg-transparent ${className}`}
|
||||
aria-labelledby="feature-grid-headline"
|
||||
role="region"
|
||||
>
|
||||
<div className="max-w-[1200px] mx-auto gap-[var(--spacing-scale-048)]">
|
||||
{/* Feature Content Lockup */}
|
||||
<ContentLockup
|
||||
title={title}
|
||||
subtitle={subtitle}
|
||||
variant="feature"
|
||||
linkText="Learn more"
|
||||
linkHref="#"
|
||||
/>
|
||||
|
||||
{/* MiniCard Grid */}
|
||||
<div className="grid grid-cols-2 gap-[var(--spacing-scale-012)] mt-[var(--spacing-scale-048)]">
|
||||
<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>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default FeatureGrid;
|
||||
@@ -0,0 +1,49 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
|
||||
const MiniCard = ({
|
||||
children,
|
||||
className = "",
|
||||
backgroundColor = "bg-[var(--color-surface-default-brand-royal)]",
|
||||
panelContent,
|
||||
label,
|
||||
labelLine1,
|
||||
labelLine2,
|
||||
}) => {
|
||||
return (
|
||||
<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`}
|
||||
>
|
||||
{/* Content for the inner panel */}
|
||||
{panelContent && (
|
||||
<div className="flex items-center justify-center w-full h-full">
|
||||
<img
|
||||
src={panelContent}
|
||||
alt=""
|
||||
className="max-w-[58px] max-h-[58px] w-auto h-auto object-contain"
|
||||
/>
|
||||
</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>
|
||||
);
|
||||
};
|
||||
|
||||
export default MiniCard;
|
||||
@@ -3,6 +3,7 @@ import HeroBanner from "./components/HeroBanner";
|
||||
import LogoWall from "./components/LogoWall";
|
||||
import RuleStack from "./components/RuleStack";
|
||||
import QuoteBlock from "./components/QuoteBlock";
|
||||
import FeatureGrid from "./components/FeatureGrid";
|
||||
|
||||
export default function Page() {
|
||||
const heroBannerData = {
|
||||
@@ -36,12 +37,19 @@ 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.",
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<HeroBanner {...heroBannerData} />
|
||||
<LogoWall />
|
||||
<NumberedCards {...numberedCardsData} />
|
||||
<RuleStack />
|
||||
<FeatureGrid {...featureGridData} />
|
||||
<QuoteBlock />
|
||||
</div>
|
||||
);
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
@@ -8,7 +8,7 @@ export default {
|
||||
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.",
|
||||
"A content lockup component that groups title, subtitle, description, and CTA button. Features responsive typography and spacing that adapts across breakpoints. Supports hero and feature variants with different styling and typography scales.",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -38,11 +38,16 @@ export default {
|
||||
description:
|
||||
"Additional CSS classes to apply to the large button (md/lg breakpoints)",
|
||||
},
|
||||
variant: {
|
||||
control: { type: "select" },
|
||||
options: ["hero", "feature"],
|
||||
description: "The visual variant of the content lockup",
|
||||
},
|
||||
},
|
||||
tags: ["autodocs"],
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
export const Hero = {
|
||||
args: {
|
||||
title: "Collaborate",
|
||||
subtitle: "with clarity",
|
||||
@@ -50,11 +55,33 @@ export const Default = {
|
||||
"Help your community make important decisions in a way that reflects its unique values.",
|
||||
ctaText: "Learn how Community Rule works",
|
||||
ctaHref: "#",
|
||||
variant: "hero",
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story: "Default content lockup with standard Community Rule messaging.",
|
||||
story:
|
||||
"Hero variant with large typography and inverse colors, designed for prominent display areas.",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const Feature = {
|
||||
args: {
|
||||
title: "Build",
|
||||
subtitle: "consensus",
|
||||
description:
|
||||
"Create structured decision-making processes that help your community reach agreement on important matters.",
|
||||
ctaText: "Explore consensus methods",
|
||||
ctaHref: "#",
|
||||
variant: "feature",
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story:
|
||||
"Feature variant with smaller typography and primary colors, designed for content sections.",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -68,6 +95,7 @@ export const LongDescription = {
|
||||
"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.",
|
||||
ctaText: "Learn how Community Rule works",
|
||||
ctaHref: "#",
|
||||
variant: "hero",
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
@@ -86,6 +114,7 @@ export const ShortContent = {
|
||||
description: "Easy community decision making.",
|
||||
ctaText: "Try it",
|
||||
ctaHref: "#",
|
||||
variant: "feature",
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
@@ -105,6 +134,7 @@ export const CustomButtonStyling = {
|
||||
ctaText: "Learn how Community Rule works",
|
||||
ctaHref: "#",
|
||||
buttonClassName: "shrink-0 whitespace-nowrap min-w-[280px]",
|
||||
variant: "hero",
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
|
||||
@@ -0,0 +1,307 @@
|
||||
import FeatureGrid from "../app/components/FeatureGrid";
|
||||
|
||||
export default {
|
||||
title: "Components/FeatureGrid",
|
||||
component: FeatureGrid,
|
||||
parameters: {
|
||||
layout: "fullscreen",
|
||||
docs: {
|
||||
description: {
|
||||
component: `
|
||||
A responsive component that displays a collection of organizational tools and services in a clean card-based grid layout with supportive messaging and categorized feature highlights.
|
||||
|
||||
## Features
|
||||
- **Three grid variants**: 1x4, 2x2, and 2x4 configurations
|
||||
- **Responsive design**: Adapts from single column to multi-column grid
|
||||
- **Color coding**: Purple, green, pink, and blue brand colors for categorization
|
||||
- **Interactive elements**: Hover states and keyboard navigation
|
||||
- **Accessibility**: WCAG 2.1 AA compliant with proper ARIA labels
|
||||
- **Design system integration**: Uses design tokens for consistent styling
|
||||
|
||||
## Usage
|
||||
\`\`\`jsx
|
||||
<FeatureGrid
|
||||
variant="2x2"
|
||||
headline="Your headline here"
|
||||
description="Your description here"
|
||||
features={[
|
||||
{
|
||||
id: "feature-1",
|
||||
label: "Feature Name",
|
||||
description: "Feature description",
|
||||
icon: "path/to/icon.svg",
|
||||
color: "purple"
|
||||
}
|
||||
]}
|
||||
/>
|
||||
\`\`\`
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
argTypes: {
|
||||
variant: {
|
||||
control: { type: "select" },
|
||||
options: ["1x4", "2x2", "2x4"],
|
||||
description: "Grid layout variant",
|
||||
},
|
||||
headline: {
|
||||
control: { type: "text" },
|
||||
description: "Main headline text",
|
||||
},
|
||||
description: {
|
||||
control: { type: "text" },
|
||||
description: "Supporting description text",
|
||||
},
|
||||
ctaText: {
|
||||
control: { type: "text" },
|
||||
description: "Call-to-action button text",
|
||||
},
|
||||
ctaHref: {
|
||||
control: { type: "text" },
|
||||
description: "Call-to-action link URL",
|
||||
},
|
||||
features: {
|
||||
control: { type: "object" },
|
||||
description: "Array of feature objects",
|
||||
},
|
||||
onFeatureClick: {
|
||||
action: "feature-click",
|
||||
description: "Callback when feature card is clicked",
|
||||
},
|
||||
onCtaClick: {
|
||||
action: "cta-click",
|
||||
description: "Callback when CTA is clicked",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Sample feature data
|
||||
const sampleFeatures = [
|
||||
{
|
||||
id: "consensus",
|
||||
label: "Consensus Decision Making",
|
||||
description: "Build agreement through collaborative processes",
|
||||
icon: "assets/Icon_Consensus.svg",
|
||||
color: "purple",
|
||||
},
|
||||
{
|
||||
id: "governance",
|
||||
label: "Governance Structures",
|
||||
description: "Create clear roles and responsibilities",
|
||||
icon: "assets/Icon_ElectedBoard.svg",
|
||||
color: "green",
|
||||
},
|
||||
{
|
||||
id: "communication",
|
||||
label: "Communication Tools",
|
||||
description: "Facilitate transparent information sharing",
|
||||
icon: "assets/Icon_Sociocracy.svg",
|
||||
color: "pink",
|
||||
},
|
||||
{
|
||||
id: "resources",
|
||||
label: "Resource Management",
|
||||
description: "Efficiently allocate and track resources",
|
||||
icon: "assets/Icon_Petition.svg",
|
||||
color: "blue",
|
||||
},
|
||||
];
|
||||
|
||||
// Default story
|
||||
export const Default = {
|
||||
args: {
|
||||
variant: "2x2",
|
||||
headline: "Everything you need to build better communities",
|
||||
description: "Our comprehensive toolkit provides the tools, resources, and guidance to help your organization thrive.",
|
||||
ctaText: "Learn more",
|
||||
ctaHref: "#",
|
||||
features: sampleFeatures,
|
||||
},
|
||||
};
|
||||
|
||||
// 1x4 Grid Variant
|
||||
export const OneByFour = {
|
||||
args: {
|
||||
variant: "1x4",
|
||||
headline: "Core organizational tools",
|
||||
description: "Essential features for effective community governance and decision-making.",
|
||||
ctaText: "Explore tools",
|
||||
ctaHref: "#",
|
||||
features: sampleFeatures,
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story: "1x4 grid layout optimized for showcasing four key features in a single row on desktop.",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// 2x4 Grid Variant
|
||||
export const TwoByFour = {
|
||||
args: {
|
||||
variant: "2x4",
|
||||
headline: "Complete toolkit for organizations",
|
||||
description: "Eight essential tools and services to support your community's growth and success.",
|
||||
ctaText: "Get started",
|
||||
ctaHref: "#",
|
||||
features: [
|
||||
...sampleFeatures,
|
||||
{
|
||||
id: "analytics",
|
||||
label: "Analytics & Insights",
|
||||
description: "Track progress and measure impact",
|
||||
icon: "assets/Icon_Consensus.svg",
|
||||
color: "purple",
|
||||
},
|
||||
{
|
||||
id: "training",
|
||||
label: "Training & Education",
|
||||
description: "Build skills and knowledge",
|
||||
icon: "assets/Icon_ElectedBoard.svg",
|
||||
color: "green",
|
||||
},
|
||||
{
|
||||
id: "support",
|
||||
label: "Community Support",
|
||||
description: "Connect with peers and experts",
|
||||
icon: "assets/Icon_Sociocracy.svg",
|
||||
color: "pink",
|
||||
},
|
||||
{
|
||||
id: "integration",
|
||||
label: "System Integration",
|
||||
description: "Connect with existing tools",
|
||||
icon: "assets/Icon_Petition.svg",
|
||||
color: "blue",
|
||||
},
|
||||
],
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story: "2x4 grid layout for comprehensive feature showcases with eight tools.",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// All Variants Comparison
|
||||
export const AllVariants = {
|
||||
render: () => (
|
||||
<div className="space-y-16 p-4">
|
||||
<div>
|
||||
<h3 className="text-lg font-bold mb-4">1x4 Grid Variant</h3>
|
||||
<FeatureGrid
|
||||
variant="1x4"
|
||||
headline="Core organizational tools"
|
||||
description="Essential features for effective community governance."
|
||||
ctaText="Explore tools"
|
||||
ctaHref="#"
|
||||
features={sampleFeatures}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-lg font-bold mb-4">2x2 Grid Variant</h3>
|
||||
<FeatureGrid
|
||||
variant="2x2"
|
||||
headline="Everything you need to build better communities"
|
||||
description="Our comprehensive toolkit provides the tools, resources, and guidance to help your organization thrive."
|
||||
ctaText="Learn more"
|
||||
ctaHref="#"
|
||||
features={sampleFeatures}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-lg font-bold mb-4">2x4 Grid Variant</h3>
|
||||
<FeatureGrid
|
||||
variant="2x4"
|
||||
headline="Complete toolkit for organizations"
|
||||
description="Eight essential tools and services to support your community's growth and success."
|
||||
ctaText="Get started"
|
||||
ctaHref="#"
|
||||
features={[
|
||||
...sampleFeatures,
|
||||
{
|
||||
id: "analytics",
|
||||
label: "Analytics & Insights",
|
||||
description: "Track progress and measure impact",
|
||||
icon: "assets/Icon_Consensus.svg",
|
||||
color: "purple",
|
||||
},
|
||||
{
|
||||
id: "training",
|
||||
label: "Training & Education",
|
||||
description: "Build skills and knowledge",
|
||||
icon: "assets/Icon_ElectedBoard.svg",
|
||||
color: "green",
|
||||
},
|
||||
{
|
||||
id: "support",
|
||||
label: "Community Support",
|
||||
description: "Connect with peers and experts",
|
||||
icon: "assets/Icon_Sociocracy.svg",
|
||||
color: "pink",
|
||||
},
|
||||
{
|
||||
id: "integration",
|
||||
label: "System Integration",
|
||||
description: "Connect with existing tools",
|
||||
icon: "assets/Icon_Petition.svg",
|
||||
color: "blue",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story: "Side-by-side comparison of all three grid variants to show the differences in layout and content density.",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Interactive States
|
||||
export const InteractiveStates = {
|
||||
args: {
|
||||
variant: "2x2",
|
||||
headline: "Interactive feature showcase",
|
||||
description: "Hover over cards and use keyboard navigation to test interactive states.",
|
||||
ctaText: "Try it out",
|
||||
ctaHref: "#",
|
||||
features: sampleFeatures,
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story: "Test hover states, focus indicators, and keyboard navigation for accessibility compliance.",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Empty State
|
||||
export const EmptyState = {
|
||||
args: {
|
||||
variant: "2x2",
|
||||
headline: "No features available",
|
||||
description: "This is how the component looks when no features are provided.",
|
||||
ctaText: "Add features",
|
||||
ctaHref: "#",
|
||||
features: [],
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story: "Empty state when no features are provided, showing graceful fallback messaging.",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user