App reorganization

This commit is contained in:
adilallo
2026-04-18 14:12:49 -06:00
parent f866d11ff8
commit e9dab04b34
288 changed files with 2698 additions and 5029 deletions
@@ -0,0 +1,106 @@
"use client";
import { useState, useEffect } from "react";
import MultiSelect from "../../../../components/controls/MultiSelect";
import type { ChipOption } from "../../../../components/controls/MultiSelect/MultiSelect.types";
import { useMessages } from "../../../../contexts/MessagesContext";
import { useCreateFlow } from "../../context/CreateFlowContext";
import { CreateFlowHeaderLockup } from "../../components/CreateFlowHeaderLockup";
import { CreateFlowTwoColumnSelectShell } from "../../components/CreateFlowTwoColumnSelectShell";
function chipRowsFromLabels(
rows: readonly { label: string }[],
): ChipOption[] {
return rows.map((row, i) => ({
id: String(i + 1),
label: row.label,
state: "unselected" as const,
}));
}
function selectedIdsFromOptions(options: ChipOption[]): string[] {
return options
.filter((o) => o.state === "selected")
.map((o) => o.id);
}
/** Create Community — Figma `20094:41317`, chips only (layout tokens shared with structure select). */
export function CommunitySizeSelectScreen() {
const m = useMessages();
const cs = m.create.communitySize;
const { markCreateFlowInteraction, updateState, state } = useCreateFlow();
const [communitySizeOptions, setCommunitySizeOptions] = useState<
ChipOption[]
>(() => {
const base = chipRowsFromLabels(cs.communitySizes);
const selected = new Set(state.selectedCommunitySizeIds ?? []);
return base.map((opt) => ({
...opt,
state: selected.has(opt.id) ? ("selected" as const) : ("unselected" as const),
}));
});
useEffect(() => {
const selected = new Set(state.selectedCommunitySizeIds ?? []);
setCommunitySizeOptions((prev) =>
prev.map((opt) =>
opt.state === "custom"
? opt
: {
...opt,
state: selected.has(opt.id)
? ("selected" as const)
: ("unselected" as const),
},
),
);
}, [state.selectedCommunitySizeIds]);
const persistSelection = (next: ChipOption[]) => {
markCreateFlowInteraction();
setCommunitySizeOptions(next);
updateState({
selectedCommunitySizeIds: selectedIdsFromOptions(next),
});
};
const handleCommunitySizeClick = (chipId: string) => {
const next: ChipOption[] = communitySizeOptions.map((opt) =>
opt.id === chipId
? {
...opt,
state:
opt.state === "selected"
? ("unselected" as const)
: ("selected" as const),
}
: opt,
);
persistSelection(next);
};
const multiSelectBlock = (
<MultiSelect
formHeader={false}
size="m"
options={communitySizeOptions}
onChipClick={handleCommunitySizeClick}
addButton={false}
/>
);
return (
<CreateFlowTwoColumnSelectShell
header={
<CreateFlowHeaderLockup
title={cs.header.title}
description={cs.header.description}
justification="left"
/>
}
>
{multiSelectBlock}
</CreateFlowTwoColumnSelectShell>
);
}
@@ -0,0 +1,350 @@
"use client";
import {
useState,
useMemo,
useEffect,
type Dispatch,
type SetStateAction,
} from "react";
import MultiSelect from "../../../../components/controls/MultiSelect";
import type { ChipOption } from "../../../../components/controls/MultiSelect/MultiSelect.types";
import { useMessages } from "../../../../contexts/MessagesContext";
import { useCreateFlow } from "../../context/CreateFlowContext";
import type { CommunityStructureChipSnapshotRow } from "../../types";
import { CreateFlowHeaderLockup } from "../../components/CreateFlowHeaderLockup";
import { CreateFlowTwoColumnSelectShell } from "../../components/CreateFlowTwoColumnSelectShell";
function createListCustomHandlers(
setList: Dispatch<SetStateAction<ChipOption[]>>,
confirmState: "unselected" | "selected",
onInteraction?: () => void,
) {
const touch = () => onInteraction?.();
return {
onAddClick: () => {
touch();
setList((prev) => [
...prev,
{ id: crypto.randomUUID(), label: "", state: "custom" },
]);
},
onCustomChipConfirm: (chipId: string, value: string) => {
touch();
setList((prev) =>
prev.map((opt) =>
opt.id === chipId
? { ...opt, label: value, state: confirmState }
: opt,
),
);
},
onCustomChipClose: (chipId: string) => {
touch();
setList((prev) => prev.filter((o) => o.id !== chipId));
},
};
}
function chipRowsFromLabels(
rows: readonly { label: string }[],
): ChipOption[] {
return rows.map((row, i) => ({
id: String(i + 1),
label: row.label,
state: "unselected" as const,
}));
}
function applySavedSelection(
options: ChipOption[],
saved: string[] | undefined,
): ChipOption[] {
const selected = new Set(saved ?? []);
return options.map((opt) =>
opt.state === "custom"
? opt
: {
...opt,
state: selected.has(opt.id)
? ("selected" as const)
: ("unselected" as const),
},
);
}
function selectedIdsFromOptions(options: ChipOption[]): string[] {
return options
.filter((o) => o.state === "selected")
.map((o) => o.id);
}
function chipOptionsToSnapshotRows(
options: ChipOption[],
): CommunityStructureChipSnapshotRow[] {
return options.map((o) => ({
id: o.id,
label: o.label,
...(o.state !== undefined ? { state: o.state } : {}),
}));
}
/** Returns chips when a draft snapshot exists; otherwise null (use preset rows + selected ids). */
function snapshotRowsToChipOptions(
rows: CommunityStructureChipSnapshotRow[] | undefined,
): ChipOption[] | null {
if (!Array.isArray(rows) || rows.length === 0) return null;
return rows.map((r) => ({
id: r.id,
label: r.label,
...(r.state !== undefined
? { state: r.state as ChipOption["state"] }
: {}),
}));
}
/** Create Community step 3 — Figma `20094:18244` (responsive grid + column caps via `createFlowLayoutTokens`). */
export function CommunityStructureSelectScreen() {
const m = useMessages();
const cs = m.create.communityStructure;
const { markCreateFlowInteraction, updateState, state } = useCreateFlow();
const [organizationTypeOptions, setOrganizationTypeOptions] = useState<
ChipOption[]
>(() => {
const fromSnap = snapshotRowsToChipOptions(
state.communityStructureChipSnapshots?.organizationTypes,
);
if (fromSnap) return fromSnap;
return applySavedSelection(
chipRowsFromLabels(cs.organizationTypes),
state.selectedOrganizationTypeIds,
);
});
const [scaleOptions, setScaleOptions] = useState<ChipOption[]>(() => {
const fromSnap = snapshotRowsToChipOptions(
state.communityStructureChipSnapshots?.scale,
);
if (fromSnap) return fromSnap;
return applySavedSelection(
chipRowsFromLabels(cs.scaleOptions),
state.selectedScaleIds,
);
});
const [maturityOptions, setMaturityOptions] = useState<ChipOption[]>(() => {
const fromSnap = snapshotRowsToChipOptions(
state.communityStructureChipSnapshots?.maturity,
);
if (fromSnap) return fromSnap;
return applySavedSelection(
chipRowsFromLabels(cs.maturityOptions),
state.selectedMaturityIds,
);
});
useEffect(() => {
const fromSnap = snapshotRowsToChipOptions(
state.communityStructureChipSnapshots?.organizationTypes,
);
if (fromSnap) {
setOrganizationTypeOptions(fromSnap);
return;
}
setOrganizationTypeOptions((prev) =>
applySavedSelection(prev, state.selectedOrganizationTypeIds),
);
}, [
state.communityStructureChipSnapshots?.organizationTypes,
state.selectedOrganizationTypeIds,
]);
useEffect(() => {
const fromSnap = snapshotRowsToChipOptions(
state.communityStructureChipSnapshots?.scale,
);
if (fromSnap) {
setScaleOptions(fromSnap);
return;
}
setScaleOptions((prev) => applySavedSelection(prev, state.selectedScaleIds));
}, [
state.communityStructureChipSnapshots?.scale,
state.selectedScaleIds,
]);
useEffect(() => {
const fromSnap = snapshotRowsToChipOptions(
state.communityStructureChipSnapshots?.maturity,
);
if (fromSnap) {
setMaturityOptions(fromSnap);
return;
}
setMaturityOptions((prev) =>
applySavedSelection(prev, state.selectedMaturityIds),
);
}, [
state.communityStructureChipSnapshots?.maturity,
state.selectedMaturityIds,
]);
const organizationCustomHandlers = useMemo(
() =>
createListCustomHandlers(
setOrganizationTypeOptions,
"unselected",
markCreateFlowInteraction,
),
[markCreateFlowInteraction],
);
const scaleCustomHandlers = useMemo(
() =>
createListCustomHandlers(
setScaleOptions,
"unselected",
markCreateFlowInteraction,
),
[markCreateFlowInteraction],
);
const maturityCustomHandlers = useMemo(
() =>
createListCustomHandlers(
setMaturityOptions,
"unselected",
markCreateFlowInteraction,
),
[markCreateFlowInteraction],
);
const persistOrg = (next: ChipOption[]) => {
markCreateFlowInteraction();
setOrganizationTypeOptions(next);
updateState({
selectedOrganizationTypeIds: selectedIdsFromOptions(next),
communityStructureChipSnapshots: {
organizationTypes: chipOptionsToSnapshotRows(next),
},
});
};
const persistScale = (next: ChipOption[]) => {
markCreateFlowInteraction();
setScaleOptions(next);
updateState({
selectedScaleIds: selectedIdsFromOptions(next),
communityStructureChipSnapshots: {
scale: chipOptionsToSnapshotRows(next),
},
});
};
const persistMaturity = (next: ChipOption[]) => {
markCreateFlowInteraction();
setMaturityOptions(next);
updateState({
selectedMaturityIds: selectedIdsFromOptions(next),
communityStructureChipSnapshots: {
maturity: chipOptionsToSnapshotRows(next),
},
});
};
const handleOrganizationTypeClick = (chipId: string) => {
persistOrg(
organizationTypeOptions.map((opt) =>
opt.id === chipId
? {
...opt,
state:
opt.state === "selected"
? ("unselected" as const)
: ("selected" as const),
}
: opt,
),
);
};
const handleScaleClick = (chipId: string) => {
persistScale(
scaleOptions.map((opt) =>
opt.id === chipId
? {
...opt,
state:
opt.state === "selected"
? ("unselected" as const)
: ("selected" as const),
}
: opt,
),
);
};
const handleMaturityClick = (chipId: string) => {
persistMaturity(
maturityOptions.map((opt) =>
opt.id === chipId
? {
...opt,
state:
opt.state === "selected"
? ("unselected" as const)
: ("selected" as const),
}
: opt,
),
);
};
const multiSelectBlock = (
<>
<MultiSelect
label={cs.organizationMultiSelect.label}
showHelpIcon
size="s"
options={organizationTypeOptions}
onChipClick={handleOrganizationTypeClick}
{...organizationCustomHandlers}
addButton
addButtonText={cs.organizationMultiSelect.addButtonText}
/>
<MultiSelect
label={cs.scaleMultiSelect.label}
showHelpIcon
size="s"
options={scaleOptions}
onChipClick={handleScaleClick}
{...scaleCustomHandlers}
addButton
addButtonText={cs.scaleMultiSelect.addButtonText}
/>
<MultiSelect
label={cs.maturityMultiSelect.label}
showHelpIcon
size="s"
options={maturityOptions}
onChipClick={handleMaturityClick}
{...maturityCustomHandlers}
addButton
addButtonText={cs.maturityMultiSelect.addButtonText}
/>
</>
);
return (
<CreateFlowTwoColumnSelectShell
header={
<CreateFlowHeaderLockup
title={cs.header.title}
description={cs.header.description}
justification="left"
/>
}
>
{multiSelectBlock}
</CreateFlowTwoColumnSelectShell>
);
}
@@ -0,0 +1,98 @@
"use client";
import { useState } from "react";
import MultiSelect from "../../../../components/controls/MultiSelect";
import Alert from "../../../../components/modals/Alert";
import type { ChipOption } from "../../../../components/controls/MultiSelect/MultiSelect.types";
import { useTranslation } from "../../../../contexts/MessagesContext";
import { useCreateFlow } from "../../context/CreateFlowContext";
import { CreateFlowHeaderLockup } from "../../components/CreateFlowHeaderLockup";
import { CreateFlowStepShell } from "../../components/CreateFlowStepShell";
import { CREATE_FLOW_MD_UP_COLUMN_MAX_CLASS } from "../../components/createFlowLayoutTokens";
export function ConfirmStakeholdersScreen() {
const { markCreateFlowInteraction } = useCreateFlow();
const t = useTranslation("create.confirmStakeholders");
const [toastDismissed, setToastDismissed] = useState(false);
const [stakeholderOptions, setStakeholderOptions] = useState<ChipOption[]>(
[],
);
const handleAddStakeholder = () => {
markCreateFlowInteraction();
setStakeholderOptions((prev) => [
...prev,
{ id: crypto.randomUUID(), label: "", state: "custom" },
]);
};
const handleCustomChipConfirm = (chipId: string, value: string) => {
markCreateFlowInteraction();
setStakeholderOptions((prev) =>
prev.map((opt) =>
opt.id === chipId ? { ...opt, label: value, state: "selected" } : opt,
),
);
};
const handleCustomChipClose = (chipId: string) => {
markCreateFlowInteraction();
setStakeholderOptions((prev) => prev.filter((opt) => opt.id !== chipId));
};
const handleChipClick = (chipId: string) => {
markCreateFlowInteraction();
setStakeholderOptions((prev) => prev.filter((opt) => opt.id !== chipId));
};
return (
<>
<CreateFlowStepShell
variant="centeredNarrowBottomPad"
contentTopBelowMd="space-1400"
>
<div
className={`flex flex-col items-start gap-[var(--measures-spacing-300,12px)] ${CREATE_FLOW_MD_UP_COLUMN_MAX_CLASS}`}
>
<div className="flex w-full flex-col gap-[var(--measures-spacing-200,8px)] py-[12px]">
<CreateFlowHeaderLockup
title={t("title")}
description={t("description")}
justification="left"
/>
</div>
<MultiSelect
formHeader={false}
showHelpIcon={false}
size="s"
options={stakeholderOptions}
onChipClick={handleChipClick}
onAddClick={handleAddStakeholder}
onCustomChipConfirm={handleCustomChipConfirm}
onCustomChipClose={handleCustomChipClose}
addButton
addButtonText={t("addStakeholder")}
/>
</div>
</CreateFlowStepShell>
{!toastDismissed && (
<div
className="fixed bottom-[5.25rem] left-1/2 z-10 w-[min(640px,calc(100%-2.5rem))] max-w-[640px] -translate-x-1/2 md:bottom-[5.5rem]"
role="status"
aria-live="polite"
>
<Alert
type="banner"
status="positive"
title={t("draftToastTitle")}
hasLeadingIcon={false}
hasBodyText={false}
onClose={() => setToastDismissed(true)}
className="w-full !px-[var(--space-600,24px)] !py-[var(--space-400,16px)] md:!py-4"
/>
</div>
)}
</>
);
}
@@ -0,0 +1,401 @@
"use client";
import { useState, useEffect, useCallback, useMemo } from "react";
import MultiSelect from "../../../../components/controls/MultiSelect";
import type { ChipOption } from "../../../../components/controls/MultiSelect/MultiSelect.types";
import TextArea from "../../../../components/controls/TextArea";
import Create from "../../../../components/modals/Create";
import ContentLockup from "../../../../components/type/ContentLockup";
import { useMessages } from "../../../../contexts/MessagesContext";
import { useCreateFlow } from "../../context/CreateFlowContext";
import type { CommunityStructureChipSnapshotRow } from "../../types";
import { CreateFlowHeaderLockup } from "../../components/CreateFlowHeaderLockup";
import { CreateFlowTwoColumnSelectShell } from "../../components/CreateFlowTwoColumnSelectShell";
const MAX_CORE_VALUES = 5;
type ModalSession = "pending" | "editing";
/** Row in `coreValues.json` `values` — string (legacy) or `{ label, meaning, signals }`. */
type CoreValuePresetJson =
| string
| { label: string; meaning?: string; signals?: string };
type CoreValuePreset = {
label: string;
meaning: string;
signals: string;
};
function normalizeCoreValuePresets(
values: readonly CoreValuePresetJson[],
): CoreValuePreset[] {
return values.map((v) => {
if (typeof v === "string") {
return { label: v, meaning: "", signals: "" };
}
return {
label: v.label,
meaning: typeof v.meaning === "string" ? v.meaning : "",
signals: typeof v.signals === "string" ? v.signals : "",
};
});
}
function chipRowsFromPresets(presets: readonly CoreValuePreset[]): ChipOption[] {
return presets.map((row, i) => ({
id: String(i + 1),
label: row.label,
state: "unselected" as const,
}));
}
function applySavedSelection(
options: ChipOption[],
saved: string[] | undefined,
): ChipOption[] {
const selected = new Set(saved ?? []);
return options.map((opt) =>
opt.state === "custom"
? opt
: {
...opt,
state: selected.has(opt.id)
? ("selected" as const)
: ("unselected" as const),
},
);
}
function selectedIdsFromOptions(options: ChipOption[]): string[] {
return options
.filter((o) => o.state === "selected")
.map((o) => o.id);
}
function chipOptionsToSnapshotRows(
options: ChipOption[],
): CommunityStructureChipSnapshotRow[] {
return options.map((o) => ({
id: o.id,
label: o.label,
...(o.state !== undefined ? { state: o.state } : {}),
}));
}
function snapshotRowsToChipOptions(
rows: CommunityStructureChipSnapshotRow[] | undefined,
): ChipOption[] | null {
if (!Array.isArray(rows) || rows.length === 0) return null;
return rows.map((r) => ({
id: r.id,
label: r.label,
...(r.state !== undefined
? { state: r.state as ChipOption["state"] }
: {}),
}));
}
/** Create Custom — Core Values (Figma `20264:68378`). Up to five selections; preset list + custom chips. */
export function CoreValuesSelectScreen() {
const m = useMessages();
const cv = m.create.coreValues;
const presets = useMemo(
() => normalizeCoreValuePresets(cv.values as CoreValuePresetJson[]),
[cv.values],
);
const { markCreateFlowInteraction, updateState, state } = useCreateFlow();
const [coreValueOptions, setCoreValueOptions] = useState<ChipOption[]>(
() => {
const fromSnap = snapshotRowsToChipOptions(state.coreValuesChipsSnapshot);
if (fromSnap) return fromSnap;
return applySavedSelection(
chipRowsFromPresets(presets),
state.selectedCoreValueIds,
);
},
);
const [activeModalChipId, setActiveModalChipId] = useState<string | null>(
null,
);
const [modalSession, setModalSession] = useState<ModalSession | null>(null);
const [draftMeaning, setDraftMeaning] = useState("");
const [draftSignals, setDraftSignals] = useState("");
useEffect(() => {
const fromSnap = snapshotRowsToChipOptions(state.coreValuesChipsSnapshot);
if (fromSnap) {
setCoreValueOptions(fromSnap);
return;
}
setCoreValueOptions((prev) =>
applySavedSelection(prev, state.selectedCoreValueIds),
);
}, [state.coreValuesChipsSnapshot, state.selectedCoreValueIds]);
/** Sync chips to create-flow draft. Never call `updateState` from inside a `setCoreValueOptions` updater — defer with `queueMicrotask`. */
const syncCoreValuesToDraft = useCallback(
(next: ChipOption[]) => {
updateState({
selectedCoreValueIds: selectedIdsFromOptions(next),
coreValuesChipsSnapshot: chipOptionsToSnapshotRows(next),
});
},
[updateState],
);
const persistCoreValues = useCallback(
(next: ChipOption[]) => {
markCreateFlowInteraction();
setCoreValueOptions(next);
syncCoreValuesToDraft(next);
},
[markCreateFlowInteraction, syncCoreValuesToDraft],
);
/** Default meaning/signals from `coreValues.json` `values` for each preset label. */
const getPresetTexts = useCallback(
(valueLabel: string): { meaning: string; signals: string } => {
const row = presets.find((p) => p.label === valueLabel);
if (!row) return { meaning: "", signals: "" };
return { meaning: row.meaning, signals: row.signals };
},
[presets],
);
const getInitialTexts = useCallback(
(chipId: string, valueLabel: string) => {
const saved = state.coreValueDetailsByChipId?.[chipId];
const preset = getPresetTexts(valueLabel);
return {
meaning: saved?.meaning ?? preset.meaning,
signals: saved?.signals ?? preset.signals,
};
},
[state.coreValueDetailsByChipId, getPresetTexts],
);
const openModal = useCallback(
(chipId: string, session: ModalSession, valueLabel: string) => {
const initial = getInitialTexts(chipId, valueLabel);
setDraftMeaning(initial.meaning);
setDraftSignals(initial.signals);
setActiveModalChipId(chipId);
setModalSession(session);
markCreateFlowInteraction();
},
[getInitialTexts, markCreateFlowInteraction],
);
const handleModalDismiss = useCallback(() => {
if (activeModalChipId && modalSession === "pending") {
const next = coreValueOptions.map((opt) =>
opt.id === activeModalChipId
? { ...opt, state: "unselected" as const }
: opt,
);
persistCoreValues(next);
}
setActiveModalChipId(null);
setModalSession(null);
}, [activeModalChipId, modalSession, coreValueOptions, persistCoreValues]);
const handleModalConfirm = useCallback(() => {
if (!activeModalChipId) return;
markCreateFlowInteraction();
updateState({
coreValueDetailsByChipId: {
[activeModalChipId]: {
meaning: draftMeaning,
signals: draftSignals,
},
},
});
setActiveModalChipId(null);
setModalSession(null);
}, [
activeModalChipId,
draftMeaning,
draftSignals,
markCreateFlowInteraction,
updateState,
]);
const handleChipClick = (chipId: string) => {
const target = coreValueOptions.find((o) => o.id === chipId);
if (!target || target.state === "custom") return;
const selectedCount = coreValueOptions.filter(
(o) => o.state === "selected",
).length;
if (target.state === "selected") {
const next: ChipOption[] = coreValueOptions.map((opt) =>
opt.id === chipId
? { ...opt, state: "unselected" as const }
: opt,
);
persistCoreValues(next);
return;
}
if (selectedCount >= MAX_CORE_VALUES) return;
const next: ChipOption[] = coreValueOptions.map((opt) =>
opt.id === chipId
? { ...opt, state: "selected" as const }
: opt,
);
persistCoreValues(next);
openModal(chipId, "pending", target.label);
};
const addHandlers = {
onAddClick: () => {
markCreateFlowInteraction();
setCoreValueOptions((prev) => {
const next: ChipOption[] = [
...prev,
{ id: crypto.randomUUID(), label: "", state: "custom" },
];
queueMicrotask(() => syncCoreValuesToDraft(next));
return next;
});
},
onCustomChipConfirm: (chipId: string, value: string) => {
markCreateFlowInteraction();
setCoreValueOptions((prev) => {
const withLabel = prev.map((opt) =>
opt.id === chipId
? { ...opt, label: value, state: "unselected" as const }
: opt,
);
const selectedCount = withLabel.filter(
(o) => o.state === "selected",
).length;
const canSelect = selectedCount < MAX_CORE_VALUES;
const next = canSelect
? withLabel.map((opt) =>
opt.id === chipId
? { ...opt, state: "selected" as const }
: opt,
)
: withLabel;
queueMicrotask(() => {
syncCoreValuesToDraft(next);
if (canSelect) {
openModal(chipId, "pending", value);
} else {
openModal(chipId, "editing", value);
}
});
return next;
});
},
onCustomChipClose: (chipId: string) => {
markCreateFlowInteraction();
setCoreValueOptions((prev) => {
const next = prev.filter((o) => o.id !== chipId);
queueMicrotask(() => syncCoreValuesToDraft(next));
return next;
});
},
};
const modalChipLabel =
coreValueOptions.find((o) => o.id === activeModalChipId)?.label ?? "";
const description = (
<>
<span className="leading-[1.3] text-[color:var(--color-content-default-tertiary,#b4b4b4)]">
{cv.header.descriptionLead}{" "}
</span>
<button
type="button"
onClick={addHandlers.onAddClick}
className="cursor-pointer font-inter font-normal leading-[1.3] text-[color:var(--color-content-default-tertiary,#b4b4b4)] underline decoration-solid underline-offset-[3px] hover:opacity-90"
>
{cv.header.addLink}
</button>
<span className="leading-[1.3] text-[color:var(--color-content-default-tertiary,#b4b4b4)]">
{" "}
{cv.header.descriptionTrail}
</span>
</>
);
const detailModal = cv.detailModal;
return (
<CreateFlowTwoColumnSelectShell
lgVerticalAlign="start"
header={
<CreateFlowHeaderLockup
title={cv.header.title}
description={description}
justification="left"
/>
}
>
<MultiSelect
formHeader={false}
size="m"
options={coreValueOptions}
onChipClick={handleChipClick}
onAddClick={addHandlers.onAddClick}
onCustomChipConfirm={addHandlers.onCustomChipConfirm}
onCustomChipClose={addHandlers.onCustomChipClose}
addButton
addButtonText={cv.multiSelect.addButtonText}
/>
{detailModal && (
<Create
isOpen={activeModalChipId !== null}
onClose={handleModalDismiss}
backdropVariant="loginYellow"
headerContent={
<div className="bg-[var(--color-surface-default-primary)] px-[24px] py-[12px] shrink-0">
<ContentLockup
title={modalChipLabel}
description={detailModal.subtitle}
variant="modal"
alignment="left"
/>
</div>
}
showBackButton={false}
showNextButton
onNext={handleModalConfirm}
nextButtonText={detailModal.addValueButton}
ariaLabel={modalChipLabel || "Core value details"}
>
<div className="flex flex-col gap-[var(--measures-spacing-600,24px)] pb-2">
<TextArea
label={detailModal.meaningLabel}
showHelpIcon
appearance="embedded"
size="medium"
value={draftMeaning}
onChange={(e) => setDraftMeaning(e.target.value)}
rows={4}
/>
<TextArea
label={detailModal.signalsLabel}
showHelpIcon
appearance="embedded"
size="medium"
value={draftSignals}
onChange={(e) => setDraftSignals(e.target.value)}
rows={4}
/>
</div>
</Create>
)}
</CreateFlowTwoColumnSelectShell>
);
}