Rule Stack Start

This commit is contained in:
adilallo
2025-08-22 13:57:56 -06:00
parent a8f17cc6c7
commit a9557ddedf
10 changed files with 183 additions and 6 deletions
+40
View File
@@ -0,0 +1,40 @@
"use client";
const RuleCard = ({
title,
description,
icon,
backgroundColor = "bg-[var(--color-community-teal-100)]",
className = "",
}) => {
return (
<div
className={`${backgroundColor} rounded-[var(--spacing-scale-012)] pt-[var(--spacing-scale-012)] pr-[var(--spacing-scale-012)] pl-[var(--spacing-scale-012)] pb-[var(--spacing-scale-024)] flex flex-col gap-[18px] shadow-lg backdrop-blur-sm ${className}`}
>
{/* Header Container */}
<div className="grid grid-cols-[auto_1fr] h-[72px] border-b border-[var(--color-surface-default-primary)]">
{/* Icon Container */}
{icon && (
<div className="p-[var(--spacing-scale-016)] border-r border-[var(--color-surface-default-primary)] w-fit flex items-center justify-center">
{icon}
</div>
)}
{/* Title Container */}
{title && (
<div className="pl-[var(--spacing-scale-008)] flex items-center gap-[var(--spacing-scale-004)]">
<h3 className="font-space-grotesk font-bold text-[20px] leading-[28px] text-[--color-content-inverse-primary]">
{title}
</h3>
</div>
)}
</div>
{description && (
<p className="font-inter font-medium text-[12px] leading-[14px] text-[var(--color-content-inverse-primary)]">
{description}
</p>
)}
</div>
);
};
export default RuleCard;
+75
View File
@@ -0,0 +1,75 @@
"use client";
import SectionHeader from "./SectionHeader";
import RuleCard from "./RuleCard";
import Image from "next/image";
const RuleStack = ({ children, className = "" }) => {
return (
<div
className={`w-full bg-transparent py-[var(--spacing-scale-032)] px-[var(--spacing-scale-020)] flex flex-col gap-[var(--spacing-scale-024)] ${className}`}
>
<SectionHeader
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="small"
/>
<div className="flex flex-col gap-[18px]">
<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."
icon={
<Image
src="/assets/Icon_Sociocracy.svg"
alt="Sociocracy"
width={40}
height={40}
/>
}
backgroundColor="bg-[var(--color-community-kiwi-200)]"
/>
<RuleCard
title="Consensus"
description="Decisions that affect the group collectively should involve participation of all participants."
icon={
<Image
src="/assets/Icon_Consensus.svg"
alt="Consensus"
width={40}
height={40}
/>
}
backgroundColor="bg-[var(--color-community-red-200)]"
/>
<RuleCard
title="Elected Board"
description="An elected board determines policies and organizes their implementation."
icon={
<Image
src="/assets/Icon_ElectedBoard.svg"
alt="Elected Board"
width={40}
height={40}
/>
}
backgroundColor="bg-[var(--color-surface-default-brand-accent)]"
/>
<RuleCard
title="Petition"
description="All participants can propose and vote on proposals for the group."
icon={
<Image
src="/assets/Icon_Petition.svg"
alt="Petition"
width={40}
height={40}
/>
}
backgroundColor="bg-[var(--color-community-blue-300)]"
/>
</div>
</div>
);
};
export default RuleStack;
+15 -3
View File
@@ -1,11 +1,17 @@
"use client";
const SectionHeader = ({ title, subtitle, titleLg }) => {
const SectionHeader = ({ title, subtitle, titleLg, variant = "default" }) => {
return (
<div className="flex flex-col gap-1 w-full lg:flex-row lg:justify-between lg:items-start xl:gap-[var(--spacing-scale-024)]">
{/* Title Container - Left side (lg breakpoint) */}
<div className="lg:w-[369px] lg:h-[120px] lg:flex lg:items-center xl:w-[452px] xl:h-[156px] xl:flex xl:items-center">
<h2 className="font-bricolage-grotesque font-bold text-[28px] leading-[36px] sm:text-[32px] sm:leading-[40px] lg:text-[32px] lg:leading-[40px] lg:w-[369px] lg:pr-24 xl:text-[40px] xl:leading-[52px] xl:w-[452px] xl:pr-24 text-[var(--color-content-default-primary)]">
<h2
className={
variant === "small"
? "font-bricolage-grotesque font-bold text-[28px] leading-[36px] text-[var(--color-content-default-primary)]"
: "font-bricolage-grotesque font-bold text-[28px] leading-[36px] sm:text-[32px] sm:leading-[40px] lg:text-[32px] lg:leading-[40px] lg:w-[369px] lg:pr-24 xl:text-[40px] xl:leading-[52px] xl:w-[452px] xl:pr-24 text-[var(--color-content-default-primary)]"
}
>
<span className="block lg:hidden">{title}</span>
<span className="hidden lg:block">{titleLg || title}</span>
</h2>
@@ -13,7 +19,13 @@ const SectionHeader = ({ title, subtitle, titleLg }) => {
{/* Subtitle Container */}
<div className="lg:w-[928px] lg:h-[120px] lg:flex lg:items-center lg:justify-end xl:w-[763px] xl:h-[156px] xl:flex xl:items-center xl:justify-end">
<p className="font-inter font-normal text-[18px] leading-[130%] sm:text-[18px] sm:leading-[32px] lg:text-[24px] lg:leading-[32px] xl:text-[32px] xl:leading-[40px] xl:text-right text-[#484848] sm:text-[var(--color-content-default-tertiary)] lg:text-[var(--color-content-default-tertiary)] xl:text-[var(--color-content-default-tertiary)] tracking-[0px]">
<p
className={
variant === "small"
? "font-inter font-normal text-[14px] leading-[20px] text-[var(--color-content-default-tertiary)]"
: "font-inter font-normal text-[18px] leading-[130%] sm:text-[18px] sm:leading-[32px] lg:text-[24px] lg:leading-[32px] xl:text-[32px] xl:leading-[40px] xl:text-right text-[#484848] sm:text-[var(--color-content-default-tertiary)] lg:text-[var(--color-content-default-tertiary)] xl:text-[var(--color-content-default-tertiary)] tracking-[0px]"
}
>
{subtitle}
</p>
</div>
+5
View File
@@ -12,6 +12,11 @@
-apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial;
}
.font-space-grotesk {
font-family: var(--font-space-grotesk), ui-sans-serif, system-ui,
-apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial;
}
/* Set default body text face */
html,
body {
+11 -3
View File
@@ -1,4 +1,4 @@
import { Inter, Bricolage_Grotesque } from "next/font/google";
import { Inter, Bricolage_Grotesque, Space_Grotesk } from "next/font/google";
import "./globals.css";
import HomeHeader from "./components/HomeHeader";
import Footer from "./components/Footer";
@@ -11,14 +11,22 @@ const inter = Inter({
const bricolageGrotesque = Bricolage_Grotesque({
subsets: ["latin"],
weight: ["400", "500"],
weight: ["400", "500", "700"],
variable: "--font-bricolage-grotesque",
});
const spaceGrotesk = Space_Grotesk({
subsets: ["latin"],
weight: ["400", "500", "700"],
variable: "--font-space-grotesk",
});
export default function RootLayout({ children }) {
return (
<html lang="en">
<body className={`${inter.variable} ${bricolageGrotesque.variable}`}>
<body
className={`${inter.variable} ${bricolageGrotesque.variable} ${spaceGrotesk.variable}`}
>
<div className="min-h-screen flex flex-col">
<HomeHeader />
<main className="flex-1">{children}</main>
+2
View File
@@ -1,6 +1,7 @@
import NumberedCards from "./components/NumberedCards";
import HeroBanner from "./components/HeroBanner";
import LogoWall from "./components/LogoWall";
import RuleStack from "./components/RuleStack";
export default function Page() {
const heroBannerData = {
@@ -39,6 +40,7 @@ export default function Page() {
<HeroBanner {...heroBannerData} />
<LogoWall />
<NumberedCards {...numberedCardsData} />
<RuleStack />
</div>
);
}