import { expect, within } from "storybook/test"; import type { Meta, StoryObj } from "@storybook/react-vite"; import { SwatchesRegularIcon } from "alouette-icons/phosphor-icons/Swatches"; import { Text } from "../primitives/Text"; import { View } from "../primitives/View"; import { Story, accentsWithoutNeutral } from "../story-components/Story"; import { ConfirmationMessage, ErrorMessage, InfoMessage, Message, WarningMessage, } from "./Message"; type ThisStory = StoryObj; const SIZES = ["sm", "md", "lg"] as const; export default { title: "alouette/Feedback/Message", component: Message, parameters: { componentSubtitle: "A versatile component for displaying feedback to users", }, argTypes: { accent: { description: "The accent of the message", control: "select", options: accentsWithoutNeutral, table: { defaultValue: { summary: "info" } }, }, onDismiss: { description: "Callback function when dismiss button is clicked", control: "boolean", }, children: { description: "The content of the message", control: "text", }, }, } satisfies Meta; export const PreviewMessageStory: ThisStory = { parameters: { layout: "padded", chromatic: { disableSnapshot: true }, }, args: { accent: "info" }, render: (args) => ( }> Example Message ), }; export const Variants: ThisStory = { render: () => ( } accent="info"> Example Message } accent="info" dismissIconAriaLabel="Close message" onDismiss={() => {}} > Example Message with dismiss {accentsWithoutNeutral.map((accent) => ( } accent={accent}> {`${accent} message`} ))} {SIZES.map((size) => ( } accent="info" size={size}> {`Example ${size} Message`} } accent="info" size={size} dismissIconAriaLabel="Close message" onDismiss={() => {}} > {`Example ${size} Message with dismiss`} ))} Raised above the page. Info Message Success Message Warning Message Error Message Info Message Success Message Warning Message Error Message {SIZES.map((size) => ( } accent="info" size={size} dismissIconAriaLabel="Close message" onDismiss={() => {}} > {`Narrow ${size} message with a long enough text to wrap`} ))} } accent="info"> Example Message with very very very very very very very very very very very very very very very very very very very very very very very long text } accent="info" dismissIconAriaLabel="Close message" onDismiss={() => {}} > Dismissable Example Message with very very very very very very very very very very very very very very very very very very very very very very long text ), play: async ({ canvasElement }) => { // A wrapping text must not squeeze the leading icon below its size. // Story renders its children once per mode, hence getAll. for (const narrow of within(canvasElement).getAllByLabelText( "Narrow messages", )) { // Two svgs per message: the leading icon, then the dismiss icon. const [smIcon, , mdIcon, , lgIcon] = narrow.querySelectorAll("svg"); if (!smIcon || !mdIcon || !lgIcon) { throw new Error("Expected a leading icon in each narrow message"); } await expect(smIcon.getBoundingClientRect().width).toBe(20); await expect(mdIcon.getBoundingClientRect().width).toBe(24); await expect(lgIcon.getBoundingClientRect().width).toBe(28); // ...and the text must wrap rather than push the dismiss button out. for (const dismiss of narrow.querySelectorAll("button")) { await expect(dismiss.getBoundingClientRect().right).toBeLessThanOrEqual( narrow.getBoundingClientRect().right, ); } } }, };