import { expect, fn, userEvent, within } from "storybook/test"; import type { Meta, StoryObj } from "@storybook/react-vite"; import { View } from "../primitives/View"; import { Story } from "../story-components/Story"; import { ActionButton } from "./ActionButton"; import { Button } from "./Button"; import { DecisionBar } from "./DecisionBar"; type ThisStory = StoryObj; export default { title: "alouette/Actions/DecisionBar", component: DecisionBar, parameters: { componentSubtitle: "The row of actions ending a decision: it owns their order and alignment.", docs: { description: { component: `### Composition ~~~tsx } primary={} /> ~~~ - Right-aligned, in this order whatever the props' order: dismiss, \`alternative\`, \`primary\` - \`primary\` is required: an \`ActionButton\` for an async action, a \`FormSubmitButton\` in a \`Form\`, a \`Button\` for a synchronous one - \`onDismiss\` renders the dismiss action itself, a neutral \`soft\` Button labelled \`dismissText\` ("Cancel" by default); \`emphasis="dismiss"\` makes it neutral \`filled\` when backing out is the expected answer - \`alternative\` is one element, another way to commit; several belong in a \`SplitButton\` or a \`Menu\` - Only actions that end the decision: an editor's tools (attach, insert) stay in the editor's own toolbar`, }, }, }, } satisfies Meta; function errorToMessage(error: unknown): string { return error instanceof Error ? error.message : "Unknown error"; } function rejectAfter(ms: number, message: string): Promise { return new Promise((_resolve, reject) => { setTimeout(() => { reject(new Error(message)); }, ms); }); } export const DecisionBarPreviewStory: ThisStory = { name: "DecisionBar Preview", parameters: { layout: "padded", chromatic: { disableSnapshot: true }, }, args: { dismissText: "Cancel", onDismiss: fn(), primary: