import "./all.js"; import { Meta, StoryObj } from "@storybook/react-vite"; import { expect, fn, userEvent, waitFor, within } from "storybook/test"; import { Icon } from "../../atoms/icon/Icon.js"; import { Button } from "../button/Button.js"; import { Tab } from "./Tab.js"; import { TabList } from "./TabList.js"; import { TabPanel } from "./TabPanel.js"; import { Tabs } from "./Tabs.js"; import { TabsBody } from "./TabsBody.js"; /** * Tabs component. * * You can import this component and use it like: * * ```tsx * import {Tabs} from "@tsed/react-formio/molecules/tabs/all" * * or * * import {Tabs} from "@tsed/react-formio/molecules/tabs/Tabs"; * ``` * * Tabs component support DI container and can be used with custom component. Here is the list of components that you can override: * * - Tab * - TabList * - TabPanel * - Tabs * - TabsBody * * ```tsx * function CustomTab() { * * } * * registerComponent("Tab", CustomTab); * ``` */ export default { title: "Tabs", component: Tabs, argTypes: { reverse: { control: "boolean", description: "Reverse the order of the tabs" }, selected: { control: { type: "number", min: 0, max: 10 }, description: "Selected tab index" }, items: { control: "object", description: "Array of tab items with label, icon, and content" } }, parameters: {}, args: {} } satisfies Meta; type Story = StoryObj; export const Usage: Story = { args: { reverse: false, items: [ { action: "edit", exact: true, icon: "edit", label: "Edit", children:
Edit
}, { action: "submissions", exact: false, icon: "data", label: "Data", children:
Data
}, { action: "preview", exact: true, icon: "test-tube", label: "Preview", children:
Preview
}, { action: "actions", exact: false, icon: "paper-plane", label: "Actions", children:
Actions
}, { action: "access", exact: true, icon: "lock", label: "Access", children:
Access
}, { action: "export", exact: true, icon: "download", label: "Export", children:
Export
}, { action: "delete", exact: true, icon: "trash", label: "Delete", roles: ["administrator", "owner"], children:
Trash
} ], onClick: fn() }, play: async ({ canvasElement, args }) => { const canvas = within(canvasElement); // Vérifie que tous les onglets sont présents await expect(canvas.getByRole("tab", { name: "Edit" })).toBeInTheDocument(); await expect(canvas.getByRole("tab", { name: "Data" })).toBeInTheDocument(); await expect(canvas.getByRole("tab", { name: "Preview" })).toBeInTheDocument(); await expect(canvas.getByRole("tab", { name: "Actions" })).toBeInTheDocument(); await expect(canvas.getByRole("tab", { name: "Access" })).toBeInTheDocument(); await expect(canvas.getByRole("tab", { name: "Export" })).toBeInTheDocument(); await expect(canvas.getByRole("tab", { name: "Delete" })).toBeInTheDocument(); await waitFor(() => expect(canvas.getByRole("tabpanel")).toHaveTextContent("Edit")); // Clique sur l'onglet "Preview" et vérifie le contenu await userEvent.click(canvas.getByRole("tab", { name: "Preview" })); await expect(args.onClick).toHaveBeenCalledWith( expect.objectContaining({ action: "preview" }) ); await waitFor(() => expect(canvas.getByRole("tabpanel")).toHaveTextContent("Preview")); // Clique sur l'onglet "Delete" et vérifie le contenu await userEvent.click(canvas.getByRole("tab", { name: "Delete" })); await expect(args.onClick).toHaveBeenCalledWith( expect.objectContaining({ action: "delete" }) ); await waitFor(() => expect(canvas.getByRole("tabpanel")).toHaveTextContent("Trash")); }, render: (args) => { const items: any[] = args.items.filter((item: any) => item.label || item.icon); return (
{items.map((item, index) => { return ( args.onClick(item)} key={index} icon={item.icon} value={index} className={args.reverse ? "-reverse" : ""} > {item.label} ); })} {items.map((item, index) => { return ( {item.children} ); })}
); } }; export const WithSelectedTab: Story = { args: { selected: 2, reverse: false, items: [ { action: "edit", exact: true, icon: "edit", label: "Edit", children:
Edit
}, { action: "submissions", exact: false, icon: "data", label: "Data", children:
Data
}, { action: "preview", exact: true, icon: "test-tube", label: "Preview", children:
Preview
}, { action: "actions", exact: false, icon: "paper-plane", label: "Actions", children:
Actions
}, { action: "access", exact: true, icon: "lock", label: "Access", children:
Access
}, { action: "export", exact: true, icon: "download", label: "Export", children:
Export
}, { action: "delete", exact: true, icon: "trash", label: "Delete", roles: ["administrator", "owner"], children:
Trash
} ] }, render: (args) => { const items: any[] = args.items.filter((item: any) => item.label || item.icon); return (
{items.map((item, index) => { return ( {item.label} ); })} {items.map((item, index) => { return ( {item.children} ); })}
); } }; export const WithExtraControls: Story = { args: { reverse: false, items: [ { action: "edit", exact: true, icon: "edit", label: "Edit", children:
Edit
}, { action: "submissions", exact: false, icon: "data", label: "Data", children:
Data
}, { action: "preview", exact: true, icon: "test-tube", label: "Preview", children:
Preview
}, { action: "actions", exact: false, icon: "paper-plane", label: "Actions", children:
Actions
}, { action: "access", exact: true, icon: "lock", label: "Access", children:
Access
}, { action: "export", exact: true, icon: "download", label: "Export", children:
Export
}, { action: "delete", exact: true, icon: "trash", label: "Delete", roles: ["administrator", "owner"], children:
Trash
} ] }, render: (args) => { const items: any[] = args.items.filter((item: any) => item.label || item.icon); return (
{items.map((item, index) => { return ( {item.label} ); })} {items.map((item, index) => { return ( {item.children} ); })}
); } };