import { StoryObj, Meta } from "@storybook/react-vite"; import { within, expect, userEvent } from "storybook/test"; import Details from "./details"; import Icons from "../icons/icon"; const content = ( <>

Lorem ipsum dolor sit, amet consectetur adipisicing elit. Accusantium accusamus molestiae, qui omnis illum iste asperiores fugit doloribus voluptatem numquam voluptatibus nisi blanditiis quidem sint optio. Dicta officia commodi numquam?

Impedit, libero ea. Repellendus doloribus possimus magni ullam natus voluptates, magnam ad iure quas eum adipisci! Repellat vel placeat commodi voluptatem optio odit, voluptatum id, magnam architecto at est ipsa.

Vitae, laudantium libero, dolorem enim architecto consectetur qui vero error possimus beatae iusto, labore praesentium. Assumenda recusandae labore aliquam omnis, aliquid in impedit possimus! Rerum consequuntur non hic est placeat!

); const icon = ; const meta: Meta = { title: "FP.React Components/Details", component: Details, tags: ["stable"], parameters: { docs: { description: { component: `Expandable/collapsible details component with smooth transitions and accessible markup. ## CSS Variables ### Layout & Display - \`--details-display\`: Display mode (default: flex) - \`--details-direction\`: Flex direction (default: column) - \`--details-justify\`: Content justification (default: flex-start) - \`--details-width\`: Details width (default: 100%) - \`--details-height\`: Details height (default: max-content) - \`--details-gap\`: Gap between elements (default: 0rem) ### Sizing & Constraints - \`--details-max-height-closed\`: Max height when closed (default: 6.25rem) - \`--details-max-height-open\`: Max height when open (default: 50rem) ### Spacing - \`--details-padding-inline\`: Horizontal padding (default: 1.5rem) - \`--details-padding-block\`: Vertical padding (default: 1rem) ### Borders & Radius - \`--details-border\`: Border style (default: 0.0625rem solid #dfdfdf) - \`--details-radius\`: Border radius (default: 0) ### Summary Element - \`--summary-display\`: Summary display mode (default: flex) - \`--summary-justify\`: Summary content justification (default: flex-start) - \`--summary-align\`: Summary vertical alignment (default: center) - \`--summary-gap\`: Gap within summary (default: 0.5rem) - \`--summary-padding-inline\`: Summary horizontal padding (fallback: \`--details-padding-inline\`) - \`--summary-padding-block\`: Summary vertical padding (fallback: \`--details-padding-block\`) - \`--summary-cursor\`: Summary cursor style (default: pointer) - \`--summary-transitions\`: Transition timing (default: all 0.75s ease-in-out) `, }, }, }, args: { children: content, icon: icon, summary: <>Summary Section, }, decorators: [ (Story) => (
), ], } as Story; export default meta; type Story = StoryObj; export const DetailsDropdown: Story = { args: {}, play: async ({ canvasElement }) => { const canvas = within(canvasElement); expect( canvas.getByRole("group", { name: /details dropdown/i }) ).toBeInTheDocument(); }, } as Story; export const DetailsStyles: Story = { args: { classes: "list-style", }, } as Story; export const DetailsOpen: Story = { args: { open: true, }, play: async ({ canvasElement }) => { const canvas = within(canvasElement); expect(canvas.getByRole("group")).toBeInTheDocument(); }, } as Story; export const CustomDropdown: Story = { render: () => ( <>
{content}

Lorem ipsum, dolor sit amet consectetur adipisicing elit. Dolorum quasi maiores placeat voluptate voluptatem, tenetur consectetur earum modi, quam pariatur, quas porro iste quo ipsum rem rerum fuga incidunt? Suscipit!

), } as Story; export const DetailsAccordion: Story = { render: () => ( <>
{content}
{content}
{content}
), } as Story; export const DetailsInteractionTest: Story = { args: {}, play: async ({ canvasElement, step }) => { const canvas = within(canvasElement); // Find the summary element const summaryElement = canvas.getByText("Summary Section"); // add an open step await step("Open the details", async () => { // Simulate a click on the summary element await userEvent.click(summaryElement, { delay: 500 }); // Assert that the details element is open const detailsElement = canvas.getByRole("group", { name: /details dropdown/i, }); expect(detailsElement).toHaveAttribute("open"); }); await step("Close the detail panel", async () => { await userEvent.click(summaryElement, { delay: 500 }); // `open` is an attribute on
, not on . The old // assertion was vacuously true because summary never has that attr. const detailsElement = canvas.getByRole("group", { name: /details dropdown/i, }); expect(detailsElement).not.toHaveAttribute("open"); }); // test if it works with the space bar await step("Open the details with space", async () => { summaryElement.focus(); expect(summaryElement).toHaveFocus(); await userEvent.type(summaryElement, "{space}", { delay: 500 }); // Assert that the details element is open const detailsElement = canvas.getByRole("group", { name: /details dropdown/i, }); expect(detailsElement).toHaveAttribute("open"); }); }, };