"use client"; import { useState } from "react"; import RuleCard from "../../components/cards/RuleCard"; import Card from "../../components/cards/Card"; import Chip from "../../components/controls/Chip"; import MultiSelect from "../../components/controls/MultiSelect"; import Image from "next/image"; import { getAssetPath } from "../../../lib/assetUtils"; /** Module-level counter for unique rule card chip IDs (avoids ref in initial state). */ let ruleCardIdCounter = 0; interface ChipData { id: string; label: string; state: "unselected" | "selected" | "custom"; palette: "default" | "inverse"; size: "s" | "m"; } function MultiSelectExample({ size }: { size: "s" | "m" }) { const [options, setOptions] = useState< Array<{ id: string; label: string; state: "unselected" | "selected" | "custom"; }> >([ { id: "1", label: "1 member", state: "unselected" }, { id: "2", label: "2-10 members", state: "unselected" }, { id: "3", label: "10-24 members", state: "unselected" }, { id: "4", label: "24-64 members", state: "unselected" }, { id: "5", label: "64-128 members", state: "unselected" }, { id: "6", label: "125-1000 members", state: "unselected" }, { id: "7", label: "1000+ members", state: "unselected" }, ]); const handleChipClick = (chipId: string) => { setOptions((prev) => prev.map((opt) => opt.id === chipId ? { ...opt, state: opt.state === "selected" ? "unselected" : "selected", } : opt, ), ); }; const handleAddClick = () => { const newId = `custom-${Date.now()}`; setOptions((prev) => [...prev, { id: newId, label: "", state: "custom" }]); }; const handleCustomConfirm = (chipId: string, value: string) => { setOptions((prev) => prev.map((opt) => opt.id === chipId ? { ...opt, label: value, state: "selected" as const } : opt, ), ); }; const handleCustomClose = (chipId: string) => { setOptions((prev) => prev.filter((opt) => opt.id !== chipId)); }; return (

{size === "s" ? "Small (S)" : "Medium (M)"}

); } export default function ComponentsPreview() { const [chipStates, setChipStates] = useState< Record >({ "default-s": "unselected", "default-m": "unselected", "inverse-s": "unselected", "inverse-m": "unselected", }); // Manage custom chips separately const [customChips, setCustomChips] = useState([ { id: "custom-1", label: "", state: "custom", palette: "default", size: "s", }, { id: "custom-2", label: "", state: "custom", palette: "default", size: "m", }, ]); // RuleCard categories with chip options and state management const [ruleCardCategories, setRuleCardCategories] = useState< Array<{ name: string; chipOptions: Array<{ id: string; label: string; state: "unselected" | "selected" | "custom"; }>; onChipClick?: (_categoryName: string, _chipId: string) => void; onAddClick?: (_categoryName: string) => void; onCustomChipConfirm?: ( _categoryName: string, _chipId: string, _value: string, ) => void; onCustomChipClose?: (_categoryName: string, _chipId: string) => void; }> >([ { 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" }, ], onChipClick: (categoryName: string, chipId: string) => { setRuleCardCategories((prev) => prev.map((cat) => cat.name === categoryName ? { ...cat, chipOptions: cat.chipOptions.map((opt) => opt.id === chipId ? { ...opt, state: opt.state === "selected" ? "unselected" : "selected", } : opt, ), } : cat, ), ); }, onAddClick: (categoryName: string) => { const newId = `custom-${categoryName}-${++ruleCardIdCounter}`; setRuleCardCategories((prev) => prev.map((cat) => cat.name === categoryName ? { ...cat, chipOptions: [ ...cat.chipOptions, { id: newId, label: "", state: "custom" }, ], } : cat, ), ); }, onCustomChipConfirm: ( categoryName: string, chipId: string, value: string, ) => { setRuleCardCategories((prev) => prev.map((cat) => cat.name === categoryName ? { ...cat, chipOptions: cat.chipOptions.map((opt) => opt.id === chipId ? { ...opt, label: value, state: "selected" } : opt, ), } : cat, ), ); }, onCustomChipClose: (categoryName: string, chipId: string) => { setRuleCardCategories((prev) => prev.map((cat) => cat.name === categoryName ? { ...cat, chipOptions: cat.chipOptions.filter( (opt) => opt.id !== chipId, ), } : cat, ), ); }, }, { name: "Communication", chipOptions: [{ id: "comm-1", label: "Signal", state: "unselected" }], onChipClick: (categoryName: string, chipId: string) => { setRuleCardCategories((prev) => prev.map((cat) => cat.name === categoryName ? { ...cat, chipOptions: cat.chipOptions.map((opt) => opt.id === chipId ? { ...opt, state: opt.state === "selected" ? "unselected" : "selected", } : opt, ), } : cat, ), ); }, onAddClick: (categoryName: string) => { const newId = `custom-${categoryName}-${++ruleCardIdCounter}`; setRuleCardCategories((prev) => prev.map((cat) => cat.name === categoryName ? { ...cat, chipOptions: [ ...cat.chipOptions, { id: newId, label: "", state: "custom" }, ], } : cat, ), ); }, onCustomChipConfirm: ( categoryName: string, chipId: string, value: string, ) => { setRuleCardCategories((prev) => prev.map((cat) => cat.name === categoryName ? { ...cat, chipOptions: cat.chipOptions.map((opt) => opt.id === chipId ? { ...opt, label: value, state: "selected" } : opt, ), } : cat, ), ); }, onCustomChipClose: (categoryName: string, chipId: string) => { setRuleCardCategories((prev) => prev.map((cat) => cat.name === categoryName ? { ...cat, chipOptions: cat.chipOptions.filter( (opt) => opt.id !== chipId, ), } : cat, ), ); }, }, { name: "Membership", chipOptions: [ { id: "membership-1", label: "Open Admission", state: "unselected" }, ], onChipClick: (categoryName: string, chipId: string) => { setRuleCardCategories((prev) => prev.map((cat) => cat.name === categoryName ? { ...cat, chipOptions: cat.chipOptions.map((opt) => opt.id === chipId ? { ...opt, state: opt.state === "selected" ? "unselected" : "selected", } : opt, ), } : cat, ), ); }, onAddClick: (categoryName: string) => { const newId = `custom-${categoryName}-${++ruleCardIdCounter}`; setRuleCardCategories((prev) => prev.map((cat) => cat.name === categoryName ? { ...cat, chipOptions: [ ...cat.chipOptions, { id: newId, label: "", state: "custom" }, ], } : cat, ), ); }, onCustomChipConfirm: ( categoryName: string, chipId: string, value: string, ) => { setRuleCardCategories((prev) => prev.map((cat) => cat.name === categoryName ? { ...cat, chipOptions: cat.chipOptions.map((opt) => opt.id === chipId ? { ...opt, label: value, state: "selected" } : opt, ), } : cat, ), ); }, onCustomChipClose: (categoryName: string, chipId: string) => { setRuleCardCategories((prev) => prev.map((cat) => cat.name === categoryName ? { ...cat, chipOptions: cat.chipOptions.filter( (opt) => opt.id !== chipId, ), } : cat, ), ); }, }, { name: "Decision-making", chipOptions: [ { id: "decision-1", label: "Lazy Consensus", state: "unselected" }, { id: "decision-2", label: "Modified Consensus", state: "unselected" }, ], onChipClick: (categoryName: string, chipId: string) => { setRuleCardCategories((prev) => prev.map((cat) => cat.name === categoryName ? { ...cat, chipOptions: cat.chipOptions.map((opt) => opt.id === chipId ? { ...opt, state: opt.state === "selected" ? "unselected" : "selected", } : opt, ), } : cat, ), ); }, onAddClick: (categoryName: string) => { const newId = `custom-${categoryName}-${++ruleCardIdCounter}`; setRuleCardCategories((prev) => prev.map((cat) => cat.name === categoryName ? { ...cat, chipOptions: [ ...cat.chipOptions, { id: newId, label: "", state: "custom" }, ], } : cat, ), ); }, onCustomChipConfirm: ( categoryName: string, chipId: string, value: string, ) => { setRuleCardCategories((prev) => prev.map((cat) => cat.name === categoryName ? { ...cat, chipOptions: cat.chipOptions.map((opt) => opt.id === chipId ? { ...opt, label: value, state: "selected" } : opt, ), } : cat, ), ); }, onCustomChipClose: (categoryName: string, chipId: string) => { setRuleCardCategories((prev) => prev.map((cat) => cat.name === categoryName ? { ...cat, chipOptions: cat.chipOptions.filter( (opt) => opt.id !== chipId, ), } : cat, ), ); }, }, { name: "Conflict management", chipOptions: [ { id: "conflict-1", label: "Code of Conduct", state: "unselected" }, { id: "conflict-2", label: "Restorative Justice", state: "unselected" }, ], onChipClick: (categoryName: string, chipId: string) => { setRuleCardCategories((prev) => prev.map((cat) => cat.name === categoryName ? { ...cat, chipOptions: cat.chipOptions.map((opt) => opt.id === chipId ? { ...opt, state: opt.state === "selected" ? "unselected" : "selected", } : opt, ), } : cat, ), ); }, onAddClick: (categoryName: string) => { const newId = `custom-${categoryName}-${++ruleCardIdCounter}`; setRuleCardCategories((prev) => prev.map((cat) => cat.name === categoryName ? { ...cat, chipOptions: [ ...cat.chipOptions, { id: newId, label: "", state: "custom" }, ], } : cat, ), ); }, onCustomChipConfirm: ( categoryName: string, chipId: string, value: string, ) => { setRuleCardCategories((prev) => prev.map((cat) => cat.name === categoryName ? { ...cat, chipOptions: cat.chipOptions.map((opt) => opt.id === chipId ? { ...opt, label: value, state: "selected" } : opt, ), } : cat, ), ); }, onCustomChipClose: (categoryName: string, chipId: string) => { setRuleCardCategories((prev) => prev.map((cat) => cat.name === categoryName ? { ...cat, chipOptions: cat.chipOptions.filter( (opt) => opt.id !== chipId, ), } : cat, ), ); }, }, ]); return (

Component Preview

RuleCard, Card, and Chip component examples - states, palettes, sizes, and interactions

{/* Chip Component - Controls */}

Chip Component (Controls)

{/* Default palette */}

Default palette

setChipStates((prev) => ({ ...prev, "default-s": prev["default-s"] === "selected" ? "unselected" : "selected", })) } /> setChipStates((prev) => ({ ...prev, "default-m": prev["default-m"] === "selected" ? "unselected" : "selected", })) } /> {customChips .filter((chip) => chip.palette === "default") .map((chip) => ( { e.stopPropagation(); setCustomChips((prev) => prev.map((c) => c.id === chip.id ? { ...c, label: value, state: "selected" } : c, ), ); }} onClose={(e) => { e.stopPropagation(); setCustomChips((prev) => prev.filter((c) => c.id !== chip.id), ); }} onClick={(e) => { e.stopPropagation(); // Only toggle if the chip is in Selected or Unselected state (not Custom) if ( chip.state === "selected" || chip.state === "unselected" ) { setCustomChips((prev) => prev.map((c) => c.id === chip.id ? { ...c, state: c.state === "selected" ? "unselected" : "selected", } : c, ), ); } }} /> ))} {/* Add new custom chip button - Ghost button style */}
{/* Inverse palette - on white background */}

Inverse palette (on white background)

setChipStates((prev) => ({ ...prev, "inverse-s": prev["inverse-s"] === "selected" ? "unselected" : "selected", })) } /> setChipStates((prev) => ({ ...prev, "inverse-m": prev["inverse-m"] === "selected" ? "unselected" : "selected", })) } />
{/* Card Component - Create flow selection card variants */}

Card Component

Horizontal and vertical orientations with recommended and selected states.

Horizontal + Recommended

console.warn("Card clicked")} />

Horizontal + Selected

console.warn("Card clicked")} />

Vertical + Recommended

console.warn("Card clicked")} />

Vertical + Selected

console.warn("Card clicked")} />
{/* Collapsed State - Large */}

Collapsed State - Large (L)

console.warn("Card clicked: Mutual Aid Mondays")} />
{/* Collapsed State - Medium */}

Collapsed State - Medium (M)

console.warn("Card clicked: Mutual Aid Mondays")} />
{/* Expanded State - Large */}

Expanded State - Large (L)

console.warn("Card clicked: Mutual Aid Mondays")} />
{/* Expanded State - Medium */}

Expanded State - Medium (M)

console.warn("Card clicked: Mutual Aid Mondays")} />
{/* Different Background Colors */}

Different Background Colors

} onClick={() => console.warn("Consensus clusters selected")} /> } onClick={() => console.warn("Consensus selected")} />
{/* Logo Fallback */}

Logo Fallback (Community Initials)

console.warn("Community Example selected")} />
{/* MultiSelect Component */}

MultiSelect Component (Controls)

{/* Small size */} {/* Medium size */}
); }