mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-03 09:37:19 +01:00
Add interaction card Storybook state matrix
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
ad961227f5
commit
224741e4d1
2 files changed
+652
No files matched your search
@@ -329,6 +329,34 @@ export const acceptedSuggestedTasksInteraction = createSuggestTasksInteraction({
|
||||
},
|
||||
});
|
||||
|
||||
export const partialAcceptedSuggestedTasksInteraction = createSuggestTasksInteraction({
|
||||
id: "interaction-suggest-partial-accepted",
|
||||
status: "accepted",
|
||||
resolvedByUserId: issueThreadInteractionFixtureMeta.currentUserId,
|
||||
resolvedAt: new Date("2026-04-20T14:16:30.000Z"),
|
||||
updatedAt: new Date("2026-04-20T14:16:30.000Z"),
|
||||
result: {
|
||||
version: 1,
|
||||
createdTasks: [
|
||||
{
|
||||
clientKey: "root-design",
|
||||
issueId: "issue-created-1",
|
||||
identifier: "PAP-1713",
|
||||
title: "Prototype issue-thread interaction cards",
|
||||
},
|
||||
{
|
||||
clientKey: "child-stories",
|
||||
issueId: "issue-created-2",
|
||||
identifier: "PAP-1714",
|
||||
title: "Add Storybook coverage for acceptance and rejection states",
|
||||
parentIssueId: "issue-created-1",
|
||||
parentIdentifier: "PAP-1713",
|
||||
},
|
||||
],
|
||||
skippedClientKeys: ["child-mixed-thread", "hidden-follow-up"],
|
||||
},
|
||||
});
|
||||
|
||||
export const rejectedSuggestedTasksInteraction = createSuggestTasksInteraction({
|
||||
id: "interaction-suggest-rejected",
|
||||
status: "rejected",
|
||||
@@ -342,8 +370,92 @@ export const rejectedSuggestedTasksInteraction = createSuggestTasksInteraction({
|
||||
},
|
||||
});
|
||||
|
||||
export const expiredSuggestedTasksInteraction = createSuggestTasksInteraction({
|
||||
id: "interaction-suggest-expired",
|
||||
status: "expired",
|
||||
resolvedByAgentId: "agent-codex",
|
||||
resolvedAt: new Date("2026-04-20T14:17:30.000Z"),
|
||||
updatedAt: new Date("2026-04-20T14:17:30.000Z"),
|
||||
});
|
||||
|
||||
export const cancelledSuggestedTasksInteraction = createSuggestTasksInteraction({
|
||||
id: "interaction-suggest-cancelled",
|
||||
status: "cancelled",
|
||||
resolvedByUserId: issueThreadInteractionFixtureMeta.currentUserId,
|
||||
resolvedAt: new Date("2026-04-20T14:17:45.000Z"),
|
||||
updatedAt: new Date("2026-04-20T14:17:45.000Z"),
|
||||
});
|
||||
|
||||
export const failedSuggestedTasksInteraction = createSuggestTasksInteraction({
|
||||
id: "interaction-suggest-failed",
|
||||
status: "failed",
|
||||
updatedAt: new Date("2026-04-20T14:17:55.000Z"),
|
||||
});
|
||||
|
||||
export const pendingAskUserQuestionsInteraction = createAskUserQuestionsInteraction({});
|
||||
|
||||
export const everyQuestionTypeAskUserQuestionsInteraction = createAskUserQuestionsInteraction({
|
||||
id: "interaction-questions-every-type",
|
||||
title: "Confirm rollout answers",
|
||||
summary:
|
||||
"This fixture keeps single-select, multi-select, optional, long-copy, and other free-text inputs visible in one form.",
|
||||
payload: {
|
||||
version: 1,
|
||||
title: "Rollout choices",
|
||||
submitLabel: "Submit rollout answers",
|
||||
questions: [
|
||||
{
|
||||
id: "free-text",
|
||||
prompt: "What extra context should the implementer carry into the rollout?",
|
||||
helpText:
|
||||
"Use the Other field for free-form text. The schema still stores this as a structured question answer.",
|
||||
selectionMode: "single",
|
||||
required: true,
|
||||
options: [
|
||||
{
|
||||
id: "use-other",
|
||||
label: "I'll write the answer in Other",
|
||||
description: "Exercises the free-text answer path without adding a separate schema shape.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "single-select",
|
||||
prompt: "Which rollout path should be treated as the default?",
|
||||
selectionMode: "single",
|
||||
required: true,
|
||||
options: [
|
||||
{ id: "guarded", label: "Guarded rollout", description: "Ship behind the existing flag first." },
|
||||
{ id: "direct", label: "Direct rollout", description: "Enable the behavior immediately." },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "multi-select",
|
||||
prompt: "Which review signals should be included in the handoff?",
|
||||
helpText:
|
||||
"This intentionally uses longer copy so the option rows prove wrapping behavior in the card.",
|
||||
selectionMode: "multi",
|
||||
required: true,
|
||||
options: [
|
||||
{ id: "storybook", label: "Storybook snapshots", description: "Reference the visual matrix directly." },
|
||||
{ id: "unit-tests", label: "Focused unit tests", description: "Keep the regression proof close to the component." },
|
||||
{ id: "accessibility", label: "A11y notes", description: "Flag keyboard and screen-reader concerns while reviewing the card." },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "optional",
|
||||
prompt: "Optional: which follow-up should wait until after this change?",
|
||||
selectionMode: "multi",
|
||||
required: false,
|
||||
options: [
|
||||
{ id: "animation", label: "Micro-animation polish" },
|
||||
{ id: "copy-pass", label: "Long-form copy review" },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
export const answeredAskUserQuestionsInteraction = createAskUserQuestionsInteraction({
|
||||
id: "interaction-questions-answered",
|
||||
status: "answered",
|
||||
@@ -370,6 +482,41 @@ export const answeredAskUserQuestionsInteraction = createAskUserQuestionsInterac
|
||||
},
|
||||
});
|
||||
|
||||
export const everyQuestionTypeAnsweredAskUserQuestionsInteraction = createAskUserQuestionsInteraction({
|
||||
id: "interaction-questions-every-type-answered",
|
||||
status: "answered",
|
||||
title: everyQuestionTypeAskUserQuestionsInteraction.title,
|
||||
summary: everyQuestionTypeAskUserQuestionsInteraction.summary,
|
||||
resolvedByUserId: issueThreadInteractionFixtureMeta.currentUserId,
|
||||
resolvedAt: new Date("2026-04-20T14:24:30.000Z"),
|
||||
updatedAt: new Date("2026-04-20T14:24:30.000Z"),
|
||||
payload: everyQuestionTypeAskUserQuestionsInteraction.payload,
|
||||
result: {
|
||||
version: 1,
|
||||
answers: [
|
||||
{
|
||||
questionId: "free-text",
|
||||
optionIds: [],
|
||||
otherText: "Keep the rollout reversible until QA signs off on mobile-width cards.",
|
||||
},
|
||||
{
|
||||
questionId: "single-select",
|
||||
optionIds: ["guarded"],
|
||||
},
|
||||
{
|
||||
questionId: "multi-select",
|
||||
optionIds: ["storybook", "accessibility"],
|
||||
},
|
||||
{
|
||||
questionId: "optional",
|
||||
optionIds: [],
|
||||
},
|
||||
],
|
||||
summaryMarkdown:
|
||||
"Use a guarded rollout, include Storybook and a11y notes, and keep the free-text guidance visible.",
|
||||
},
|
||||
});
|
||||
|
||||
export const commentExpiredAskUserQuestionsInteraction = createAskUserQuestionsInteraction({
|
||||
id: "interaction-questions-expired-comment",
|
||||
status: "expired",
|
||||
@@ -385,6 +532,32 @@ export const commentExpiredAskUserQuestionsInteraction = createAskUserQuestionsI
|
||||
},
|
||||
});
|
||||
|
||||
export const cancelledAskUserQuestionsInteraction = createAskUserQuestionsInteraction({
|
||||
id: "interaction-questions-cancelled",
|
||||
status: "cancelled",
|
||||
resolvedByUserId: issueThreadInteractionFixtureMeta.currentUserId,
|
||||
resolvedAt: new Date("2026-04-20T14:25:30.000Z"),
|
||||
updatedAt: new Date("2026-04-20T14:25:30.000Z"),
|
||||
result: {
|
||||
version: 1,
|
||||
answers: [],
|
||||
cancelled: true,
|
||||
cancellationReason: "The board answered this in a later synchronous review.",
|
||||
summaryMarkdown: null,
|
||||
},
|
||||
});
|
||||
|
||||
export const failedAskUserQuestionsInteraction = createAskUserQuestionsInteraction({
|
||||
id: "interaction-questions-failed",
|
||||
status: "failed",
|
||||
updatedAt: new Date("2026-04-20T14:25:45.000Z"),
|
||||
result: {
|
||||
version: 1,
|
||||
answers: [],
|
||||
summaryMarkdown: null,
|
||||
},
|
||||
});
|
||||
|
||||
export const pendingRequestConfirmationInteraction = createRequestConfirmationInteraction({});
|
||||
|
||||
export const genericPendingRequestConfirmationInteraction = createRequestConfirmationInteraction({
|
||||
@@ -540,6 +713,14 @@ export const failedRequestConfirmationInteraction = createRequestConfirmationInt
|
||||
updatedAt: new Date("2026-04-20T14:42:00.000Z"),
|
||||
});
|
||||
|
||||
export const cancelledRequestConfirmationInteraction = createRequestConfirmationInteraction({
|
||||
id: "interaction-confirmation-cancelled",
|
||||
status: "cancelled",
|
||||
resolvedByUserId: issueThreadInteractionFixtureMeta.currentUserId,
|
||||
resolvedAt: new Date("2026-04-20T14:43:00.000Z"),
|
||||
updatedAt: new Date("2026-04-20T14:43:00.000Z"),
|
||||
});
|
||||
|
||||
export const pendingRequestCheckboxConfirmationInteraction =
|
||||
createRequestCheckboxConfirmationInteraction({});
|
||||
|
||||
@@ -642,6 +823,21 @@ export const rejectedRequestCheckboxConfirmationInteraction =
|
||||
},
|
||||
});
|
||||
|
||||
export const commentExpiredRequestCheckboxConfirmationInteraction =
|
||||
createRequestCheckboxConfirmationInteraction({
|
||||
id: "interaction-checkbox-expired-comment",
|
||||
status: "expired",
|
||||
resolvedByUserId: issueThreadInteractionFixtureMeta.currentUserId,
|
||||
resolvedAt: new Date("2026-04-20T14:50:30.000Z"),
|
||||
updatedAt: new Date("2026-04-20T14:50:30.000Z"),
|
||||
result: {
|
||||
version: 1,
|
||||
outcome: "superseded_by_comment",
|
||||
commentId: "22222222-2222-4222-8222-222222222222",
|
||||
selectedOptionIds: [],
|
||||
},
|
||||
});
|
||||
|
||||
export const staleTargetRequestCheckboxConfirmationInteraction =
|
||||
createRequestCheckboxConfirmationInteraction({
|
||||
id: "interaction-checkbox-stale",
|
||||
@@ -679,6 +875,22 @@ export const staleTargetRequestCheckboxConfirmationInteraction =
|
||||
},
|
||||
});
|
||||
|
||||
export const cancelledRequestCheckboxConfirmationInteraction =
|
||||
createRequestCheckboxConfirmationInteraction({
|
||||
id: "interaction-checkbox-cancelled",
|
||||
status: "cancelled",
|
||||
resolvedByUserId: issueThreadInteractionFixtureMeta.currentUserId,
|
||||
resolvedAt: new Date("2026-04-20T14:51:30.000Z"),
|
||||
updatedAt: new Date("2026-04-20T14:51:30.000Z"),
|
||||
});
|
||||
|
||||
export const failedRequestCheckboxConfirmationInteraction =
|
||||
createRequestCheckboxConfirmationInteraction({
|
||||
id: "interaction-checkbox-failed",
|
||||
status: "failed",
|
||||
updatedAt: new Date("2026-04-20T14:51:45.000Z"),
|
||||
});
|
||||
|
||||
export const issueThreadInteractionComments: IssueChatComment[] = [
|
||||
createComment({
|
||||
id: "comment-thread-board",
|
||||
|
||||
@@ -10,8 +10,20 @@ import {
|
||||
answeredAskUserQuestionsInteraction,
|
||||
acceptedRequestConfirmationInteraction,
|
||||
boundedRequestCheckboxConfirmationInteraction,
|
||||
cancelledAskUserQuestionsInteraction,
|
||||
cancelledRequestCheckboxConfirmationInteraction,
|
||||
cancelledRequestConfirmationInteraction,
|
||||
cancelledSuggestedTasksInteraction,
|
||||
commentExpiredAskUserQuestionsInteraction,
|
||||
commentExpiredRequestCheckboxConfirmationInteraction,
|
||||
commentExpiredRequestConfirmationInteraction,
|
||||
everyQuestionTypeAnsweredAskUserQuestionsInteraction,
|
||||
everyQuestionTypeAskUserQuestionsInteraction,
|
||||
expiredSuggestedTasksInteraction,
|
||||
failedAskUserQuestionsInteraction,
|
||||
failedRequestCheckboxConfirmationInteraction,
|
||||
failedRequestConfirmationInteraction,
|
||||
failedSuggestedTasksInteraction,
|
||||
genericPendingRequestConfirmationInteraction,
|
||||
issueThreadInteractionComments,
|
||||
issueThreadInteractionEvents,
|
||||
@@ -21,6 +33,7 @@ import {
|
||||
manyOptionsRequestCheckboxConfirmationInteraction,
|
||||
mixedIssueThreadInteractions,
|
||||
optionalDeclineRequestConfirmationInteraction,
|
||||
partialAcceptedSuggestedTasksInteraction,
|
||||
pendingAskUserQuestionsInteraction,
|
||||
pendingRequestCheckboxConfirmationInteraction,
|
||||
pendingRequestConfirmationInteraction,
|
||||
@@ -39,6 +52,7 @@ import type {
|
||||
RequestCheckboxConfirmationInteraction,
|
||||
RequestConfirmationInteraction,
|
||||
SuggestTasksInteraction,
|
||||
IssueThreadInteraction,
|
||||
} from "@/lib/issue-thread-interactions";
|
||||
import { storybookAgentMap } from "../fixtures/paperclipData";
|
||||
|
||||
@@ -97,6 +111,39 @@ function ScenarioCard({
|
||||
);
|
||||
}
|
||||
|
||||
function StaticInteractionCard({
|
||||
interaction,
|
||||
}: {
|
||||
interaction: IssueThreadInteraction;
|
||||
}) {
|
||||
return (
|
||||
<IssueThreadInteractionCard
|
||||
interaction={interaction}
|
||||
agentMap={storybookAgentMap}
|
||||
currentUserId={issueThreadInteractionFixtureMeta.currentUserId}
|
||||
userLabelMap={boardUserLabels}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function MobileScenario({
|
||||
title,
|
||||
interaction,
|
||||
}: {
|
||||
title: string;
|
||||
interaction: IssueThreadInteraction;
|
||||
}) {
|
||||
return (
|
||||
<StoryFrame>
|
||||
<div className="mx-auto w-[390px] max-w-full">
|
||||
<ScenarioCard title={title} description="390px-wide mobile render.">
|
||||
<StaticInteractionCard interaction={interaction} />
|
||||
</ScenarioCard>
|
||||
</div>
|
||||
</StoryFrame>
|
||||
);
|
||||
}
|
||||
|
||||
function InteractiveSuggestedTasksCard() {
|
||||
const [interaction, setInteraction] = useState<SuggestTasksInteraction>(
|
||||
pendingSuggestedTasksInteraction,
|
||||
@@ -136,6 +183,100 @@ function InteractiveSuggestedTasksCard() {
|
||||
);
|
||||
}
|
||||
|
||||
function AutoClickInteractionCard({
|
||||
buttonText,
|
||||
children,
|
||||
}: {
|
||||
buttonText: string;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
const ref = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const button = Array.from(ref.current?.querySelectorAll("button") ?? [])
|
||||
.find((candidate) => candidate.textContent?.includes(buttonText));
|
||||
button?.click();
|
||||
}, [buttonText]);
|
||||
|
||||
return <div ref={ref}>{children}</div>;
|
||||
}
|
||||
|
||||
function InFlightSuggestedTasksCard() {
|
||||
return (
|
||||
<AutoClickInteractionCard buttonText="Accept drafts">
|
||||
<IssueThreadInteractionCard
|
||||
interaction={pendingSuggestedTasksInteraction}
|
||||
agentMap={storybookAgentMap}
|
||||
currentUserId={issueThreadInteractionFixtureMeta.currentUserId}
|
||||
userLabelMap={boardUserLabels}
|
||||
onAcceptInteraction={() => new Promise(() => {})}
|
||||
onRejectInteraction={() => undefined}
|
||||
/>
|
||||
</AutoClickInteractionCard>
|
||||
);
|
||||
}
|
||||
|
||||
function InFlightAskUserQuestionsCard() {
|
||||
const readyInteraction: AskUserQuestionsInteraction = {
|
||||
...pendingAskUserQuestionsInteraction,
|
||||
result: {
|
||||
version: 1,
|
||||
answers: [
|
||||
{
|
||||
questionId: "collapse-depth",
|
||||
optionIds: ["visible-root"],
|
||||
},
|
||||
{
|
||||
questionId: "post-submit-summary",
|
||||
optionIds: ["answers-inline"],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<AutoClickInteractionCard buttonText="Send answers">
|
||||
<IssueThreadInteractionCard
|
||||
interaction={readyInteraction}
|
||||
agentMap={storybookAgentMap}
|
||||
currentUserId={issueThreadInteractionFixtureMeta.currentUserId}
|
||||
userLabelMap={boardUserLabels}
|
||||
onSubmitInteractionAnswers={() => new Promise(() => {})}
|
||||
/>
|
||||
</AutoClickInteractionCard>
|
||||
);
|
||||
}
|
||||
|
||||
function InFlightRequestConfirmationCard() {
|
||||
return (
|
||||
<AutoClickInteractionCard buttonText="Approve plan">
|
||||
<IssueThreadInteractionCard
|
||||
interaction={pendingRequestConfirmationInteraction}
|
||||
agentMap={storybookAgentMap}
|
||||
currentUserId={issueThreadInteractionFixtureMeta.currentUserId}
|
||||
userLabelMap={boardUserLabels}
|
||||
onAcceptInteraction={() => new Promise(() => {})}
|
||||
onRejectInteraction={() => undefined}
|
||||
/>
|
||||
</AutoClickInteractionCard>
|
||||
);
|
||||
}
|
||||
|
||||
function InFlightCheckboxConfirmationCard() {
|
||||
return (
|
||||
<AutoClickInteractionCard buttonText="Delete selected">
|
||||
<IssueThreadInteractionCard
|
||||
interaction={pendingRequestCheckboxConfirmationInteraction}
|
||||
agentMap={storybookAgentMap}
|
||||
currentUserId={issueThreadInteractionFixtureMeta.currentUserId}
|
||||
userLabelMap={boardUserLabels}
|
||||
onAcceptInteraction={() => new Promise(() => {})}
|
||||
onRejectInteraction={() => undefined}
|
||||
/>
|
||||
</AutoClickInteractionCard>
|
||||
);
|
||||
}
|
||||
|
||||
function buildAnsweredInteraction(
|
||||
answers: AskUserQuestionsAnswer[],
|
||||
): AskUserQuestionsInteraction {
|
||||
@@ -314,6 +455,19 @@ export const SuggestedTasksAccepted: Story = {
|
||||
),
|
||||
};
|
||||
|
||||
export const SuggestedTasksPartiallyAccepted: Story = {
|
||||
render: () => (
|
||||
<StoryFrame>
|
||||
<ScenarioCard
|
||||
title="Partially accepted suggested tasks"
|
||||
description="Some suggested tasks became issues while the rest stayed marked as skipped."
|
||||
>
|
||||
<StaticInteractionCard interaction={partialAcceptedSuggestedTasksInteraction} />
|
||||
</ScenarioCard>
|
||||
</StoryFrame>
|
||||
),
|
||||
};
|
||||
|
||||
export const SuggestedTasksRejected: Story = {
|
||||
render: () => (
|
||||
<StoryFrame>
|
||||
@@ -332,6 +486,45 @@ export const SuggestedTasksRejected: Story = {
|
||||
),
|
||||
};
|
||||
|
||||
export const SuggestedTasksExpired: Story = {
|
||||
render: () => (
|
||||
<StoryFrame>
|
||||
<ScenarioCard
|
||||
title="Expired suggested tasks"
|
||||
description="The suggestion is no longer actionable, but the proposed task tree remains readable."
|
||||
>
|
||||
<StaticInteractionCard interaction={expiredSuggestedTasksInteraction} />
|
||||
</ScenarioCard>
|
||||
</StoryFrame>
|
||||
),
|
||||
};
|
||||
|
||||
export const SuggestedTasksCancelled: Story = {
|
||||
render: () => (
|
||||
<StoryFrame>
|
||||
<ScenarioCard
|
||||
title="Cancelled suggested tasks"
|
||||
description="The cancelled state keeps the draft artifact visible without action controls."
|
||||
>
|
||||
<StaticInteractionCard interaction={cancelledSuggestedTasksInteraction} />
|
||||
</ScenarioCard>
|
||||
</StoryFrame>
|
||||
),
|
||||
};
|
||||
|
||||
export const SuggestedTasksFailed: Story = {
|
||||
render: () => (
|
||||
<StoryFrame>
|
||||
<ScenarioCard
|
||||
title="Failed suggested tasks"
|
||||
description="Failed resolution removes controls while preserving the task tree for inspection."
|
||||
>
|
||||
<StaticInteractionCard interaction={failedSuggestedTasksInteraction} />
|
||||
</ScenarioCard>
|
||||
</StoryFrame>
|
||||
),
|
||||
};
|
||||
|
||||
export const AskUserQuestionsPending: Story = {
|
||||
render: () => (
|
||||
<StoryFrame>
|
||||
@@ -345,6 +538,26 @@ export const AskUserQuestionsPending: Story = {
|
||||
),
|
||||
};
|
||||
|
||||
export const AskUserQuestionsEveryQuestionType: Story = {
|
||||
render: () => (
|
||||
<StoryFrame>
|
||||
<ScenarioCard
|
||||
title="Every question input shape"
|
||||
description="Single-select, multi-select, optional, long-copy, and Other free-text paths render together."
|
||||
>
|
||||
<IssueThreadInteractionCard
|
||||
interaction={everyQuestionTypeAskUserQuestionsInteraction}
|
||||
agentMap={storybookAgentMap}
|
||||
currentUserId={issueThreadInteractionFixtureMeta.currentUserId}
|
||||
userLabelMap={boardUserLabels}
|
||||
onSubmitInteractionAnswers={() => undefined}
|
||||
onCancelInteraction={() => undefined}
|
||||
/>
|
||||
</ScenarioCard>
|
||||
</StoryFrame>
|
||||
),
|
||||
};
|
||||
|
||||
export const AskUserQuestionsAnswered: Story = {
|
||||
render: () => (
|
||||
<StoryFrame>
|
||||
@@ -363,6 +576,58 @@ export const AskUserQuestionsAnswered: Story = {
|
||||
),
|
||||
};
|
||||
|
||||
export const AskUserQuestionsEveryQuestionTypeAnswered: Story = {
|
||||
render: () => (
|
||||
<StoryFrame>
|
||||
<ScenarioCard
|
||||
title="Answered every question input shape"
|
||||
description="Answered summaries include selected choices, empty optional answers, and Other free text."
|
||||
>
|
||||
<StaticInteractionCard interaction={everyQuestionTypeAnsweredAskUserQuestionsInteraction} />
|
||||
</ScenarioCard>
|
||||
</StoryFrame>
|
||||
),
|
||||
};
|
||||
|
||||
export const AskUserQuestionsExpiredByComment: Story = {
|
||||
render: () => (
|
||||
<StoryFrame>
|
||||
<ScenarioCard
|
||||
title="Question form expired by comment"
|
||||
description="A later board comment superseded the unanswered question request."
|
||||
>
|
||||
<StaticInteractionCard interaction={commentExpiredAskUserQuestionsInteraction} />
|
||||
</ScenarioCard>
|
||||
</StoryFrame>
|
||||
),
|
||||
};
|
||||
|
||||
export const AskUserQuestionsCancelled: Story = {
|
||||
render: () => (
|
||||
<StoryFrame>
|
||||
<ScenarioCard
|
||||
title="Cancelled question form"
|
||||
description="Cancellation records why no answer set was captured."
|
||||
>
|
||||
<StaticInteractionCard interaction={cancelledAskUserQuestionsInteraction} />
|
||||
</ScenarioCard>
|
||||
</StoryFrame>
|
||||
),
|
||||
};
|
||||
|
||||
export const AskUserQuestionsFailed: Story = {
|
||||
render: () => (
|
||||
<StoryFrame>
|
||||
<ScenarioCard
|
||||
title="Failed question form"
|
||||
description="The failed state is read-only and keeps each unanswered prompt visible."
|
||||
>
|
||||
<StaticInteractionCard interaction={failedAskUserQuestionsInteraction} />
|
||||
</ScenarioCard>
|
||||
</StoryFrame>
|
||||
),
|
||||
};
|
||||
|
||||
export const RequestConfirmationPending: Story = {
|
||||
render: () => (
|
||||
<StoryFrame>
|
||||
@@ -570,6 +835,19 @@ export const RequestConfirmationFailed: Story = {
|
||||
),
|
||||
};
|
||||
|
||||
export const RequestConfirmationCancelled: Story = {
|
||||
render: () => (
|
||||
<StoryFrame>
|
||||
<ScenarioCard
|
||||
title="Cancelled request confirmation"
|
||||
description="A cancelled confirmation has the same shell language as other inactive states."
|
||||
>
|
||||
<StaticInteractionCard interaction={cancelledRequestConfirmationInteraction} />
|
||||
</ScenarioCard>
|
||||
</StoryFrame>
|
||||
),
|
||||
};
|
||||
|
||||
export const RequestConfirmationAccepted = RequestConfirmationConfirmed;
|
||||
export const RequestConfirmationRejected = RequestConfirmationDeclinedWithReason;
|
||||
|
||||
@@ -661,6 +939,19 @@ export const CheckboxConfirmationRejected: Story = {
|
||||
),
|
||||
};
|
||||
|
||||
export const CheckboxConfirmationExpiredByComment: Story = {
|
||||
render: () => (
|
||||
<StoryFrame>
|
||||
<ScenarioCard
|
||||
title="Checkbox confirmation expired by comment"
|
||||
description="A later board comment superseded the selection before it was confirmed."
|
||||
>
|
||||
<StaticInteractionCard interaction={commentExpiredRequestCheckboxConfirmationInteraction} />
|
||||
</ScenarioCard>
|
||||
</StoryFrame>
|
||||
),
|
||||
};
|
||||
|
||||
export const CheckboxConfirmationStaleTarget: Story = {
|
||||
render: () => (
|
||||
<StoryFrame>
|
||||
@@ -679,6 +970,32 @@ export const CheckboxConfirmationStaleTarget: Story = {
|
||||
),
|
||||
};
|
||||
|
||||
export const CheckboxConfirmationCancelled: Story = {
|
||||
render: () => (
|
||||
<StoryFrame>
|
||||
<ScenarioCard
|
||||
title="Cancelled checkbox confirmation"
|
||||
description="The cancelled state keeps the prompt and option context visible without controls."
|
||||
>
|
||||
<StaticInteractionCard interaction={cancelledRequestCheckboxConfirmationInteraction} />
|
||||
</ScenarioCard>
|
||||
</StoryFrame>
|
||||
),
|
||||
};
|
||||
|
||||
export const CheckboxConfirmationFailed: Story = {
|
||||
render: () => (
|
||||
<StoryFrame>
|
||||
<ScenarioCard
|
||||
title="Failed checkbox confirmation"
|
||||
description="Failed resolution shows the recovery copy used by inactive checkbox confirmations."
|
||||
>
|
||||
<StaticInteractionCard interaction={failedRequestCheckboxConfirmationInteraction} />
|
||||
</ScenarioCard>
|
||||
</StoryFrame>
|
||||
),
|
||||
};
|
||||
|
||||
export const CheckboxConfirmationManyOptions: Story = {
|
||||
render: () => (
|
||||
<StoryFrame>
|
||||
@@ -696,6 +1013,129 @@ export const CheckboxConfirmationManyOptions: Story = {
|
||||
),
|
||||
};
|
||||
|
||||
export const InteractionInFlightStates: Story = {
|
||||
render: () => (
|
||||
<StoryFrame>
|
||||
<Section eyebrow="In-flight" title="Submitting states where the card can represent a pending action">
|
||||
<div className="grid gap-6 xl:grid-cols-2">
|
||||
<ScenarioCard
|
||||
title="Suggested tasks accepting"
|
||||
description="The primary action shows a loading state while acceptance is in flight."
|
||||
>
|
||||
<InFlightSuggestedTasksCard />
|
||||
</ScenarioCard>
|
||||
<ScenarioCard
|
||||
title="Questions submitting"
|
||||
description="The submit button shows a loading state while answers are being sent."
|
||||
>
|
||||
<InFlightAskUserQuestionsCard />
|
||||
</ScenarioCard>
|
||||
<ScenarioCard
|
||||
title="Confirmation accepting"
|
||||
description="The confirmation button stays disabled and shows progress."
|
||||
>
|
||||
<InFlightRequestConfirmationCard />
|
||||
</ScenarioCard>
|
||||
<ScenarioCard
|
||||
title="Checkbox confirmation accepting"
|
||||
description="Selection confirmation shows progress while the response is unresolved."
|
||||
>
|
||||
<InFlightCheckboxConfirmationCard />
|
||||
</ScenarioCard>
|
||||
</div>
|
||||
</Section>
|
||||
</StoryFrame>
|
||||
),
|
||||
};
|
||||
|
||||
export const SuggestedTasksMobile390: Story = {
|
||||
render: () => (
|
||||
<MobileScenario
|
||||
title="Suggested tasks mobile"
|
||||
interaction={pendingSuggestedTasksInteraction}
|
||||
/>
|
||||
),
|
||||
};
|
||||
|
||||
export const AskUserQuestionsMobile390: Story = {
|
||||
render: () => (
|
||||
<MobileScenario
|
||||
title="Question form mobile"
|
||||
interaction={everyQuestionTypeAskUserQuestionsInteraction}
|
||||
/>
|
||||
),
|
||||
};
|
||||
|
||||
export const RequestConfirmationMobile390: Story = {
|
||||
render: () => (
|
||||
<MobileScenario
|
||||
title="Confirmation mobile"
|
||||
interaction={pendingRequestConfirmationInteraction}
|
||||
/>
|
||||
),
|
||||
};
|
||||
|
||||
export const CheckboxConfirmationMobile390: Story = {
|
||||
render: () => (
|
||||
<MobileScenario
|
||||
title="Checkbox confirmation mobile"
|
||||
interaction={pendingRequestCheckboxConfirmationInteraction}
|
||||
/>
|
||||
),
|
||||
};
|
||||
|
||||
export const StateMatrix: Story = {
|
||||
render: () => (
|
||||
<StoryFrame>
|
||||
<Section eyebrow="State matrix" title="Issue-thread interaction status coverage">
|
||||
<div className="grid gap-6 xl:grid-cols-2">
|
||||
<ScenarioCard title="Suggested tasks" description="Pending, accepted, rejected, expired, cancelled, and failed.">
|
||||
<div className="space-y-4">
|
||||
<StaticInteractionCard interaction={pendingSuggestedTasksInteraction} />
|
||||
<StaticInteractionCard interaction={partialAcceptedSuggestedTasksInteraction} />
|
||||
<StaticInteractionCard interaction={rejectedSuggestedTasksInteraction} />
|
||||
<StaticInteractionCard interaction={expiredSuggestedTasksInteraction} />
|
||||
<StaticInteractionCard interaction={cancelledSuggestedTasksInteraction} />
|
||||
<StaticInteractionCard interaction={failedSuggestedTasksInteraction} />
|
||||
</div>
|
||||
</ScenarioCard>
|
||||
<ScenarioCard title="Ask user questions" description="Pending, answered, expired by comment, cancelled, and failed.">
|
||||
<div className="space-y-4">
|
||||
<StaticInteractionCard interaction={everyQuestionTypeAskUserQuestionsInteraction} />
|
||||
<StaticInteractionCard interaction={everyQuestionTypeAnsweredAskUserQuestionsInteraction} />
|
||||
<StaticInteractionCard interaction={commentExpiredAskUserQuestionsInteraction} />
|
||||
<StaticInteractionCard interaction={cancelledAskUserQuestionsInteraction} />
|
||||
<StaticInteractionCard interaction={failedAskUserQuestionsInteraction} />
|
||||
</div>
|
||||
</ScenarioCard>
|
||||
<ScenarioCard title="Request confirmation" description="Pending, accepted, rejected, both expiry reasons, cancelled, and failed.">
|
||||
<div className="space-y-4">
|
||||
<StaticInteractionCard interaction={pendingRequestConfirmationInteraction} />
|
||||
<StaticInteractionCard interaction={acceptedRequestConfirmationInteraction} />
|
||||
<StaticInteractionCard interaction={rejectedRequestConfirmationInteraction} />
|
||||
<StaticInteractionCard interaction={commentExpiredRequestConfirmationInteraction} />
|
||||
<StaticInteractionCard interaction={staleTargetRequestConfirmationInteraction} />
|
||||
<StaticInteractionCard interaction={cancelledRequestConfirmationInteraction} />
|
||||
<StaticInteractionCard interaction={failedRequestConfirmationInteraction} />
|
||||
</div>
|
||||
</ScenarioCard>
|
||||
<ScenarioCard title="Checkbox confirmation" description="Pending, accepted, rejected, both expiry reasons, cancelled, and failed.">
|
||||
<div className="space-y-4">
|
||||
<StaticInteractionCard interaction={pendingRequestCheckboxConfirmationInteraction} />
|
||||
<StaticInteractionCard interaction={acceptedRequestCheckboxConfirmationInteraction} />
|
||||
<StaticInteractionCard interaction={rejectedRequestCheckboxConfirmationInteraction} />
|
||||
<StaticInteractionCard interaction={commentExpiredRequestCheckboxConfirmationInteraction} />
|
||||
<StaticInteractionCard interaction={staleTargetRequestCheckboxConfirmationInteraction} />
|
||||
<StaticInteractionCard interaction={cancelledRequestCheckboxConfirmationInteraction} />
|
||||
<StaticInteractionCard interaction={failedRequestCheckboxConfirmationInteraction} />
|
||||
</div>
|
||||
</ScenarioCard>
|
||||
</div>
|
||||
</Section>
|
||||
</StoryFrame>
|
||||
),
|
||||
};
|
||||
|
||||
export const ReviewSurface: Story = {
|
||||
render: () => (
|
||||
<StoryFrame>
|
||||
|
||||
Reference in new issue
Block a user