import React from 'react' import { type Meta, type StoryObj } from '@storybook/react' import { expect, userEvent, waitFor, within } from '@storybook/test' import isChromatic from 'chromatic' import { Button } from '~components/Button' import { Focusable } from '~components/Focusable' import { Icon } from '~components/Icon' import { LinkButton } from '~components/LinkButton' import { Tab, TabList, TabPanel, Tabs } from '~components/Tabs' import { Tag } from '~components/Tag' import { Text } from '~components/Text' import { Tooltip, TooltipTrigger } from '../index' const meta = { title: 'Components/Tooltip/Tests', component: Tooltip, parameters: { layout: 'centered', }, args: { defaultOpen: isChromatic(), }, argTypes: { UNSTABLE_portalContainer: { control: false, table: { disable: true }, }, triggerRef: { control: false }, }, } satisfies Meta export default meta type Story = StoryObj export const OnButton: Story = { render: ({ defaultOpen, isOpen, ...args }) => ( Tooltip content ), play: async ({ canvasElement, step }) => { const canvas = within(canvasElement.parentElement!) const button = canvas.queryByRole('button') ?? canvas.getByRole('link') await step('Hover shows', async () => { await waitFor(() => userEvent.click(canvasElement)) // needed to refocus the browser window await userEvent.hover(button) await expect(await canvas.findByRole('tooltip')).toBeInTheDocument() await expect((await canvas.findByRole('tooltip')).checkVisibility()).toBe(true) await expect(button).toHaveAttribute('aria-describedby', canvas.getByRole('tooltip').id) await userEvent.unhover(button) }) await step('Focus shows', async () => { await waitFor(() => userEvent.click(canvasElement)) // needed to refocus the browser window await userEvent.tab() // focus await expect((await canvas.findByRole('tooltip')).checkVisibility()).toBe(true) await expect(await canvas.findByRole('tooltip')).toBeInTheDocument() await userEvent.tab() // unfocus waitFor(() => expect(canvas.queryByRole('tooltip')).toBeNull()) waitFor(async () => expect(await canvas.queryByText('Tooltip content')).toBeNull()) }) await step('Escape closes', async () => { await waitFor(() => userEvent.click(canvasElement)) // needed to refocus the browser window await userEvent.tab() // focus await waitFor(() => expect(canvas.getByRole('tooltip')).toBeVisible()) await userEvent.keyboard('{Escape}') await waitFor(() => expect(canvas.queryByRole('tooltip')).toBeNull(), { timeout: 5000, }) await userEvent.tab() // unfocus }) }, } export const OnLink: Story = { ...OnButton, render: ({ defaultOpen, isOpen, ...args }) => ( Button Tooltip content ), } export const OnButtonWithDesc: Story = { render: ({ defaultOpen, isOpen, ...args }) => ( <> Tooltip content This is target of aria-describedby ), } export const OnIconButton: Story = { render: ({ defaultOpen, isOpen, ...args }) => ( Add something ), } export const OnDisabledButton: Story = { render: ({ defaultOpen, isOpen, ...args }) => ( Tooltip content ), } export const OnCustomFocusableElement: Story = { render: ({ defaultOpen, isOpen, ...args }) => ( Non-interactive element Tooltip content ), } export const OnTabs: Story = { render: ({ defaultOpen, isOpen, ...args }) => ( Tab 1 Tooltip content Tab content ), } export const Placement: Story = { render: ({ defaultOpen, isOpen, ...args }) => ( Placement top Placement end Placement bottom Placement start ), } export const ReversedColors: Story = { render: ({ defaultOpen, isOpen, ...args }) => ( Tooltip content ), parameters: { reverseColors: true, }, }