import { Freeze, Plus, Send, Convert, Card } from '@transferwise/icons'; import { Meta, StoryObj } from '@storybook/react-webpack5'; import { expect, fn, userEvent, within } from 'storybook/test'; import { useState } from 'react'; import CircularButton from './CircularButton'; import Title from '../title'; import Body from '../body'; import { withVariantConfig } from '../../.storybook/helpers'; const wait = async (ms: number) => new Promise((resolve) => { setTimeout(resolve, ms); }); export default { component: CircularButton, title: 'Actions/CircularButton/Tests', tags: ['!autodocs', '!manifest'], } satisfies Meta; type Story = StoryObj; /** All priorities, types, and states across all themes. */ export const Variants: Story = { render: () => { const rowStyle = { display: 'grid', gridTemplateColumns: 'repeat(4, minmax(0, 100px))', gap: '16px', textAlign: 'center' as const, }; return (
} onClick={fn()}> Primary } onClick={fn()}> Secondary }> Primary disabled }> Secondary disabled
} onClick={fn()}> Primary } onClick={fn()}> Secondary }> Primary disabled }> Secondary disabled
); }, ...withVariantConfig(['default', 'dark', 'bright-green', 'forest-green']), }; /** * `Space` or `Enter` activates when focused. Tab skips disabled buttons. */ export const KeyboardInteraction: Story = { render: () => { const onClick = fn(); return (
} onClick={onClick}> Send } onClick={onClick}> Add funds } onClick={onClick}> Convert } disabled onClick={onClick} > Disabled
); }, play: async ({ canvasElement, step }) => { const canvas = within(canvasElement); const buttons = canvas.getAllByRole('button'); await step('tab to Send and press Space', async () => { await userEvent.tab(); await expect(buttons[0]).toHaveFocus(); await wait(400); await userEvent.keyboard(' '); }); await wait(400); await step('tab to Add funds and press Space', async () => { await userEvent.tab(); await expect(buttons[1]).toHaveFocus(); await wait(400); await userEvent.keyboard(' '); }); await wait(400); await step('tab to Convert and press Space', async () => { await userEvent.tab(); await expect(buttons[2]).toHaveFocus(); await wait(400); await userEvent.keyboard(' '); }); await wait(400); await step('tab skips Disabled button', async () => { await userEvent.tab(); // Disabled button should be skipped, focus leaves the component await expect(buttons[3]).not.toHaveFocus(); }); }, }; /** Base variants in right-to-left layout. */ export const RTL: Story = { render: function Render() { const [clicks, setClicks] = useState(0); const rowStyle = { display: 'grid', gridTemplateColumns: 'repeat(4, minmax(0, 100px))', gap: '16px', textAlign: 'center' as const, }; return (
} onClick={() => setClicks((c) => c + 1)} > Primary } onClick={() => setClicks((c) => c + 1)} > Secondary }> Primary disabled }> Secondary disabled
} onClick={() => setClicks((c) => c + 1)} > Primary } onClick={() => setClicks((c) => c + 1)} > Secondary }> Primary disabled }> Secondary disabled
); }, ...withVariantConfig(['rtl']), }; /** Long labels are centered beneath the icon. */ export const CenteredText: Story = { render: () => { return (
}> Very long text for a circular button that will be centered
); }, }; const All: Story = { args: { children: 'Button text', icon: , className: 'm-r-2', }, render: (props) => { return ( <> Default (Primary and secondary) Negative (Primary and secondary) Accent (Deprecated) Positive (Deprecated) ); }, }; /** All variants at 400% zoom for accessibility testing. */ export const Zoom400: Story = { ...All, ...withVariantConfig(['400%'], All), };