App reorganization
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import React, { useState } from "react";
|
||||
import ContextMenu from "../../app/components/ContextMenu/ContextMenu";
|
||||
import ContextMenuItem from "../../app/components/ContextMenu/ContextMenuItem";
|
||||
import ContextMenuSection from "../../app/components/ContextMenu/ContextMenuSection";
|
||||
import ContextMenuDivider from "../../app/components/ContextMenu/ContextMenuDivider";
|
||||
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",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import WebVitalsDashboard from "../app/components/WebVitalsDashboard";
|
||||
import WebVitalsDashboard from "../app/components/sections/WebVitalsDashboard";
|
||||
|
||||
export default {
|
||||
title: "Components/WebVitalsDashboard",
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import { Icon } from "../../app/components/asset";
|
||||
|
||||
export default {
|
||||
title: "Components/Asset/Icon",
|
||||
component: Icon,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
},
|
||||
argTypes: {
|
||||
name: {
|
||||
control: "select",
|
||||
options: ["exclamation"],
|
||||
description: "Name of the icon to render",
|
||||
},
|
||||
size: {
|
||||
control: { type: "number", min: 12, max: 96, step: 4 },
|
||||
description: "Width and height in pixels",
|
||||
},
|
||||
className: {
|
||||
control: "text",
|
||||
description: "Optional className applied to the SVG",
|
||||
},
|
||||
"aria-hidden": {
|
||||
control: "boolean",
|
||||
description: "Whether to mark the icon as aria-hidden",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
args: {
|
||||
name: "exclamation",
|
||||
size: 24,
|
||||
},
|
||||
};
|
||||
|
||||
export const Large = {
|
||||
args: {
|
||||
name: "exclamation",
|
||||
size: 48,
|
||||
},
|
||||
};
|
||||
@@ -56,7 +56,7 @@ export const Small = {
|
||||
args: {
|
||||
number: 1,
|
||||
text: "Document how your community makes decisions",
|
||||
size: "Small",
|
||||
size: "small",
|
||||
iconShape: "blob",
|
||||
iconColor: "green",
|
||||
},
|
||||
@@ -74,7 +74,7 @@ export const Medium = {
|
||||
args: {
|
||||
number: 1,
|
||||
text: "Document how your community makes decisions",
|
||||
size: "Medium",
|
||||
size: "medium",
|
||||
iconShape: "blob",
|
||||
iconColor: "green",
|
||||
},
|
||||
@@ -92,7 +92,7 @@ export const Large = {
|
||||
args: {
|
||||
number: 1,
|
||||
text: "Document how your community makes decisions",
|
||||
size: "Large",
|
||||
size: "large",
|
||||
iconShape: "blob",
|
||||
iconColor: "green",
|
||||
},
|
||||
@@ -110,7 +110,7 @@ export const XLarge = {
|
||||
args: {
|
||||
number: 1,
|
||||
text: "Document how your community makes decisions",
|
||||
size: "XLarge",
|
||||
size: "xlarge",
|
||||
iconShape: "blob",
|
||||
iconColor: "green",
|
||||
},
|
||||
|
||||
@@ -82,11 +82,11 @@ export const Expanded = {
|
||||
{
|
||||
name: "Values",
|
||||
chipOptions: [
|
||||
{ id: "values-1", label: "Consciousness", state: "Unselected" },
|
||||
{ id: "values-2", label: "Ecology", state: "Unselected" },
|
||||
{ id: "values-3", label: "Abundance", state: "Unselected" },
|
||||
{ id: "values-4", label: "Art", state: "Unselected" },
|
||||
{ id: "values-5", label: "Decisiveness", state: "Unselected" },
|
||||
{ id: "values-1", label: "Consciousness", state: "unselected" },
|
||||
{ id: "values-2", label: "Ecology", state: "unselected" },
|
||||
{ id: "values-3", label: "Abundance", state: "unselected" },
|
||||
{ id: "values-4", label: "Art", state: "unselected" },
|
||||
{ id: "values-5", label: "Decisiveness", state: "unselected" },
|
||||
],
|
||||
onChipClick: (categoryName, chipId) => {
|
||||
console.log(`Chip clicked: ${categoryName} - ${chipId}`);
|
||||
@@ -97,7 +97,7 @@ export const Expanded = {
|
||||
},
|
||||
{
|
||||
name: "Communication",
|
||||
chipOptions: [{ id: "comm-1", label: "Signal", state: "Unselected" }],
|
||||
chipOptions: [{ id: "comm-1", label: "Signal", state: "unselected" }],
|
||||
onChipClick: (categoryName, chipId) => {
|
||||
console.log(`Chip clicked: ${categoryName} - ${chipId}`);
|
||||
},
|
||||
@@ -108,7 +108,7 @@ export const Expanded = {
|
||||
{
|
||||
name: "Membership",
|
||||
chipOptions: [
|
||||
{ id: "membership-1", label: "Open Admission", state: "Unselected" },
|
||||
{ id: "membership-1", label: "Open Admission", state: "unselected" },
|
||||
],
|
||||
onChipClick: (categoryName, chipId) => {
|
||||
console.log(`Chip clicked: ${categoryName} - ${chipId}`);
|
||||
@@ -120,11 +120,11 @@ export const Expanded = {
|
||||
{
|
||||
name: "Decision-making",
|
||||
chipOptions: [
|
||||
{ id: "decision-1", label: "Lazy Consensus", state: "Unselected" },
|
||||
{ id: "decision-1", label: "Lazy Consensus", state: "unselected" },
|
||||
{
|
||||
id: "decision-2",
|
||||
label: "Modified Consensus",
|
||||
state: "Unselected",
|
||||
state: "unselected",
|
||||
},
|
||||
],
|
||||
onChipClick: (categoryName, chipId) => {
|
||||
@@ -137,11 +137,11 @@ export const Expanded = {
|
||||
{
|
||||
name: "Conflict management",
|
||||
chipOptions: [
|
||||
{ id: "conflict-1", label: "Code of Conduct", state: "Unselected" },
|
||||
{ id: "conflict-1", label: "Code of Conduct", state: "unselected" },
|
||||
{
|
||||
id: "conflict-2",
|
||||
label: "Restorative Justice",
|
||||
state: "Unselected",
|
||||
state: "unselected",
|
||||
},
|
||||
],
|
||||
onChipClick: (categoryName, chipId) => {
|
||||
@@ -246,42 +246,42 @@ export const ExpandedMedium = {
|
||||
{
|
||||
name: "Values",
|
||||
chipOptions: [
|
||||
{ id: "values-1", label: "Consciousness", state: "Unselected" },
|
||||
{ id: "values-2", label: "Ecology", state: "Unselected" },
|
||||
{ id: "values-3", label: "Abundance", state: "Unselected" },
|
||||
{ id: "values-4", label: "Art", state: "Unselected" },
|
||||
{ id: "values-5", label: "Decisiveness", state: "Unselected" },
|
||||
{ id: "values-1", label: "Consciousness", state: "unselected" },
|
||||
{ id: "values-2", label: "Ecology", state: "unselected" },
|
||||
{ id: "values-3", label: "Abundance", state: "unselected" },
|
||||
{ id: "values-4", label: "Art", state: "unselected" },
|
||||
{ id: "values-5", label: "Decisiveness", state: "unselected" },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Communication",
|
||||
chipOptions: [{ id: "comm-1", label: "Signal", state: "Unselected" }],
|
||||
chipOptions: [{ id: "comm-1", label: "Signal", state: "unselected" }],
|
||||
},
|
||||
{
|
||||
name: "Membership",
|
||||
chipOptions: [
|
||||
{ id: "membership-1", label: "Open Admission", state: "Unselected" },
|
||||
{ id: "membership-1", label: "Open Admission", state: "unselected" },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Decision-making",
|
||||
chipOptions: [
|
||||
{ id: "decision-1", label: "Lazy Consensus", state: "Unselected" },
|
||||
{ id: "decision-1", label: "Lazy Consensus", state: "unselected" },
|
||||
{
|
||||
id: "decision-2",
|
||||
label: "Modified Consensus",
|
||||
state: "Unselected",
|
||||
state: "unselected",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Conflict management",
|
||||
chipOptions: [
|
||||
{ id: "conflict-1", label: "Code of Conduct", state: "Unselected" },
|
||||
{ id: "conflict-1", label: "Code of Conduct", state: "unselected" },
|
||||
{
|
||||
id: "conflict-2",
|
||||
label: "Restorative Justice",
|
||||
state: "Unselected",
|
||||
state: "unselected",
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -394,9 +394,9 @@ export const InteractiveStates = {
|
||||
{
|
||||
name: "Values",
|
||||
chipOptions: [
|
||||
{ id: "values-1", label: "Consciousness", state: "Unselected" },
|
||||
{ id: "values-2", label: "Ecology", state: "Unselected" },
|
||||
{ id: "values-3", label: "Abundance", state: "Unselected" },
|
||||
{ id: "values-1", label: "Consciousness", state: "unselected" },
|
||||
{ id: "values-2", label: "Ecology", state: "unselected" },
|
||||
{ id: "values-3", label: "Abundance", state: "unselected" },
|
||||
],
|
||||
onChipClick: (categoryName, chipId) => {
|
||||
console.log(`Chip clicked: ${categoryName} - ${chipId}`);
|
||||
@@ -407,7 +407,7 @@ export const InteractiveStates = {
|
||||
},
|
||||
{
|
||||
name: "Communication",
|
||||
chipOptions: [{ id: "comm-1", label: "Signal", state: "Unselected" }],
|
||||
chipOptions: [{ id: "comm-1", label: "Signal", state: "unselected" }],
|
||||
onChipClick: (categoryName, chipId) => {
|
||||
console.log(`Chip clicked: ${categoryName} - ${chipId}`);
|
||||
},
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
import { TemplateReviewCard } from "../../app/components/cards/TemplateReviewCard";
|
||||
|
||||
const sampleTemplate = {
|
||||
id: "tmpl-1",
|
||||
slug: "consensus",
|
||||
title: "Consensus",
|
||||
category: null,
|
||||
description:
|
||||
"Important decisions require unanimous agreement. Proposals pass only if no serious objections remain.",
|
||||
body: {
|
||||
sections: [
|
||||
{
|
||||
categoryName: "Decision making",
|
||||
entries: [
|
||||
{ title: "How proposals pass", body: "Unanimous agreement is required." },
|
||||
{ title: "Blocks", body: "Anyone with a serious objection may block." },
|
||||
],
|
||||
},
|
||||
{
|
||||
categoryName: "Membership",
|
||||
entries: [
|
||||
{ title: "Joining", body: "New members are welcomed by consensus." },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
sortOrder: 1,
|
||||
featured: true,
|
||||
};
|
||||
|
||||
export default {
|
||||
title: "Components/Cards/TemplateReviewCard",
|
||||
component: TemplateReviewCard,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
},
|
||||
argTypes: {
|
||||
template: {
|
||||
control: false,
|
||||
description: "RuleTemplateDto used to populate the card",
|
||||
},
|
||||
size: {
|
||||
control: "select",
|
||||
options: ["XS", "S", "M", "L"],
|
||||
description: "RuleCard size variant",
|
||||
},
|
||||
ruleCardClassName: {
|
||||
control: "text",
|
||||
description: "Class names merged onto the inner RuleCard",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
args: {
|
||||
template: sampleTemplate,
|
||||
size: "L",
|
||||
},
|
||||
};
|
||||
|
||||
export const Medium = {
|
||||
args: {
|
||||
template: sampleTemplate,
|
||||
size: "M",
|
||||
},
|
||||
};
|
||||
@@ -46,15 +46,13 @@ export default {
|
||||
},
|
||||
mode: {
|
||||
control: "select",
|
||||
options: ["standard", "inverse", "Standard", "Inverse"],
|
||||
description:
|
||||
"Visual mode of the checkbox (case-insensitive: accepts both lowercase and PascalCase)",
|
||||
options: ["standard", "inverse"],
|
||||
description: "Visual mode of the checkbox",
|
||||
},
|
||||
state: {
|
||||
control: "select",
|
||||
options: ["default", "hover", "focus", "Default", "Hover", "Focus"],
|
||||
description:
|
||||
"Interaction state for static display (case-insensitive: accepts both lowercase and PascalCase)",
|
||||
options: ["default", "hover", "focus"],
|
||||
description: "Interaction state for static display",
|
||||
},
|
||||
disabled: {
|
||||
control: "boolean",
|
||||
@@ -228,15 +226,15 @@ export const FigmaPascalCase = () => {
|
||||
<Checkbox
|
||||
label="Standard Mode (PascalCase)"
|
||||
checked={standardChecked}
|
||||
mode="Standard"
|
||||
state="Default"
|
||||
mode="standard"
|
||||
state="default"
|
||||
onChange={({ checked }) => setStandardChecked(checked)}
|
||||
/>
|
||||
<Checkbox
|
||||
label="Inverse Mode (PascalCase)"
|
||||
checked={inverseChecked}
|
||||
mode="Inverse"
|
||||
state="Default"
|
||||
mode="inverse"
|
||||
state="default"
|
||||
onChange={({ checked }) => setInverseChecked(checked)}
|
||||
/>
|
||||
</div>
|
||||
@@ -256,7 +254,7 @@ export const FigmaPascalCase = () => {
|
||||
label="Inverse Mode (mixed) - still works"
|
||||
checked={false}
|
||||
mode="inverse"
|
||||
state="Default"
|
||||
state="default"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
import Chip from "../../app/components/controls/Chip";
|
||||
|
||||
export default {
|
||||
title: "Components/Controls/Chip",
|
||||
component: Chip,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
},
|
||||
argTypes: {
|
||||
label: {
|
||||
control: "text",
|
||||
description: "Text displayed inside the chip",
|
||||
},
|
||||
state: {
|
||||
control: "select",
|
||||
options: ["unselected", "selected", "disabled", "custom"],
|
||||
description: "Visual state of the chip",
|
||||
},
|
||||
palette: {
|
||||
control: "select",
|
||||
options: ["default", "inverse"],
|
||||
description: "Color palette of the chip",
|
||||
},
|
||||
size: {
|
||||
control: "select",
|
||||
options: ["s", "m"],
|
||||
description: "Size of the chip",
|
||||
},
|
||||
disabled: {
|
||||
control: "boolean",
|
||||
description: "Override the disabled behaviour independently of state",
|
||||
},
|
||||
onClick: { action: "clicked" },
|
||||
onRemove: { action: "removed" },
|
||||
onCheck: { action: "checked" },
|
||||
onClose: { action: "closed" },
|
||||
},
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
args: {
|
||||
label: "Worker cooperative",
|
||||
state: "unselected",
|
||||
palette: "default",
|
||||
size: "m",
|
||||
},
|
||||
};
|
||||
|
||||
export const Selected = {
|
||||
args: {
|
||||
label: "Worker cooperative",
|
||||
state: "selected",
|
||||
palette: "default",
|
||||
size: "m",
|
||||
},
|
||||
};
|
||||
|
||||
export const Disabled = {
|
||||
args: {
|
||||
label: "Worker cooperative",
|
||||
state: "disabled",
|
||||
palette: "default",
|
||||
size: "m",
|
||||
},
|
||||
};
|
||||
|
||||
export const Inverse = {
|
||||
args: {
|
||||
label: "Worker cooperative",
|
||||
state: "selected",
|
||||
palette: "inverse",
|
||||
size: "m",
|
||||
},
|
||||
};
|
||||
|
||||
export const Small = {
|
||||
args: {
|
||||
label: "Worker cooperative",
|
||||
state: "unselected",
|
||||
palette: "default",
|
||||
size: "s",
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,82 @@
|
||||
import React from "react";
|
||||
import InputWithCounter from "../../app/components/controls/InputWithCounter";
|
||||
|
||||
export default {
|
||||
title: "Components/Controls/InputWithCounter",
|
||||
component: InputWithCounter,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
},
|
||||
argTypes: {
|
||||
label: {
|
||||
control: "text",
|
||||
description: "Label rendered above the input",
|
||||
},
|
||||
placeholder: {
|
||||
control: "text",
|
||||
description: "Placeholder text shown when value is empty",
|
||||
},
|
||||
value: {
|
||||
control: "text",
|
||||
description: "Current value of the input (controlled)",
|
||||
},
|
||||
maxLength: {
|
||||
control: { type: "number", min: 1, max: 500, step: 1 },
|
||||
description: "Maximum number of characters allowed",
|
||||
},
|
||||
showHelpIcon: {
|
||||
control: "boolean",
|
||||
description: "Whether to show the help icon next to the label",
|
||||
},
|
||||
onChange: { action: "changed" },
|
||||
},
|
||||
};
|
||||
|
||||
const Template = (args) => {
|
||||
const [value, setValue] = React.useState(args.value ?? "");
|
||||
return (
|
||||
<div style={{ width: 320 }}>
|
||||
<InputWithCounter
|
||||
{...args}
|
||||
value={value}
|
||||
onChange={(next) => {
|
||||
setValue(next);
|
||||
args.onChange?.(next);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
render: Template,
|
||||
args: {
|
||||
label: "Community name",
|
||||
placeholder: "Enter a name",
|
||||
value: "",
|
||||
maxLength: 50,
|
||||
showHelpIcon: false,
|
||||
},
|
||||
};
|
||||
|
||||
export const WithHelpIcon = {
|
||||
render: Template,
|
||||
args: {
|
||||
label: "Community name",
|
||||
placeholder: "Enter a name",
|
||||
value: "",
|
||||
maxLength: 50,
|
||||
showHelpIcon: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const WithInitialValue = {
|
||||
render: Template,
|
||||
args: {
|
||||
label: "Community name",
|
||||
placeholder: "Enter a name",
|
||||
value: "My community",
|
||||
maxLength: 30,
|
||||
showHelpIcon: false,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,85 @@
|
||||
import React from "react";
|
||||
import MultiSelect from "../../app/components/controls/MultiSelect";
|
||||
|
||||
export default {
|
||||
title: "Components/Controls/MultiSelect",
|
||||
component: MultiSelect,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
},
|
||||
argTypes: {
|
||||
label: {
|
||||
control: "text",
|
||||
description: "Label displayed above the chip set",
|
||||
},
|
||||
showHelpIcon: {
|
||||
control: "boolean",
|
||||
description: "Whether to show the help icon next to the label",
|
||||
},
|
||||
size: {
|
||||
control: "select",
|
||||
options: ["s", "m"],
|
||||
description: "Size variant of the chips",
|
||||
},
|
||||
palette: {
|
||||
control: "select",
|
||||
options: ["default", "inverse"],
|
||||
description: "Color palette applied to the chips",
|
||||
},
|
||||
addButton: {
|
||||
control: "boolean",
|
||||
description: "Whether to show the add button",
|
||||
},
|
||||
addButtonText: {
|
||||
control: "text",
|
||||
description: "Text rendered on the add button",
|
||||
},
|
||||
formHeader: {
|
||||
control: "boolean",
|
||||
description: "Whether to show the label/help-icon header",
|
||||
},
|
||||
onChipClick: { action: "chip-clicked" },
|
||||
onAddClick: { action: "add-clicked" },
|
||||
},
|
||||
};
|
||||
|
||||
const defaultOptions = [
|
||||
{ id: "1", label: "Worker cooperative", state: "unselected" },
|
||||
{ id: "2", label: "Consumer cooperative", state: "selected" },
|
||||
{ id: "3", label: "Housing cooperative", state: "unselected" },
|
||||
{ id: "4", label: "Producer cooperative", state: "unselected" },
|
||||
];
|
||||
|
||||
export const Default = {
|
||||
args: {
|
||||
label: "Organization type",
|
||||
showHelpIcon: true,
|
||||
size: "m",
|
||||
palette: "default",
|
||||
options: defaultOptions,
|
||||
addButton: true,
|
||||
addButtonText: "Add organization type",
|
||||
formHeader: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const Small = {
|
||||
args: {
|
||||
...Default.args,
|
||||
size: "s",
|
||||
},
|
||||
};
|
||||
|
||||
export const Inverse = {
|
||||
args: {
|
||||
...Default.args,
|
||||
palette: "inverse",
|
||||
},
|
||||
};
|
||||
|
||||
export const NoAddButton = {
|
||||
args: {
|
||||
...Default.args,
|
||||
addButton: false,
|
||||
},
|
||||
};
|
||||
@@ -21,24 +21,13 @@ export default {
|
||||
},
|
||||
mode: {
|
||||
control: "select",
|
||||
options: ["standard", "inverse", "Standard", "Inverse"],
|
||||
description:
|
||||
"Visual mode of the radio button (case-insensitive: accepts both lowercase and PascalCase)",
|
||||
options: ["standard", "inverse"],
|
||||
description: "Visual mode of the radio button",
|
||||
},
|
||||
state: {
|
||||
control: "select",
|
||||
options: [
|
||||
"default",
|
||||
"hover",
|
||||
"focus",
|
||||
"selected",
|
||||
"Default",
|
||||
"Hover",
|
||||
"Focus",
|
||||
"Selected",
|
||||
],
|
||||
description:
|
||||
"Interaction state for static display (case-insensitive: accepts both lowercase and PascalCase)",
|
||||
options: ["default", "hover", "focus", "selected"],
|
||||
description: "Interaction state for static display",
|
||||
},
|
||||
disabled: {
|
||||
control: "boolean",
|
||||
@@ -286,15 +275,15 @@ export const FigmaPascalCase = () => {
|
||||
<RadioButton
|
||||
label="Standard Mode (PascalCase)"
|
||||
checked={standardChecked}
|
||||
mode="Standard"
|
||||
state="Default"
|
||||
mode="standard"
|
||||
state="default"
|
||||
onChange={({ checked }) => setStandardChecked(checked)}
|
||||
/>
|
||||
<RadioButton
|
||||
label="Inverse Mode (PascalCase)"
|
||||
checked={inverseChecked}
|
||||
mode="Inverse"
|
||||
state="Default"
|
||||
mode="inverse"
|
||||
state="default"
|
||||
onChange={({ checked }) => setInverseChecked(checked)}
|
||||
/>
|
||||
</div>
|
||||
@@ -314,7 +303,7 @@ export const FigmaPascalCase = () => {
|
||||
label="Inverse Mode (mixed) - still works"
|
||||
checked={false}
|
||||
mode="inverse"
|
||||
state="Default"
|
||||
state="default"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import ApplicableScopeField from "../../app/create/components/ApplicableScopeField";
|
||||
import ApplicableScopeField from "../../app/(app)/create/components/ApplicableScopeField";
|
||||
|
||||
export default {
|
||||
title: "Create Flow/ApplicableScopeField",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import ModalTextAreaField from "../../app/create/components/ModalTextAreaField";
|
||||
import ModalTextAreaField from "../../app/(app)/create/components/ModalTextAreaField";
|
||||
|
||||
export default {
|
||||
title: "Create Flow/ModalTextAreaField",
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import LanguageSwitcher from "../../app/components/localization/LanguageSwitcher";
|
||||
|
||||
export default {
|
||||
title: "Components/Localization/LanguageSwitcher",
|
||||
component: LanguageSwitcher,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
},
|
||||
argTypes: {
|
||||
className: {
|
||||
control: "text",
|
||||
description: "Optional wrapper className",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
args: {},
|
||||
};
|
||||
@@ -121,7 +121,7 @@ export const HeaderOverlayBlurred = {
|
||||
),
|
||||
};
|
||||
|
||||
/** Matches `app/login/page.tsx`: dedicated route, solid yellow, no portal. */
|
||||
/** Matches `app/(app)/login/page.tsx`: dedicated route, solid yellow, no portal. */
|
||||
export const FullPageRouteSolid = {
|
||||
name: "Full-page route (/login — solid)",
|
||||
parameters: {
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
import NavigationItem from "../../app/components/navigation/NavigationItem";
|
||||
|
||||
export default {
|
||||
title: "Components/Navigation/NavigationItem",
|
||||
component: NavigationItem,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
},
|
||||
argTypes: {
|
||||
href: {
|
||||
control: "text",
|
||||
description: "Anchor href",
|
||||
},
|
||||
variant: {
|
||||
control: "select",
|
||||
options: ["default"],
|
||||
description: "Visual variant",
|
||||
},
|
||||
size: {
|
||||
control: "select",
|
||||
options: ["default", "xsmall"],
|
||||
description: "Size variant",
|
||||
},
|
||||
disabled: {
|
||||
control: "boolean",
|
||||
description: "Disable interaction (renders as span)",
|
||||
},
|
||||
isActive: {
|
||||
control: "boolean",
|
||||
description: "Mark the item as currently active",
|
||||
},
|
||||
children: {
|
||||
control: "text",
|
||||
description: "Item label",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
args: {
|
||||
children: "Templates",
|
||||
href: "#",
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
};
|
||||
|
||||
export const Active = {
|
||||
args: {
|
||||
children: "Templates",
|
||||
href: "#",
|
||||
variant: "default",
|
||||
size: "default",
|
||||
isActive: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const Disabled = {
|
||||
args: {
|
||||
children: "Templates",
|
||||
href: "#",
|
||||
variant: "default",
|
||||
size: "default",
|
||||
disabled: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const XSmall = {
|
||||
args: {
|
||||
children: "Templates",
|
||||
href: "#",
|
||||
variant: "default",
|
||||
size: "xsmall",
|
||||
},
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CommunicationMethodsScreen } from "../../app/create/screens/card/CommunicationMethodsScreen";
|
||||
import { CommunicationMethodsScreen } from "../../app/(app)/create/screens/card/CommunicationMethodsScreen";
|
||||
|
||||
export default {
|
||||
title: "Pages/Create Flow/Communication methods",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CompletedScreen } from "../../app/create/screens/completed/CompletedScreen";
|
||||
import { CompletedScreen } from "../../app/(app)/create/screens/completed/CompletedScreen";
|
||||
|
||||
export default {
|
||||
title: "Pages/Create Flow/Completed",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ConfirmStakeholdersScreen } from "../../app/create/screens/select/ConfirmStakeholdersScreen";
|
||||
import { ConfirmStakeholdersScreen } from "../../app/(app)/create/screens/select/ConfirmStakeholdersScreen";
|
||||
|
||||
export default {
|
||||
title: "Pages/Create Flow/Confirm stakeholders",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { DecisionApproachesScreen } from "../../app/create/screens/right-rail/DecisionApproachesScreen";
|
||||
import { DecisionApproachesScreen } from "../../app/(app)/create/screens/right-rail/DecisionApproachesScreen";
|
||||
|
||||
export default {
|
||||
title: "Pages/Create Flow/Decision approaches",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { FinalReviewScreen } from "../../app/create/screens/review/FinalReviewScreen";
|
||||
import { FinalReviewScreen } from "../../app/(app)/create/screens/review/FinalReviewScreen";
|
||||
|
||||
export default {
|
||||
title: "Pages/Create Flow/Final review",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { InformationalScreen } from "../../app/create/screens/informational/InformationalScreen";
|
||||
import { InformationalScreen } from "../../app/(app)/create/screens/informational/InformationalScreen";
|
||||
|
||||
export default {
|
||||
title: "Pages/Create/Informational",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CommunityReviewScreen } from "../../app/create/screens/review/CommunityReviewScreen";
|
||||
import { CommunityReviewScreen } from "../../app/(app)/create/screens/review/CommunityReviewScreen";
|
||||
|
||||
export default {
|
||||
title: "Pages/Create/Review",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CommunitySizeSelectScreen } from "../../app/create/screens/select/CommunitySizeSelectScreen";
|
||||
import { CommunitySizeSelectScreen } from "../../app/(app)/create/screens/select/CommunitySizeSelectScreen";
|
||||
|
||||
export default {
|
||||
title: "Pages/Create/CommunitySize",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CreateFlowTextFieldScreen } from "../../app/create/screens/text/CreateFlowTextFieldScreen";
|
||||
import { CreateFlowTextFieldScreen } from "../../app/(app)/create/screens/text/CreateFlowTextFieldScreen";
|
||||
|
||||
export default {
|
||||
title: "Pages/Create/CommunityName",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CommunityUploadScreen } from "../../app/create/screens/upload/CommunityUploadScreen";
|
||||
import { CommunityUploadScreen } from "../../app/(app)/create/screens/upload/CommunityUploadScreen";
|
||||
|
||||
export default {
|
||||
title: "Pages/Create/CommunityUpload",
|
||||
|
||||
@@ -15,7 +15,7 @@ export default {
|
||||
argTypes: {
|
||||
variant: {
|
||||
control: { type: "select" },
|
||||
options: ["default", "segmented", "Default", "Segmented"],
|
||||
options: ["default", "segmented"],
|
||||
description:
|
||||
"Segmented: pill-shaped partial fills (create-flow footer / Figma).",
|
||||
},
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
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,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
import { GovernanceTemplateGrid } from "../../app/components/sections/GovernanceTemplateGrid";
|
||||
import { GOVERNANCE_TEMPLATE_CATALOG } from "../../lib/templates/governanceTemplateCatalog";
|
||||
|
||||
export default {
|
||||
title: "Components/Sections/GovernanceTemplateGrid",
|
||||
component: GovernanceTemplateGrid,
|
||||
parameters: {
|
||||
layout: "fullscreen",
|
||||
},
|
||||
argTypes: {
|
||||
entries: {
|
||||
control: false,
|
||||
description: "Catalog entries to render as a 2-column grid of RuleCards",
|
||||
},
|
||||
onTemplateClick: { action: "template-clicked" },
|
||||
},
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
args: {
|
||||
entries: GOVERNANCE_TEMPLATE_CATALOG.slice(0, 4),
|
||||
},
|
||||
};
|
||||
|
||||
export const SingleEntry = {
|
||||
args: {
|
||||
entries: GOVERNANCE_TEMPLATE_CATALOG.slice(0, 1),
|
||||
},
|
||||
};
|
||||
@@ -1,40 +0,0 @@
|
||||
import ErrorBoundary from "../../app/components/utility/ErrorBoundary";
|
||||
|
||||
export default {
|
||||
title: "Components/Utility/ErrorBoundary",
|
||||
component: ErrorBoundary,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
"An error boundary component that catches JavaScript errors in its child component tree. Displays a fallback UI when errors occur and logs error information for debugging.",
|
||||
},
|
||||
},
|
||||
},
|
||||
argTypes: {
|
||||
children: {
|
||||
control: { type: "text" },
|
||||
description: "Child components to wrap with error boundary",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
args: {
|
||||
children: <div>Normal content</div>,
|
||||
},
|
||||
};
|
||||
|
||||
export const WithError = {
|
||||
render: () => {
|
||||
const ThrowError = () => {
|
||||
throw new Error("Test error for ErrorBoundary");
|
||||
};
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
<ThrowError />
|
||||
</ErrorBoundary>
|
||||
);
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,71 @@
|
||||
import ModalFooter from "../../app/components/utility/ModalFooter";
|
||||
|
||||
export default {
|
||||
title: "Components/Utility/ModalFooter",
|
||||
component: ModalFooter,
|
||||
parameters: {
|
||||
layout: "fullscreen",
|
||||
},
|
||||
argTypes: {
|
||||
showBackButton: {
|
||||
control: "boolean",
|
||||
description: "Whether to render the back button on the left",
|
||||
},
|
||||
showNextButton: {
|
||||
control: "boolean",
|
||||
description: "Whether to render the next button on the right",
|
||||
},
|
||||
backButtonText: {
|
||||
control: "text",
|
||||
description: "Override text for the back button",
|
||||
},
|
||||
nextButtonText: {
|
||||
control: "text",
|
||||
description: "Override text for the next button",
|
||||
},
|
||||
nextButtonDisabled: {
|
||||
control: "boolean",
|
||||
description: "Whether the next button is disabled",
|
||||
},
|
||||
currentStep: {
|
||||
control: { type: "number", min: 1, max: 10, step: 1 },
|
||||
description: "Current step (used by the centered Stepper)",
|
||||
},
|
||||
totalSteps: {
|
||||
control: { type: "number", min: 1, max: 10, step: 1 },
|
||||
description: "Total number of steps",
|
||||
},
|
||||
stepper: {
|
||||
control: "boolean",
|
||||
description: "Whether to render the centered stepper",
|
||||
},
|
||||
onBack: { action: "back-clicked" },
|
||||
onNext: { action: "next-clicked" },
|
||||
},
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
args: {
|
||||
showBackButton: true,
|
||||
showNextButton: true,
|
||||
currentStep: 2,
|
||||
totalSteps: 4,
|
||||
},
|
||||
};
|
||||
|
||||
export const NextDisabled = {
|
||||
args: {
|
||||
showBackButton: true,
|
||||
showNextButton: true,
|
||||
nextButtonDisabled: true,
|
||||
currentStep: 1,
|
||||
totalSteps: 4,
|
||||
},
|
||||
};
|
||||
|
||||
export const NextOnly = {
|
||||
args: {
|
||||
showBackButton: false,
|
||||
showNextButton: true,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
import ModalHeader from "../../app/components/utility/ModalHeader";
|
||||
|
||||
export default {
|
||||
title: "Components/Utility/ModalHeader",
|
||||
component: ModalHeader,
|
||||
parameters: {
|
||||
layout: "fullscreen",
|
||||
},
|
||||
argTypes: {
|
||||
showCloseButton: {
|
||||
control: "boolean",
|
||||
description: "Whether to render the close button on the left",
|
||||
},
|
||||
showMoreOptionsButton: {
|
||||
control: "boolean",
|
||||
description: "Whether to render the more-options button on the right",
|
||||
},
|
||||
onClose: { action: "close-clicked" },
|
||||
onMoreOptions: { action: "more-options-clicked" },
|
||||
},
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
args: {
|
||||
showCloseButton: true,
|
||||
showMoreOptionsButton: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const CloseOnly = {
|
||||
args: {
|
||||
showCloseButton: true,
|
||||
showMoreOptionsButton: false,
|
||||
},
|
||||
};
|
||||
|
||||
export const MoreOptionsOnly = {
|
||||
args: {
|
||||
showCloseButton: false,
|
||||
showMoreOptionsButton: true,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
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