/* eslint-disable testing-library/no-node-access */ import React from "react"; import { userEvent, within } from "@storybook/testing-library"; import { expect } from "@storybook/jest"; import * as Tokens from "../theme/tokens"; import { Popover as PopoverPrimitive } from "radix-ui"; import { Popover } from "./"; import { styled, theme, globalCss } from "../theme"; import { ChevronRight } from "@washingtonpost/wpds-assets"; import type { Meta, StoryFn } from "@storybook/react"; export default { title: "Popover", component: Popover.Content, subcomponents: { Root: Popover.Root, Portal: Popover.Portal, Trigger: Popover.Trigger, Anchor: Popover.Anchor, }, parameters: { chromatic: { delay: 300 }, }, } as Meta; // eslint-disable-next-line @typescript-eslint/no-explicit-any const Template: StoryFn = (args) => { const triggerRef = React.useRef(null); const [parentElement, setParentElement] = React.useState(); React.useEffect(() => { triggerRef?.current && setParentElement(triggerRef.current["parentElement"]); }, [setParentElement]); return ( Trigger ); }; export const Default = { render: Template, args: { children: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Diam non eget consequat pretium.", density: "default", sideOffset: "050", side: "bottom", align: "center", }, argTypes: { density: { control: "select", options: ["default", "compact"], }, sideOffset: { options: Object.keys(Tokens.sizes), mapping: theme.sizes, control: "select", }, }, parameters: { chromatic: { disableSnapshot: true }, }, }; // eslint-disable-next-line @typescript-eslint/no-explicit-any const AnchorTemplate: StoryFn = (args) => { const triggerRef = React.useRef(null); const [parentElement, setParentElement] = React.useState(); React.useEffect(() => { triggerRef?.current && setParentElement(triggerRef.current["parentElement"]); }, [setParentElement]); return ( Trigger
Anchor
); }; export const Anchor = { render: AnchorTemplate, args: { children: "Anchors allow for Popups to be triggered and positioned independently", }, parameters: { chromatic: { disableSnapshot: true } }, }; // eslint-disable-next-line @typescript-eslint/no-explicit-any const CloseButtonTemplate: StoryFn = (args) => { const triggerRef = React.useRef(null); const [parentElement, setParentElement] = React.useState(); React.useEffect(() => { triggerRef?.current && setParentElement(triggerRef.current["parentElement"]); }, [setParentElement]); return ( Trigger { e.preventDefault(); }} >
{args.children}
); }; export const CloseButton = { render: CloseButtonTemplate, args: { children: "An optional close button may be included", }, parameters: { chromatic: { disableSnapshot: true } }, }; const SideMenu = styled("menu", { backgroundColor: theme.colors.gray40, listStyle: "none", marginBlock: 0, paddingInlineStart: 0, width: "250px", minHeight: "100vh", }); const MenuLink = styled("a", { color: theme.colors.onPrimary, display: "flex", alignItems: "center", fontSize: theme.fontSizes["087"], fontWeight: theme.fontWeights.bold, textDecoration: "none", paddingBlock: theme.space["100"], paddingInline: theme.space["125"], "&:hover": { backgroundColor: theme.colors.gray0, }, "&:focus-visible": { outline: "none" }, "& :first-child": { flex: 1, }, }); const SubMenu = styled("menu", { listStyle: "none", marginBlock: 0, paddingInlineStart: 0, }); const SubMenuLink = styled("a", { color: theme.colors.primary, display: "block", fontSize: theme.fontSizes["087"], fontWeight: theme.fontWeights.bold, paddingBlock: theme.space["100"], paddingInline: theme.space["125"], textDecoration: "none", "&:hover": { backgroundColor: theme.colors.gray500, }, }); const Arrow = () => { return ( ); }; // eslint-disable-next-line @typescript-eslint/no-explicit-any const MenuTemplate: StoryFn = () => { const [menuOpen, setMenuOpen] = React.useState(false); return (
  • Home Page
  • setMenuOpen(true)} onMouseLeave={() => setMenuOpen(false)} > setMenuOpen(open)} > Politics{" "}
  • Election 2024
  • Courts and Law
  • Fact Checker
  • ); }; export const Menu = { render: MenuTemplate, parameters: { chromatic: { disableSnapshot: true } }, }; // eslint-disable-next-line @typescript-eslint/no-explicit-any const FullPopover: StoryFn = ({ side, align }) => ( Trigger {side} {align} ); // eslint-disable-next-line @typescript-eslint/no-explicit-any const ChromaticTemplate: StoryFn = () => { const side = ["bottom", "top", "right", "left"]; const align = ["start", "center", "end"]; return (
    {side.map((s) => { let direction = "row"; if (s === "right" || s === "left") { direction = "column"; } let alignItems = "flex-start"; if (s === "left") { alignItems = "flex-end"; } return (
    {align.map((a) => { let p = "0"; if (s === "bottom") { p = "0 0 54px 0"; } else if (s === "top") { p = "54px 0 0 0"; } else { p = "20px 0 20px 0"; } return (
    ); })}
    ); })}
    ); }; export const Chromatic = { render: ChromaticTemplate, parameters: { docs: { disable: true }, chromatic: { delay: 1000 }, }, }; const ecGlobalCss = globalCss({ ":not(.wpds-dark) > .ec-grid": { marginInlineStart: "-2rem", }, ".wpds-dark > .ec-grid": { marginInlineEnd: "-2rem", }, }); // eslint-disable-next-line @typescript-eslint/no-explicit-any const EdgeAndCornerCasesTemplate: StoryFn = () => { ecGlobalCss(); return (
    ); }; export const EdgeAndCornerCases = { render: EdgeAndCornerCasesTemplate, parameters: { docs: { disable: true }, chromatic: { delay: 3000 }, }, }; // eslint-disable-next-line @typescript-eslint/no-explicit-any const InteractionsTemplate: StoryFn = () => ( Trigger Popover Content ); export const Interactions = { render: InteractionsTemplate, parameters: { chromatic: { disableSnapshot: true }, }, play: async ({ canvasElement }) => { const canvas = within(canvasElement); const trigger = canvas.getByRole("button"); await userEvent.click(trigger); await sleep(500); const content = canvas.getByRole("dialog"); await expect(content).toBeVisible(); await userEvent.click(document.body); await sleep(500); await expect(content).not.toBeInTheDocument(); }, }; // Function to emulate pausing between interactions function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); }