Component cleanup
This commit is contained in:
@@ -1,138 +0,0 @@
|
||||
import React, { useState } from "react";
|
||||
import ContextMenu from "../../app/components/modals/ContextMenu/ContextMenu";
|
||||
import ContextMenuItem from "../../app/components/modals/ContextMenuItem";
|
||||
import ContextMenuSection from "../../app/components/modals/ContextMenu/ContextMenuSection";
|
||||
import ContextMenuDivider from "../../app/components/modals/ContextMenu/ContextMenuDivider";
|
||||
|
||||
export default {
|
||||
title: "Components/ContextMenu/ContextMenu",
|
||||
component: ContextMenu,
|
||||
argTypes: {
|
||||
className: {
|
||||
control: { type: "text" },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const Template = (args) => (
|
||||
<ContextMenu {...args}>
|
||||
<ContextMenuItem>Context Menu Item</ContextMenuItem>
|
||||
<ContextMenuItem>Context Menu Item</ContextMenuItem>
|
||||
<ContextMenuItem hasSubmenu>Context Menu Item</ContextMenuItem>
|
||||
<ContextMenuItem hasSubmenu>Context Menu Item</ContextMenuItem>
|
||||
<ContextMenuDivider />
|
||||
<ContextMenuItem selected>Context Menu Item</ContextMenuItem>
|
||||
<ContextMenuItem>Context Menu Item</ContextMenuItem>
|
||||
<ContextMenuDivider />
|
||||
<ContextMenuSection title="Section Title">
|
||||
<ContextMenuItem>Context Menu Item</ContextMenuItem>
|
||||
<ContextMenuItem>Context Menu Item</ContextMenuItem>
|
||||
</ContextMenuSection>
|
||||
</ContextMenu>
|
||||
);
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
||||
export const WithCustomStyling = Template.bind({});
|
||||
WithCustomStyling.args = {
|
||||
className: "min-w-[250px]",
|
||||
};
|
||||
|
||||
// Individual component stories
|
||||
export const MenuItem = () => (
|
||||
<div className="space-y-2">
|
||||
<ContextMenuItem>Default Menu Item</ContextMenuItem>
|
||||
<ContextMenuItem selected>Selected Menu Item</ContextMenuItem>
|
||||
<ContextMenuItem hasSubmenu>Menu Item with Submenu</ContextMenuItem>
|
||||
<ContextMenuItem disabled>Disabled Menu Item</ContextMenuItem>
|
||||
</div>
|
||||
);
|
||||
|
||||
export const MenuSection = () => (
|
||||
<ContextMenu>
|
||||
<ContextMenuSection title="First Section">
|
||||
<ContextMenuItem>Item 1</ContextMenuItem>
|
||||
<ContextMenuItem>Item 2</ContextMenuItem>
|
||||
</ContextMenuSection>
|
||||
<ContextMenuDivider />
|
||||
<ContextMenuSection title="Second Section">
|
||||
<ContextMenuItem>Item 3</ContextMenuItem>
|
||||
<ContextMenuItem>Item 4</ContextMenuItem>
|
||||
</ContextMenuSection>
|
||||
</ContextMenu>
|
||||
);
|
||||
|
||||
export const MenuDivider = () => (
|
||||
<ContextMenu>
|
||||
<ContextMenuItem>Item Above</ContextMenuItem>
|
||||
<ContextMenuDivider />
|
||||
<ContextMenuItem>Item Below</ContextMenuItem>
|
||||
</ContextMenu>
|
||||
);
|
||||
|
||||
export const Interactive = () => {
|
||||
const [selectedItem, setSelectedItem] = useState("");
|
||||
|
||||
return (
|
||||
<ContextMenu>
|
||||
<ContextMenuItem
|
||||
selected={selectedItem === "item1"}
|
||||
onClick={() => setSelectedItem("item1")}
|
||||
>
|
||||
Context Menu Item 1
|
||||
</ContextMenuItem>
|
||||
<ContextMenuItem
|
||||
selected={selectedItem === "item2"}
|
||||
onClick={() => setSelectedItem("item2")}
|
||||
>
|
||||
Context Menu Item 2
|
||||
</ContextMenuItem>
|
||||
<ContextMenuItem
|
||||
selected={selectedItem === "item3"}
|
||||
onClick={() => setSelectedItem("item3")}
|
||||
>
|
||||
Context Menu Item 3
|
||||
</ContextMenuItem>
|
||||
</ContextMenu>
|
||||
);
|
||||
};
|
||||
|
||||
// Comparison stories
|
||||
export const AllVariants = () => (
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<h3 className="text-sm font-medium mb-2">Default Items</h3>
|
||||
<ContextMenu>
|
||||
<ContextMenuItem>Context Menu Item</ContextMenuItem>
|
||||
<ContextMenuItem>Context Menu Item</ContextMenuItem>
|
||||
</ContextMenu>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-sm font-medium mb-2">With Submenu Indicators</h3>
|
||||
<ContextMenu>
|
||||
<ContextMenuItem hasSubmenu>Context Menu Item</ContextMenuItem>
|
||||
<ContextMenuItem hasSubmenu>Context Menu Item</ContextMenuItem>
|
||||
</ContextMenu>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-sm font-medium mb-2">With Selected Item</h3>
|
||||
<ContextMenu>
|
||||
<ContextMenuItem>Context Menu Item</ContextMenuItem>
|
||||
<ContextMenuItem selected>Context Menu Item</ContextMenuItem>
|
||||
<ContextMenuItem>Context Menu Item</ContextMenuItem>
|
||||
</ContextMenu>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-sm font-medium mb-2">With Sections</h3>
|
||||
<ContextMenu>
|
||||
<ContextMenuSection title="Section Title">
|
||||
<ContextMenuItem>Context Menu Item</ContextMenuItem>
|
||||
<ContextMenuItem>Context Menu Item</ContextMenuItem>
|
||||
</ContextMenuSection>
|
||||
</ContextMenu>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -1,7 +1,7 @@
|
||||
import WebVitalsDashboard from "../app/components/sections/WebVitalsDashboard";
|
||||
import WebVitalsDashboard from "../app/(admin)/monitor/_components/WebVitalsDashboard";
|
||||
|
||||
export default {
|
||||
title: "Components/WebVitalsDashboard",
|
||||
title: "Components/Monitor/WebVitalsDashboard",
|
||||
component: WebVitalsDashboard,
|
||||
parameters: {
|
||||
layout: "fullscreen",
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import Avatar from "../../app/components/icons/Avatar";
|
||||
import Avatar from "../../app/components/asset/Avatar";
|
||||
|
||||
export default {
|
||||
title: "Components/Icons/Avatar",
|
||||
title: "Components/Asset/Avatar",
|
||||
component: Avatar,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
"A simple avatar component that displays user profile images with multiple size variants. Supports custom images and alt text for accessibility.",
|
||||
"Rounded profile image primitive; stacks with **`AvatarContainer`**. Fuller DS-driven Avatar behavior is **[CR-58](https://linear.app/community-rule/issue/CR-58)**.",
|
||||
},
|
||||
},
|
||||
},
|
||||
+4
-4
@@ -1,15 +1,15 @@
|
||||
import AvatarContainer from "../../app/components/utility/AvatarContainer";
|
||||
import Avatar from "../../app/components/icons/Avatar";
|
||||
import AvatarContainer from "../../app/components/asset/AvatarContainer";
|
||||
import Avatar from "../../app/components/asset/Avatar";
|
||||
|
||||
export default {
|
||||
title: "Components/Utility/AvatarContainer",
|
||||
title: "Components/Asset/AvatarContainer",
|
||||
component: AvatarContainer,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
"A container component that groups multiple avatars together with overlapping spacing. Useful for displaying multiple users or team members in a compact format.",
|
||||
"Stacks multiple `Avatar` children with overlapping spacing. Lives under `asset/` next to Avatar-related chrome.",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1,4 +1,6 @@
|
||||
import { Icon, ICON_NAME_OPTIONS } from "../../app/components/asset";
|
||||
import Icon, {
|
||||
ICON_NAME_OPTIONS,
|
||||
} from "../../app/components/asset/icon";
|
||||
|
||||
export default {
|
||||
title: "Components/Asset/Icon",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Logo from "../../app/components/asset/logo";
|
||||
import Logo from "../../app/components/asset/Logo";
|
||||
|
||||
export default {
|
||||
title: "Components/Icons/Logo",
|
||||
title: "Components/Asset/Logo",
|
||||
component: Logo,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
@@ -118,13 +118,13 @@ export const IconOnly = {
|
||||
},
|
||||
};
|
||||
|
||||
export const TopNavContext = {
|
||||
export const TopContext = {
|
||||
args: {},
|
||||
render: () => (
|
||||
<div className="min-h-screen bg-gradient-to-b from-[var(--color-surface-default-primary)] to-[var(--color-surface-default-secondary)] p-8">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h2 className="text-white font-semibold mb-6">
|
||||
TopNav Context (Responsive)
|
||||
Top (navigation) — responsive
|
||||
</h2>
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center space-x-4">
|
||||
@@ -143,7 +143,7 @@ export const TopNavContext = {
|
||||
docs: {
|
||||
description: {
|
||||
story:
|
||||
"TopNav context showing responsive logo sizes. Text hides on smallest breakpoint, shows on larger breakpoints.",
|
||||
"`Top` (Figma Navigation / Top) logo sizes: folder-top vs header variants.",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1,4 +1,4 @@
|
||||
import CardStack from "../../app/components/utility/CardStack";
|
||||
import CardStack from "../../app/components/cards/CardStack";
|
||||
|
||||
const SAMPLE_CARDS = [
|
||||
{
|
||||
@@ -43,14 +43,14 @@ const SAMPLE_CARDS = [
|
||||
];
|
||||
|
||||
export default {
|
||||
title: "Create Flow/CardStack",
|
||||
title: "Components/Cards/CardStack",
|
||||
component: CardStack,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
"Card stack for the create flow: compact grid or expanded list with toggle. Uses Card components; toggle visible only when hasMore is true.",
|
||||
"Card stack for the create flow: compact grid or expanded list with toggle. Uses Selection tiles; toggle visible only when hasMore is true.",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1,9 +1,9 @@
|
||||
import IconCard from "../../app/components/cards/IconCard";
|
||||
import { getAssetPath } from "../../lib/assetUtils";
|
||||
import Icon from "../../app/components/cards/Icon";
|
||||
import { getAssetPath, vectorMarkPath } from "../../lib/assetUtils";
|
||||
|
||||
export default {
|
||||
title: "Components/Cards/IconCard",
|
||||
component: IconCard,
|
||||
title: "Components/Cards/Icon",
|
||||
component: Icon,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
docs: {
|
||||
@@ -34,7 +34,7 @@ export default {
|
||||
// Worker's Coop icon
|
||||
const WorkerCoopIcon = () => (
|
||||
<img
|
||||
src={getAssetPath("assets/Vector_WorkerCoop.svg")}
|
||||
src={getAssetPath(vectorMarkPath("worker-coop"))}
|
||||
alt=""
|
||||
className="w-[36px] h-[36px]"
|
||||
width="36"
|
||||
@@ -1,8 +1,8 @@
|
||||
import MiniCard from "../../app/components/cards/MiniCard";
|
||||
import Mini from "../../app/components/cards/Mini";
|
||||
|
||||
export default {
|
||||
title: "Components/Cards/MiniCard",
|
||||
component: MiniCard,
|
||||
title: "Components/Cards/Mini",
|
||||
component: Mini,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
},
|
||||
@@ -37,25 +37,25 @@ export const Default = {
|
||||
export const ColorVariants = {
|
||||
render: () => (
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<MiniCard
|
||||
<Mini
|
||||
backgroundColor="bg-[var(--color-surface-default-brand-royal)]"
|
||||
labelLine1="Decision-making"
|
||||
labelLine2="support"
|
||||
panelContent="assets/Feature_Support.png"
|
||||
/>
|
||||
<MiniCard
|
||||
<Mini
|
||||
backgroundColor="bg-[#D1FFE2]"
|
||||
labelLine1="Values alignment"
|
||||
labelLine2="exercises"
|
||||
panelContent="assets/Feature_Exercises.png"
|
||||
/>
|
||||
<MiniCard
|
||||
<Mini
|
||||
backgroundColor="bg-[#F4CAFF]"
|
||||
labelLine1="Membership"
|
||||
labelLine2="guidance"
|
||||
panelContent="assets/Feature_Guidance.png"
|
||||
/>
|
||||
<MiniCard
|
||||
<Mini
|
||||
backgroundColor="bg-[#CBDDFF]"
|
||||
labelLine1="Conflict resolution"
|
||||
labelLine2="tools"
|
||||
@@ -1,9 +1,9 @@
|
||||
import RuleCard from "../../app/components/cards/RuleCard";
|
||||
import Rule from "../../app/components/cards/Rule";
|
||||
import Image from "next/image";
|
||||
|
||||
export default {
|
||||
title: "Components/Cards/RuleCard",
|
||||
component: RuleCard,
|
||||
title: "Components/Cards/Rule",
|
||||
component: Rule,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
docs: {
|
||||
@@ -305,7 +305,7 @@ export const AllVariants = {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
render: (_args) => (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 max-w-4xl">
|
||||
<RuleCard
|
||||
<Rule
|
||||
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)]"
|
||||
@@ -320,7 +320,7 @@ export const AllVariants = {
|
||||
}
|
||||
onClick={() => console.log("Consensus clusters selected")}
|
||||
/>
|
||||
<RuleCard
|
||||
<Rule
|
||||
title="Consensus"
|
||||
description="Decisions that affect the group collectively should involve participation of all participants."
|
||||
backgroundColor="bg-[var(--color-surface-default-brand-rust)]"
|
||||
@@ -335,7 +335,7 @@ export const AllVariants = {
|
||||
}
|
||||
onClick={() => console.log("Consensus selected")}
|
||||
/>
|
||||
<RuleCard
|
||||
<Rule
|
||||
title="Elected Board"
|
||||
description="An elected board determines policies and organizes their implementation."
|
||||
backgroundColor="bg-[var(--color-surface-default-brand-red)]"
|
||||
@@ -350,7 +350,7 @@ export const AllVariants = {
|
||||
}
|
||||
onClick={() => console.log("Elected Board selected")}
|
||||
/>
|
||||
<RuleCard
|
||||
<Rule
|
||||
title="Petition"
|
||||
description="All participants can propose and vote on proposals for the group."
|
||||
backgroundColor="bg-[var(--color-surface-default-brand-teal)]"
|
||||
@@ -1,8 +1,8 @@
|
||||
import Card from "../../app/components/cards/Card";
|
||||
import Selection from "../../app/components/cards/Selection";
|
||||
|
||||
export default {
|
||||
title: "Components/Cards/Card",
|
||||
component: Card,
|
||||
title: "Components/Cards/Selection",
|
||||
component: Selection,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
docs: {
|
||||
@@ -104,7 +104,7 @@ export const AllVariants = {
|
||||
<p className="font-inter text-sm font-medium text-gray-600">
|
||||
Horizontal + Recommended
|
||||
</p>
|
||||
<Card
|
||||
<Selection
|
||||
label="Label"
|
||||
supportText="Members vote to resolve a dispute democratically."
|
||||
recommended={true}
|
||||
@@ -116,7 +116,7 @@ export const AllVariants = {
|
||||
<p className="font-inter text-sm font-medium text-gray-600">
|
||||
Horizontal + Selected
|
||||
</p>
|
||||
<Card
|
||||
<Selection
|
||||
label="Label"
|
||||
supportText="Members vote to resolve a dispute democratically."
|
||||
recommended={false}
|
||||
@@ -128,7 +128,7 @@ export const AllVariants = {
|
||||
<p className="font-inter text-sm font-medium text-gray-600">
|
||||
Vertical + Recommended
|
||||
</p>
|
||||
<Card
|
||||
<Selection
|
||||
label="Label"
|
||||
supportText="Invite-only"
|
||||
recommended={true}
|
||||
@@ -141,7 +141,7 @@ export const AllVariants = {
|
||||
<p className="font-inter text-sm font-medium text-gray-600">
|
||||
Vertical + Selected
|
||||
</p>
|
||||
<Card
|
||||
<Selection
|
||||
label="Label"
|
||||
supportText="Invite-only"
|
||||
recommended={false}
|
||||
@@ -1,14 +1,14 @@
|
||||
import NumberCard from "../../app/components/cards/NumberCard";
|
||||
import Step from "../../app/components/cards/Step";
|
||||
|
||||
export default {
|
||||
title: "Components/Cards/NumberCard",
|
||||
component: NumberCard,
|
||||
title: "Components/Cards/Step",
|
||||
component: Step,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
"Individual number card component that displays a step in a process with a numbered icon and descriptive text. Supports explicit size variants (Small, Medium, Large, XLarge) matching Figma designs, or responsive layouts when size is not specified.",
|
||||
"Figma Card / Step: numbered tile with descriptive text. Supports explicit size variants (small, medium, large, xlarge) matching Figma, or responsive layouts when size is not specified.",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -23,9 +23,9 @@ export default {
|
||||
},
|
||||
size: {
|
||||
control: { type: "select" },
|
||||
options: ["Small", "Medium", "Large", "XLarge", undefined],
|
||||
options: ["small", "medium", "large", "xlarge", undefined],
|
||||
description:
|
||||
"Explicit size variant matching Figma designs. If not specified, uses responsive breakpoints for backward compatibility.",
|
||||
"Explicit size variant matching Figma. If not specified, uses responsive breakpoints for backward compatibility.",
|
||||
},
|
||||
iconShape: {
|
||||
control: { type: "select" },
|
||||
@@ -129,34 +129,34 @@ export const AllSizes = {
|
||||
<div className="space-y-8">
|
||||
<div>
|
||||
<h3 className="mb-4 text-lg font-semibold">Small</h3>
|
||||
<NumberCard
|
||||
<Step
|
||||
number={1}
|
||||
text="Document how your community makes decisions"
|
||||
size="Small"
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="mb-4 text-lg font-semibold">Medium</h3>
|
||||
<NumberCard
|
||||
<Step
|
||||
number={2}
|
||||
text="Document how your community makes decisions"
|
||||
size="Medium"
|
||||
size="medium"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="mb-4 text-lg font-semibold">Large</h3>
|
||||
<NumberCard
|
||||
<Step
|
||||
number={3}
|
||||
text="Document how your community makes decisions"
|
||||
size="Large"
|
||||
size="large"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="mb-4 text-lg font-semibold">XLarge</h3>
|
||||
<NumberCard
|
||||
<Step
|
||||
number={1}
|
||||
text="Document how your community makes decisions"
|
||||
size="XLarge"
|
||||
size="xlarge"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -180,24 +180,16 @@ export const AllNumbers = {
|
||||
},
|
||||
render: (args) => (
|
||||
<div className="space-y-4">
|
||||
<NumberCard {...args} number={1} text="First step in the process" />
|
||||
<NumberCard
|
||||
{...args}
|
||||
number={2}
|
||||
text="Second step with different content"
|
||||
/>
|
||||
<NumberCard
|
||||
{...args}
|
||||
number={3}
|
||||
text="Third and final step of the workflow"
|
||||
/>
|
||||
<Step {...args} number={1} text="First step in the process" />
|
||||
<Step {...args} number={2} text="Second step with different content" />
|
||||
<Step {...args} number={3} text="Third and final step of the workflow" />
|
||||
</div>
|
||||
),
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story:
|
||||
"Shows all three numbered cards with different content to demonstrate the visual hierarchy.",
|
||||
"Shows three Step tiles with different content to demonstrate the visual hierarchy.",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -42,11 +42,11 @@ export default {
|
||||
size: {
|
||||
control: "select",
|
||||
options: ["XS", "S", "M", "L"],
|
||||
description: "RuleCard size variant",
|
||||
description: "Rule size variant",
|
||||
},
|
||||
ruleCardClassName: {
|
||||
control: "text",
|
||||
description: "Class names merged onto the inner RuleCard",
|
||||
description: "Class names merged onto the inner Rule",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import InfoMessageBox from "../../app/components/utility/InfoMessageBox";
|
||||
import InfoMessageBox from "../../app/components/controls/InfoMessageBox";
|
||||
|
||||
export default {
|
||||
title: "Components/Utility/InfoMessageBox",
|
||||
title: "Components/Controls/InfoMessageBox",
|
||||
component: InfoMessageBox,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
+23
-4
@@ -1,15 +1,20 @@
|
||||
import DecisionMakingSidebar from "../../app/components/utility/DecisionMakingSidebar";
|
||||
import React from "react";
|
||||
import HeaderLockup from "../../app/components/type/HeaderLockup";
|
||||
import InfoMessageBox from "../../app/components/controls/InfoMessageBox";
|
||||
|
||||
/**
|
||||
* Compose pattern used by create-flow “decision approaches” rail: headline lockup
|
||||
* plus bordered checklist — no standalone wrapper component.
|
||||
*/
|
||||
export default {
|
||||
title: "Components/Utility/DecisionMakingSidebar",
|
||||
component: DecisionMakingSidebar,
|
||||
title: "Components/Controls/Rail header (lockup + info box)",
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
backgrounds: { default: "dark" },
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
"HeaderLockup + InfoMessageBox for decision-making step sidebars.",
|
||||
"`HeaderLockup` stacked with `InfoMessageBox` — same chrome as decision-approaches step sidebars.",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -28,7 +33,20 @@ const messageItems = [
|
||||
{ id: "c2", label: "Majority vote" },
|
||||
];
|
||||
|
||||
const compose = (args) => (
|
||||
<div className="flex w-full min-w-0 flex-col gap-3">
|
||||
<HeaderLockup
|
||||
title={args.title}
|
||||
description={args.description}
|
||||
size={args.size}
|
||||
justification={args.justification}
|
||||
/>
|
||||
<InfoMessageBox title={args.messageBoxTitle} items={args.messageBoxItems} />
|
||||
</div>
|
||||
);
|
||||
|
||||
export const Default = {
|
||||
render: compose,
|
||||
args: {
|
||||
title: "How does your group make decisions?",
|
||||
description:
|
||||
@@ -41,6 +59,7 @@ export const Default = {
|
||||
};
|
||||
|
||||
export const Medium = {
|
||||
render: compose,
|
||||
args: {
|
||||
title: "Decision-making",
|
||||
description: "Short description.",
|
||||
@@ -1,7 +1,7 @@
|
||||
import ModalFooter from "../../app/components/utility/ModalFooter";
|
||||
import ModalFooter from "../../app/components/modals/ModalFooter";
|
||||
|
||||
export default {
|
||||
title: "Components/Utility/ModalFooter",
|
||||
title: "Components/Modals/ModalFooter",
|
||||
component: ModalFooter,
|
||||
parameters: {
|
||||
layout: "fullscreen",
|
||||
@@ -1,7 +1,7 @@
|
||||
import ModalHeader from "../../app/components/utility/ModalHeader";
|
||||
import ModalHeader from "../../app/components/modals/ModalHeader";
|
||||
|
||||
export default {
|
||||
title: "Components/Utility/ModalHeader",
|
||||
title: "Components/Modals/ModalHeader",
|
||||
component: ModalHeader,
|
||||
parameters: {
|
||||
layout: "fullscreen",
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
import CreateFlowFooter from "../../app/components/utility/CreateFlowFooter";
|
||||
import CreateFlowFooter from "../../app/components/navigation/CreateFlowFooter";
|
||||
import Button from "../../app/components/buttons/Button";
|
||||
|
||||
export default {
|
||||
title: "Components/Utility/CreateFlowFooter",
|
||||
title: "Components/Navigation/CreateFlowFooter",
|
||||
component: CreateFlowFooter,
|
||||
parameters: {
|
||||
layout: "fullscreen",
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import CreateFlowTopNav from "../../app/components/utility/CreateFlowTopNav";
|
||||
import CreateFlowTopNav from "../../app/components/navigation/CreateFlowTopNav";
|
||||
|
||||
export default {
|
||||
title: "Components/Utility/CreateFlowTopNav",
|
||||
title: "Components/Navigation/CreateFlowTopNav",
|
||||
component: CreateFlowTopNav,
|
||||
parameters: {
|
||||
layout: "fullscreen",
|
||||
@@ -0,0 +1,101 @@
|
||||
import Menu from "../../app/components/navigation/Menu";
|
||||
import MenuItem from "../../app/components/navigation/MenuItem";
|
||||
|
||||
export default {
|
||||
title: "Components/Navigation/Menu",
|
||||
component: Menu,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
"Navigation Menu (`role=\"menubar\"`) groups MenuItem children. Consistent spacing and layout for horizontal nav clusters with multiple size variants.",
|
||||
},
|
||||
},
|
||||
},
|
||||
argTypes: {
|
||||
size: {
|
||||
control: { type: "select" },
|
||||
options: ["X Small", "Small", "Medium", "Large", "X Large"],
|
||||
description: "The size of the menu and its children",
|
||||
},
|
||||
className: {
|
||||
control: { type: "text" },
|
||||
description: "Additional CSS classes",
|
||||
},
|
||||
},
|
||||
tags: ["autodocs"],
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
args: {
|
||||
size: "Small",
|
||||
},
|
||||
render: (args) => (
|
||||
<Menu {...args}>
|
||||
<MenuItem size="Large">Home</MenuItem>
|
||||
<MenuItem size="Large">About</MenuItem>
|
||||
<MenuItem size="Large">Contact</MenuItem>
|
||||
</Menu>
|
||||
),
|
||||
};
|
||||
|
||||
export const Sizes = {
|
||||
args: {},
|
||||
render: () => (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="text-white font-semibold mb-3">X Small Size</h3>
|
||||
<Menu size="X Small">
|
||||
<MenuItem size="X Small">Home</MenuItem>
|
||||
<MenuItem size="X Small">About</MenuItem>
|
||||
<MenuItem size="X Small">Contact</MenuItem>
|
||||
</Menu>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-white font-semibold mb-3">Small Size</h3>
|
||||
<Menu size="Small">
|
||||
<MenuItem size="Large">Home</MenuItem>
|
||||
<MenuItem size="Large">About</MenuItem>
|
||||
<MenuItem size="Large">Contact</MenuItem>
|
||||
</Menu>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-white font-semibold mb-3">Medium Size</h3>
|
||||
<Menu size="Medium">
|
||||
<MenuItem size="Large">Home</MenuItem>
|
||||
<MenuItem size="Large">About</MenuItem>
|
||||
<MenuItem size="Large">Contact</MenuItem>
|
||||
</Menu>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-white font-semibold mb-3">Large Size</h3>
|
||||
<Menu size="Large">
|
||||
<MenuItem size="Large">Home</MenuItem>
|
||||
<MenuItem size="Large">About</MenuItem>
|
||||
<MenuItem size="Large">Contact</MenuItem>
|
||||
</Menu>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-white font-semibold mb-3">X Large Size</h3>
|
||||
<Menu size="X Large">
|
||||
<MenuItem size="X Large">Home</MenuItem>
|
||||
<MenuItem size="X Large">About</MenuItem>
|
||||
<MenuItem size="X Large">Contact</MenuItem>
|
||||
</Menu>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story:
|
||||
"Different size variants of the menu with consistent spacing and layout.",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,101 +0,0 @@
|
||||
import MenuBar from "../../app/components/navigation/MenuBar";
|
||||
import MenuBarItem from "../../app/components/navigation/MenuBarItem";
|
||||
|
||||
export default {
|
||||
title: "Components/Navigation/MenuBar",
|
||||
component: MenuBar,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
"A navigation menu bar container that groups MenuBarItem components together. Provides consistent spacing and layout for navigation menus with multiple size variants.",
|
||||
},
|
||||
},
|
||||
},
|
||||
argTypes: {
|
||||
size: {
|
||||
control: { type: "select" },
|
||||
options: ["X Small", "Small", "Medium", "Large", "X Large"],
|
||||
description: "The size of the menu bar and its children",
|
||||
},
|
||||
className: {
|
||||
control: { type: "text" },
|
||||
description: "Additional CSS classes",
|
||||
},
|
||||
},
|
||||
tags: ["autodocs"],
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
args: {
|
||||
size: "Small",
|
||||
},
|
||||
render: (args) => (
|
||||
<MenuBar {...args}>
|
||||
<MenuBarItem size="Large">Home</MenuBarItem>
|
||||
<MenuBarItem size="Large">About</MenuBarItem>
|
||||
<MenuBarItem size="Large">Contact</MenuBarItem>
|
||||
</MenuBar>
|
||||
),
|
||||
};
|
||||
|
||||
export const Sizes = {
|
||||
args: {},
|
||||
render: () => (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="text-white font-semibold mb-3">X Small Size</h3>
|
||||
<MenuBar size="X Small">
|
||||
<MenuBarItem size="X Small">Home</MenuBarItem>
|
||||
<MenuBarItem size="X Small">About</MenuBarItem>
|
||||
<MenuBarItem size="X Small">Contact</MenuBarItem>
|
||||
</MenuBar>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-white font-semibold mb-3">Small Size</h3>
|
||||
<MenuBar size="Small">
|
||||
<MenuBarItem size="Large">Home</MenuBarItem>
|
||||
<MenuBarItem size="Large">About</MenuBarItem>
|
||||
<MenuBarItem size="Large">Contact</MenuBarItem>
|
||||
</MenuBar>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-white font-semibold mb-3">Medium Size</h3>
|
||||
<MenuBar size="Medium">
|
||||
<MenuBarItem size="Large">Home</MenuBarItem>
|
||||
<MenuBarItem size="Large">About</MenuBarItem>
|
||||
<MenuBarItem size="Large">Contact</MenuBarItem>
|
||||
</MenuBar>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-white font-semibold mb-3">Large Size</h3>
|
||||
<MenuBar size="Large">
|
||||
<MenuBarItem size="Large">Home</MenuBarItem>
|
||||
<MenuBarItem size="Large">About</MenuBarItem>
|
||||
<MenuBarItem size="Large">Contact</MenuBarItem>
|
||||
</MenuBar>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-white font-semibold mb-3">X Large Size</h3>
|
||||
<MenuBar size="X Large">
|
||||
<MenuBarItem size="X Large">Home</MenuBarItem>
|
||||
<MenuBarItem size="X Large">About</MenuBarItem>
|
||||
<MenuBarItem size="X Large">Contact</MenuBarItem>
|
||||
</MenuBar>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story:
|
||||
"Different size variants of the menu bar with consistent spacing and layout.",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
+37
-37
@@ -1,14 +1,14 @@
|
||||
import MenuBarItem from "../../app/components/navigation/MenuBarItem";
|
||||
import MenuItem from "../../app/components/navigation/MenuItem";
|
||||
|
||||
export default {
|
||||
title: "Components/Navigation/MenuBarItem",
|
||||
component: MenuBarItem,
|
||||
title: "Components/Navigation/MenuItem",
|
||||
component: MenuItem,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
"A navigation menu item component with multiple variants, sizes, and states. Can render as a link or disabled span with full accessibility support. Includes focus states with keyboard navigation - use Tab key to test focus indicators.",
|
||||
"A navigation menu item with multiple variants, sizes, and states. Renders as a link or button (or disabled span) with accessibility support. Use Tab to test focus indicators.",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -51,12 +51,12 @@ export const Modes = {
|
||||
render: (args) => (
|
||||
<div className="space-y-4">
|
||||
<div className="space-x-4">
|
||||
<MenuBarItem {...args} mode="default">
|
||||
<MenuItem {...args} mode="default">
|
||||
Default
|
||||
</MenuBarItem>
|
||||
<MenuBarItem {...args} mode="inverse">
|
||||
</MenuItem>
|
||||
<MenuItem {...args} mode="inverse">
|
||||
Inverse
|
||||
</MenuBarItem>
|
||||
</MenuItem>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
@@ -77,21 +77,21 @@ export const Sizes = {
|
||||
render: (args) => (
|
||||
<div className="space-y-4">
|
||||
<div className="space-x-4">
|
||||
<MenuBarItem {...args} size="X Small">
|
||||
<MenuItem {...args} size="X Small">
|
||||
X Small
|
||||
</MenuBarItem>
|
||||
<MenuBarItem {...args} size="Small">
|
||||
</MenuItem>
|
||||
<MenuItem {...args} size="Small">
|
||||
Small
|
||||
</MenuBarItem>
|
||||
<MenuBarItem {...args} size="Medium">
|
||||
</MenuItem>
|
||||
<MenuItem {...args} size="Medium">
|
||||
Medium
|
||||
</MenuBarItem>
|
||||
<MenuBarItem {...args} size="Large">
|
||||
</MenuItem>
|
||||
<MenuItem {...args} size="Large">
|
||||
Large
|
||||
</MenuBarItem>
|
||||
<MenuBarItem {...args} size="X Large">
|
||||
</MenuItem>
|
||||
<MenuItem {...args} size="X Large">
|
||||
X Large
|
||||
</MenuBarItem>
|
||||
</MenuItem>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
@@ -113,10 +113,10 @@ export const States = {
|
||||
render: (args) => (
|
||||
<div className="space-y-4">
|
||||
<div className="space-x-4">
|
||||
<MenuBarItem {...args}>Normal</MenuBarItem>
|
||||
<MenuBarItem {...args} disabled>
|
||||
<MenuItem {...args}>Normal</MenuItem>
|
||||
<MenuItem {...args} disabled>
|
||||
Disabled
|
||||
</MenuBarItem>
|
||||
</MenuItem>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
@@ -136,42 +136,42 @@ export const AllModes = {
|
||||
<div>
|
||||
<h3 className="text-white font-semibold mb-3">Default Mode</h3>
|
||||
<div className="space-x-4">
|
||||
<MenuBarItem size="X Small" mode="default">
|
||||
<MenuItem size="X Small" mode="default">
|
||||
X Small
|
||||
</MenuBarItem>
|
||||
<MenuBarItem size="Large" mode="default">
|
||||
</MenuItem>
|
||||
<MenuItem size="Large" mode="default">
|
||||
Large
|
||||
</MenuBarItem>
|
||||
<MenuBarItem size="X Large" mode="default">
|
||||
</MenuItem>
|
||||
<MenuItem size="X Large" mode="default">
|
||||
X Large
|
||||
</MenuBarItem>
|
||||
</MenuItem>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-white font-semibold mb-3">Inverse Mode</h3>
|
||||
<div className="space-x-4">
|
||||
<MenuBarItem mode="inverse" size="X Small">
|
||||
<MenuItem mode="inverse" size="X Small">
|
||||
X Small
|
||||
</MenuBarItem>
|
||||
<MenuBarItem mode="inverse" size="Large">
|
||||
</MenuItem>
|
||||
<MenuItem mode="inverse" size="Large">
|
||||
Large
|
||||
</MenuBarItem>
|
||||
<MenuBarItem mode="inverse" size="X Large">
|
||||
</MenuItem>
|
||||
<MenuItem mode="inverse" size="X Large">
|
||||
X Large
|
||||
</MenuBarItem>
|
||||
</MenuItem>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-white font-semibold mb-3">Disabled States</h3>
|
||||
<div className="space-x-4">
|
||||
<MenuBarItem size="Large" mode="default" disabled>
|
||||
<MenuItem size="Large" mode="default" disabled>
|
||||
Default Disabled
|
||||
</MenuBarItem>
|
||||
<MenuBarItem mode="inverse" size="Large" disabled>
|
||||
</MenuItem>
|
||||
<MenuItem mode="inverse" size="Large" disabled>
|
||||
Inverse Disabled
|
||||
</MenuBarItem>
|
||||
</MenuItem>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,8 +1,8 @@
|
||||
import TopNav from "../../app/components/navigation/TopNav";
|
||||
import Top from "../../app/components/navigation/Top";
|
||||
|
||||
export default {
|
||||
title: "Components/Navigation/TopNav",
|
||||
component: TopNav,
|
||||
title: "Components/Navigation/Top",
|
||||
component: Top,
|
||||
parameters: {
|
||||
layout: "fullscreen",
|
||||
docs: {
|
||||
@@ -117,7 +117,7 @@ export const StandardInPageContext = {
|
||||
},
|
||||
render: (args) => (
|
||||
<div className="min-h-screen bg-[var(--color-surface-default-primary)]">
|
||||
<TopNav {...args} />
|
||||
<Top {...args} />
|
||||
<main className="p-8">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h1 className="text-2xl font-bold text-white mb-4">
|
||||
@@ -168,7 +168,7 @@ export const HomePageInContext = {
|
||||
},
|
||||
render: (args) => (
|
||||
<div className="min-h-screen bg-gradient-to-b from-[var(--color-surface-default-primary)] to-[var(--color-surface-default-secondary)]">
|
||||
<TopNav {...args} />
|
||||
<Top {...args} />
|
||||
<main className="p-8">
|
||||
<div className="max-w-4xl mx-auto text-center">
|
||||
<h1 className="text-4xl font-bold text-white mb-4">
|
||||
@@ -28,7 +28,7 @@ export default {
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
"Completed flow: teal background, inverse HeaderLockup, CommunityRule document, optional bottom toast.",
|
||||
"Completed flow: teal background, inverse HeaderLockup, CommunityRule body, optional bottom toast.",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -8,7 +8,7 @@ export default {
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
"Pre-finalize review: HeaderLockup + expanded RuleCard sections.",
|
||||
"Pre-finalize review: HeaderLockup + expanded Rule sections.",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
import NumberedCards from "../../app/components/sections/NumberedCards";
|
||||
import CardSteps from "../../app/components/sections/CardSteps";
|
||||
|
||||
export default {
|
||||
title: "Components/Sections/NumberedCards",
|
||||
component: NumberedCards,
|
||||
title: "Components/Sections/CardSteps",
|
||||
component: CardSteps,
|
||||
parameters: {
|
||||
layout: "fullscreen",
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
"A component system for visually communicating multi-step workflows, processes, or value propositions. The component's modular design with NumberCard and SectionNumber sub-components makes it ideal for explaining any sequential process while maintaining brand consistency and accessibility standards across the design system.",
|
||||
"Marketing section (Figma SectionCardSteps) that composes **cards/Step** tiles with a section header and CTA. Use for sequential explainers on the home page and similar surfaces.",
|
||||
},
|
||||
},
|
||||
},
|
||||
argTypes: {
|
||||
title: {
|
||||
control: { type: "text" },
|
||||
description: "The main title for the section",
|
||||
description: "The main title for the section (mobile single line)",
|
||||
},
|
||||
subtitle: {
|
||||
control: { type: "text" },
|
||||
description: "The subtitle text below the main title",
|
||||
description: "Supporting text beside / below the title on large screens",
|
||||
},
|
||||
cards: {
|
||||
steps: {
|
||||
control: { type: "object" },
|
||||
description:
|
||||
"Array of card objects with text, iconShape, and iconColor properties",
|
||||
"Items rendered as **Step** cards (text, optional iconShape, iconColor)",
|
||||
},
|
||||
},
|
||||
tags: ["autodocs"],
|
||||
@@ -34,7 +34,8 @@ export const Default = {
|
||||
args: {
|
||||
title: "How CommunityRule works",
|
||||
subtitle: "Here's a quick overview of the process, from start to finish.",
|
||||
cards: [
|
||||
headingDesktopLines: ["How", "CommunityRule", "helps"],
|
||||
steps: [
|
||||
{
|
||||
text: "Document how your community makes decisions",
|
||||
iconShape: "blob",
|
||||
@@ -58,7 +59,7 @@ export const CustomContent = {
|
||||
args: {
|
||||
title: "Our Process",
|
||||
subtitle: "Follow these simple steps to get started with your project.",
|
||||
cards: [
|
||||
steps: [
|
||||
{
|
||||
text: "Define your project requirements and goals",
|
||||
iconShape: "blob",
|
||||
@@ -85,7 +86,7 @@ export const CustomContent = {
|
||||
docs: {
|
||||
description: {
|
||||
story:
|
||||
"Example with custom content and four cards to show flexibility.",
|
||||
"Example with custom content and four **Step** tiles to show flexibility.",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1,58 +0,0 @@
|
||||
import CommunityRuleDocument from "../../app/components/sections/CommunityRuleDocument";
|
||||
|
||||
const sampleSections = [
|
||||
{
|
||||
categoryName: "Decision making",
|
||||
entries: [
|
||||
{
|
||||
title: "How proposals pass",
|
||||
body: "Important decisions require unanimous agreement. Proposals pass only if no serious objections remain.",
|
||||
},
|
||||
{
|
||||
title: "Blocks",
|
||||
body: "Anyone with a serious objection may block consensus and require further discussion.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
categoryName: "Membership",
|
||||
entries: [
|
||||
{
|
||||
title: "Joining",
|
||||
body: "New members are welcomed by consensus of existing members.",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default {
|
||||
title: "Components/Sections/CommunityRuleDocument",
|
||||
component: CommunityRuleDocument,
|
||||
parameters: {
|
||||
layout: "padded",
|
||||
},
|
||||
argTypes: {
|
||||
sections: {
|
||||
control: false,
|
||||
description: "Document sections, each with a categoryName and entries.",
|
||||
},
|
||||
useCardStyle: {
|
||||
control: "boolean",
|
||||
description: "When true, wraps the document in a white card with a teal bar",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
args: {
|
||||
sections: sampleSections,
|
||||
useCardStyle: false,
|
||||
},
|
||||
};
|
||||
|
||||
export const CardStyle = {
|
||||
args: {
|
||||
sections: sampleSections,
|
||||
useCardStyle: true,
|
||||
},
|
||||
};
|
||||
@@ -14,7 +14,7 @@ A responsive feature grid component that displays organizational tools and servi
|
||||
|
||||
- **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
|
||||
- **Mini grid**: Four feature tiles 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
|
||||
|
||||
@@ -26,7 +26,7 @@ A responsive feature grid component that displays organizational tools and servi
|
||||
|
||||
## Interactive Elements
|
||||
|
||||
- **MiniCards**: Hover effects, focus indicators, and keyboard navigation
|
||||
- **Mini tiles**: 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
|
||||
|
||||
@@ -69,7 +69,7 @@ export const Default = {
|
||||
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
|
||||
- **Mini grid**: Four feature tiles 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
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ export default {
|
||||
argTypes: {
|
||||
entries: {
|
||||
control: false,
|
||||
description: "Catalog entries to render as a 2-column grid of RuleCards",
|
||||
description: "Catalog entries to render as a 2-column grid of Rules",
|
||||
},
|
||||
onTemplateClick: { action: "template-clicked" },
|
||||
},
|
||||
|
||||
@@ -44,7 +44,7 @@ export default {
|
||||
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" +
|
||||
"A complete template library component that displays governance patterns in a responsive grid layout. Composes **`type/SectionHeader`** (multi-line variant), interactive **`Rule`** cards, 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" +
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
import CommunityRule from "../../app/components/type/CommunityRule";
|
||||
|
||||
const sampleSections = [
|
||||
{
|
||||
categoryName: "Decision making",
|
||||
entries: [
|
||||
{
|
||||
title: "How proposals pass",
|
||||
body: "Short opener line.\n\nImportant decisions require unanimous agreement. Proposals pass only if no serious objections remain.",
|
||||
},
|
||||
{
|
||||
title: "Blocks",
|
||||
body: "Anyone with a serious objection may block consensus and require further discussion.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
categoryName: "Membership",
|
||||
entries: [
|
||||
{
|
||||
title: "Joining",
|
||||
body: "New members are welcomed by consensus of existing members.",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default {
|
||||
title: "Components/Type/CommunityRule",
|
||||
component: CommunityRule,
|
||||
parameters: {
|
||||
layout: "padded",
|
||||
},
|
||||
argTypes: {
|
||||
sections: {
|
||||
control: false,
|
||||
description: "Rule sections, each with a categoryName and entries.",
|
||||
},
|
||||
useCardStyle: {
|
||||
control: "boolean",
|
||||
description: "When true, wraps the rule body in a white card with a teal bar",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
args: {
|
||||
sections: sampleSections,
|
||||
useCardStyle: false,
|
||||
},
|
||||
};
|
||||
|
||||
export const WithLabeledBlocks = {
|
||||
args: {
|
||||
sections: [
|
||||
{
|
||||
categoryName: "Membership",
|
||||
entries: [
|
||||
{
|
||||
title: "Consensus or vote-based approval",
|
||||
body: "",
|
||||
blocks: [
|
||||
{
|
||||
label: "Eligibility & philosophy",
|
||||
body: "Access to critical resources is restricted to safeguard the project.",
|
||||
},
|
||||
{
|
||||
label: "Joining process",
|
||||
body: "Volunteers who have completed two full distributions can submit a request.",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
useCardStyle: false,
|
||||
},
|
||||
};
|
||||
|
||||
export const CardStyle = {
|
||||
args: {
|
||||
sections: sampleSections,
|
||||
useCardStyle: true,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,56 @@
|
||||
import Section from "../../app/components/type/Section";
|
||||
import TextBlock from "../../app/components/type/TextBlock";
|
||||
|
||||
export default {
|
||||
title: "Components/Type/Section",
|
||||
component: Section,
|
||||
parameters: { layout: "padded" },
|
||||
argTypes: {
|
||||
categoryName: { control: "text" },
|
||||
showRail: { control: "boolean" },
|
||||
children: { control: false },
|
||||
},
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
args: {
|
||||
categoryName: "Values",
|
||||
showRail: true,
|
||||
children: (
|
||||
<>
|
||||
<TextBlock
|
||||
title="Solidarity Forever"
|
||||
body={`“Change needs all of us.”
|
||||
|
||||
Food Not Bombs is not a charity. It is a project of solidarity.`}
|
||||
/>
|
||||
<TextBlock
|
||||
title="Shared Leadership"
|
||||
body="Everyone coordinates, no one controls."
|
||||
/>
|
||||
</>
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
export const WithoutRail = {
|
||||
args: {
|
||||
categoryName: "Membership",
|
||||
showRail: false,
|
||||
children: (
|
||||
<TextBlock
|
||||
title="Open access"
|
||||
rows={[
|
||||
{
|
||||
label: "Eligibility & philosophy",
|
||||
body: "Anyone aligned with the mission may join.",
|
||||
},
|
||||
{
|
||||
label: "Process",
|
||||
body: "Complete two orientations, then lazy consensus.",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
),
|
||||
},
|
||||
};
|
||||
@@ -1,36 +1,35 @@
|
||||
import SectionHeader from "../../app/components/sections/SectionHeader";
|
||||
import SectionHeader from "../../app/components/type/SectionHeader";
|
||||
|
||||
export default {
|
||||
title: "Components/Sections/SectionHeader",
|
||||
title: "Components/Type/SectionHeader",
|
||||
component: SectionHeader,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
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. Includes 'default' and 'multi-line' variants with different layout behaviors.",
|
||||
"Figma Type / SectionHeader ([17411:10981](https://www.figma.com/design/agv0VBLiBlcnSAaiAORgPR/Community-Rule-System?node-id=17411-10981)). Title + subtitle with responsive typography: stacked on small screens, split row from lg. **`default`**: top-aligned row; **`multi-line`**: vertically centered row on large screens (subtitle vs. title). Optional **`stackedDesktopLines`** for three-line desktop titles (CardSteps).",
|
||||
},
|
||||
},
|
||||
},
|
||||
argTypes: {
|
||||
title: {
|
||||
control: { type: "text" },
|
||||
description: "The main title text (used for xsm and sm breakpoints)",
|
||||
description: "Title for small viewports (and mobile/stacked layout)",
|
||||
},
|
||||
subtitle: {
|
||||
control: { type: "text" },
|
||||
description: "The subtitle text below the main title",
|
||||
description: "Subtitle / supporting copy",
|
||||
},
|
||||
titleLg: {
|
||||
control: { type: "text" },
|
||||
description:
|
||||
"The title text for lg and xl breakpoints (optional, falls back to title)",
|
||||
"Optional single-line title from lg up (when `stackedDesktopLines` is not set)",
|
||||
},
|
||||
variant: {
|
||||
control: { type: "select" },
|
||||
options: ["default", "multi-line"],
|
||||
description:
|
||||
"The layout variant - 'default' for traditional layout, 'multi-line' for 50/50 split layout",
|
||||
description: "Layout variant (Figma 1-line vs 3-line row behavior)",
|
||||
},
|
||||
},
|
||||
tags: ["autodocs"],
|
||||
@@ -56,7 +55,24 @@ export const MultiLine = {
|
||||
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.",
|
||||
"Used in **RuleStack**: 50/50 row from lg with subtitle vertically centered against the title block.",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const MultiLineStackedTitle = {
|
||||
args: {
|
||||
title: "How CommunityRule works",
|
||||
subtitle: "Here's a quick overview of the process, from start to finish.",
|
||||
variant: "multi-line",
|
||||
stackedDesktopLines: ["How", "CommunityRule", "helps"],
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story:
|
||||
"Used in **CardSteps**: three-line Bricolage lockup on large screens with `stackedDesktopLines`.",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -0,0 +1,35 @@
|
||||
import TextBlock from "../../app/components/type/TextBlock";
|
||||
|
||||
export default {
|
||||
title: "Components/Type/TextBlock",
|
||||
component: TextBlock,
|
||||
parameters: { layout: "padded" },
|
||||
argTypes: {
|
||||
title: { control: "text" },
|
||||
body: { control: "text" },
|
||||
rows: { control: false },
|
||||
},
|
||||
};
|
||||
|
||||
export const PlainBody = {
|
||||
args: {
|
||||
title: "Solidarity Forever",
|
||||
body: "First paragraph line.\n\nSecond paragraph with more detail.",
|
||||
},
|
||||
};
|
||||
|
||||
export const LabeledRows = {
|
||||
args: {
|
||||
title: "Consensus or vote-based approval",
|
||||
rows: [
|
||||
{
|
||||
label: "Eligibility & philosophy",
|
||||
body: "Access to critical resources is restricted to safeguard the project.",
|
||||
},
|
||||
{
|
||||
label: "Joining process",
|
||||
body: "Volunteers who have completed two full distributions can submit a request.",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
@@ -1,28 +0,0 @@
|
||||
import Separator from "../../app/components/utility/Separator";
|
||||
|
||||
export default {
|
||||
title: "Components/Utility/Separator",
|
||||
component: Separator,
|
||||
parameters: {
|
||||
layout: "padded",
|
||||
},
|
||||
argTypes: {},
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
render: () => (
|
||||
<div style={{ width: 320 }}>
|
||||
<Separator />
|
||||
</div>
|
||||
),
|
||||
};
|
||||
|
||||
export const InContext = {
|
||||
render: () => (
|
||||
<div style={{ width: 320, display: "flex", flexDirection: "column", gap: 12 }}>
|
||||
<p>Above the separator</p>
|
||||
<Separator />
|
||||
<p>Below the separator</p>
|
||||
</div>
|
||||
),
|
||||
};
|
||||
Reference in New Issue
Block a user