Rule Stack #11

Merged
an.di merged 29 commits from adilallo/component/RuleStack into main 2025-08-26 21:31:42 +00:00
3 changed files with 261 additions and 1 deletions
Showing only changes of commit f22cde728a - Show all commits
+176
View File
@@ -0,0 +1,176 @@
import RuleCard from "../app/components/RuleCard";
import Image from "next/image";
export default {
title: "Components/RuleCard",
component: RuleCard,
parameters: {
layout: "centered",
docs: {
description: {
component:
"An interactive card component that displays governance templates and decision-making patterns. Features hover states, keyboard navigation, analytics tracking, and accessibility support. Use Tab key to test focus indicators and Enter/Space to activate.",
},
},
},
argTypes: {
title: {
control: { type: "text" },
description: "The title of the governance template",
},
description: {
control: { type: "text" },
description: "The description of the governance pattern",
},
backgroundColor: {
control: { type: "select" },
options: [
"bg-[var(--color-surface-default-brand-lime)]",
"bg-[var(--color-surface-default-brand-rust)]",
"bg-[var(--color-surface-default-brand-red)]",
"bg-[var(--color-surface-default-brand-teal)]",
"bg-[var(--color-community-teal-100)]",
],
description: "The background color variant for the card",
},
onClick: { action: "clicked" },
},
tags: ["autodocs"],
};
export const Default = {
args: {
title: "Consensus clusters",
description:
"Units called Circles have the ability to decide and act on matters in their domains, which their members agree on through a Council.",
backgroundColor: "bg-[var(--color-surface-default-brand-lime)]",
icon: (
<Image
src="/assets/Icon_Sociocracy.svg"
alt="Sociocracy"
width={40}
height={40}
className="md:w-[56px] md:h-[56px] lg:w-[90px] lg:h-[90px]"
/>
),
},
};
export const AllVariants = {
render: (args) => (
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 max-w-4xl">
<RuleCard
title="Consensus clusters"
description="Units called Circles have the ability to decide and act on matters in their domains, which their members agree on through a Council."
backgroundColor="bg-[var(--color-surface-default-brand-lime)]"
icon={
<Image
src="/assets/Icon_Sociocracy.svg"
alt="Sociocracy"
width={40}
height={40}
className="md:w-[56px] md:h-[56px] lg:w-[90px] lg:h-[90px]"
/>
}
onClick={() => console.log("Consensus clusters selected")}
/>
<RuleCard
title="Consensus"
description="Decisions that affect the group collectively should involve participation of all participants."
backgroundColor="bg-[var(--color-surface-default-brand-rust)]"
icon={
<Image
src="/assets/Icon_Consensus.svg"
alt="Consensus"
width={40}
height={40}
className="md:w-[56px] md:h-[56px] lg:w-[90px] lg:h-[90px]"
/>
}
onClick={() => console.log("Consensus selected")}
/>
<RuleCard
title="Elected Board"
description="An elected board determines policies and organizes their implementation."
backgroundColor="bg-[var(--color-surface-default-brand-red)]"
icon={
<Image
src="/assets/Icon_ElectedBoard.svg"
alt="Elected Board"
width={40}
height={40}
className="md:w-[56px] md:h-[56px] lg:w-[90px] lg:h-[90px]"
/>
}
onClick={() => console.log("Elected Board selected")}
/>
<RuleCard
title="Petition"
description="All participants can propose and vote on proposals for the group."
backgroundColor="bg-[var(--color-surface-default-brand-teal)]"
icon={
<Image
src="/assets/Icon_Petition.svg"
alt="Petition"
width={40}
height={40}
className="md:w-[56px] md:h-[56px] lg:w-[90px] lg:h-[90px]"
/>
}
onClick={() => console.log("Petition selected")}
/>
</div>
),
parameters: {
docs: {
description: {
story:
"All four governance template variants with their respective colors and icons. Test hover states, focus indicators, and click interactions.",
},
},
},
};
export const InteractiveStates = {
args: {
title: "Interactive Demo",
description:
"Hover over this card to see the scale and shadow effects. Use Tab to focus and Enter/Space to activate.",
backgroundColor: "bg-[var(--color-community-teal-100)]",
icon: (
<div className="w-10 h-10 md:w-14 md:h-14 lg:w-[90px] lg:h-[90px] bg-white rounded-full flex items-center justify-center">
<span className="text-lg font-bold text-gray-800">?</span>
</div>
),
},
parameters: {
docs: {
description: {
story:
"Demonstrates interactive states including hover effects, focus indicators, and keyboard navigation. Test with mouse hover and keyboard Tab/Enter/Space.",
},
},
},
};
export const AccessibilityTest = {
args: {
title: "Accessibility Demo",
description:
"This card is designed for accessibility testing. Use Tab to focus, Enter/Space to activate, and screen readers to test ARIA labels.",
backgroundColor: "bg-[var(--color-surface-default-brand-teal)]",
icon: (
<div className="w-10 h-10 md:w-14 md:h-14 lg:w-[90px] lg:h-[90px] bg-white rounded-full flex items-center justify-center">
<span className="text-lg font-bold text-gray-800"></span>
</div>
),
},
parameters: {
docs: {
description: {
story:
"Specifically designed for testing accessibility features including keyboard navigation, screen reader support, and focus management.",
},
},
},
};
+39
View File
@@ -0,0 +1,39 @@
import RuleStack from "../app/components/RuleStack";
export default {
title: "Components/RuleStack",
component: RuleStack,
parameters: {
layout: "fullscreen",
docs: {
description: {
component:
"A complete template library component that displays governance patterns in a responsive grid layout. Includes SectionHeader with multi-line variant, interactive RuleCard components, and a call-to-action button. Features comprehensive accessibility, analytics tracking, and responsive design across all breakpoints.\n\n" +
"**Testing Scenarios:**\n" +
"- **Responsive Testing**: Resize browser window to test layout adaptation from single column on mobile to 2x2 grid on larger screens\n" +
"- **Interactive Testing**: Hover over cards to see effects, use Tab to navigate between cards, and click to see analytics events in console\n" +
"- **Accessibility Testing**: Use screen readers to test ARIA labels, keyboard navigation to move between cards, and verify focus indicators\n" +
"- **Custom Styling**: Add className prop to customize background or other styling",
},
},
},
argTypes: {
className: {
control: { type: "text" },
description: "Additional CSS classes for custom styling",
},
},
tags: ["autodocs"],
};
export const Default = {
args: {},
parameters: {
docs: {
description: {
story:
"The complete RuleStack component with all four governance templates, responsive grid layout, and interactive features. Test hover states, keyboard navigation, and responsive behavior across different screen sizes.",
},
},
},
};
+46 -1
View File
@@ -8,7 +8,7 @@ export default {
docs: {
description: {
component:
"A section header component that displays a title and subtitle with responsive typography and layout. Supports different title text for large breakpoints and maintains consistent spacing across all screen sizes.",
"A section header component that displays a title and subtitle with responsive typography and layout. Supports different title text for large breakpoints and maintains consistent spacing across all screen sizes. Includes 'default' and 'multi-line' variants with different layout behaviors.",
},
},
},
@@ -26,6 +26,12 @@ export default {
description:
"The title text for lg and xl breakpoints (optional, falls back to title)",
},
variant: {
control: { type: "select" },
options: ["default", "multi-line"],
description:
"The layout variant - 'default' for traditional layout, 'multi-line' for 50/50 split layout",
},
},
tags: ["autodocs"],
};
@@ -35,6 +41,24 @@ export const Default = {
title: "How CommunityRule works",
subtitle: "Here's a quick overview of the process, from start to finish.",
titleLg: "How CommunityRule helps",
variant: "default",
},
};
export const MultiLine = {
args: {
title: "Popular templates",
subtitle:
"These are popular patterns for making decisions in mutual aid and open source communities. You can use them as they are or as a starting place for customizing your own CommunityRule.",
variant: "multi-line",
},
parameters: {
docs: {
description: {
story:
"The multi-line variant creates a 50/50 split layout at lg and xl breakpoints, with the title on the left and subtitle on the right. This variant is used in the RuleStack component.",
},
},
},
};
@@ -44,6 +68,7 @@ export const CustomContent = {
subtitle:
"We're dedicated to helping communities thrive through better decision-making processes and transparent governance structures.",
titleLg: "Building Better Communities",
variant: "default",
},
parameters: {
docs: {
@@ -61,6 +86,7 @@ export const LongSubtitle = {
subtitle:
"This is a much longer subtitle that demonstrates how the component handles extended text content across different breakpoints and layout configurations.",
titleLg: "Complex Process Simplified",
variant: "default",
},
parameters: {
docs: {
@@ -78,6 +104,7 @@ export const ResponsiveTest = {
subtitle:
"Test the responsive behavior by resizing your browser window or using the viewport controls in Storybook.",
titleLg: "Responsive Design Test",
variant: "default",
},
parameters: {
docs: {
@@ -94,6 +121,7 @@ export const WithoutTitleLg = {
title: "Simple Header",
subtitle:
"This example doesn't specify a titleLg prop, so it will use the same title text across all breakpoints.",
variant: "default",
},
parameters: {
docs: {
@@ -104,3 +132,20 @@ export const WithoutTitleLg = {
},
},
};
export const MultiLineResponsive = {
args: {
title: "Multi-line Responsive Test",
subtitle:
"This multi-line variant demonstrates the 50/50 split layout at larger breakpoints. Resize your browser to see how the layout adapts from stacked on mobile to side-by-side on desktop.",
variant: "multi-line",
},
parameters: {
docs: {
description: {
story:
"Test the responsive behavior of the multi-line variant. The layout changes from stacked on mobile to 50/50 split on lg and xl breakpoints.",
},
},
},
};