import type { Meta, StoryObj } from '@storybook/react-vite' import React, { useState } from 'react' import { DocsTemplate } from '../../../.storybook' import Menu, { type MenuProps } from './Menu' import Pill from '../Pill/Pill' import { toast } from '../Toast/Toast' const meta: Meta = { title: 'Components/Popover/Menu', component: Menu, parameters: { design: { type: 'figma', url: 'https://www.figma.com/design/RvhKD82948FMQnh5MyCi0o/Web-Design-System?node-id=4189-8819&t=KUWdug3XS3dQ8hnl-0', }, docs: { page: () => ( The Menu component is a structured list of actionable items presented within a popover. It supports various types of actions including standard actions, toggles, CSV downloads, and links. Each action can be customized with icons, destructive styling, dividers, disabled states, and secondary content. } infoBullets={[ 'Use standard actions for simple click interactions with optional icons and callbacks.', 'Implement toggle actions for boolean state changes with visual feedback.', 'Add CSV actions for file download functionality with loading states.', 'Include link actions for navigation with router integration.', 'Use dividers to separate groups of related actions.', 'Add secondary content to provide additional context or status.', 'Implement confirmation dialogs for destructive actions.', 'Use disabled states with tooltips to explain why actions are unavailable.', ]} /> ), }, }, } export default meta type Story = StoryObj // Helper function to generate consistent navigation links const generateNavLinks = ( count: number, disabled = false, ): MenuProps['actions'] => { return Array.from({ length: count }, (_, i) => ({ text: `Navigation Link ${i + 1}`, icon: 'arrowLong' as const, link: '/', routerComponent: 'a', routerProp: 'href', ...(disabled && { disabled: { value: true, tooltip: { tooltipContent: 'This link is disabled' }, }, }), })) } // Base template for stories const Template: Story = { render: (args) => , } // Basic Actions export const Basic: Story = { ...Template, args: { actions: [ { text: 'View Details', icon: 'eye' as const, callout: () => toast({ type: 'success', message: 'Viewing details' }), }, { text: 'Edit Item', icon: 'pencil' as const, callout: () => toast({ type: 'success', message: 'Editing item' }), }, { text: 'Delete Item', icon: 'trash' as const, callout: () => toast({ type: 'success', message: 'Deleting item' }), }, ], }, } // Without Icons export const WithoutIcons: Story = { ...Template, args: { actions: [ { text: 'View Details', callout: () => toast({ type: 'success', message: 'Viewing details' }), }, { text: 'Edit Item', callout: () => toast({ type: 'success', message: 'Editing item' }), }, { text: 'Delete Item', callout: () => toast({ type: 'success', message: 'Deleting item' }), }, ], }, } // With Dividers export const WithDividers: Story = { ...Template, args: { actions: [ { text: 'View Details', icon: 'eye' as const, callout: () => toast({ type: 'success', message: 'Viewing details' }), }, { text: 'Edit Item', icon: 'pencil' as const, callout: () => toast({ type: 'success', message: 'Editing item' }), hasDivider: true, }, { text: 'Delete Item', icon: 'trash' as const, callout: () => toast({ type: 'success', message: 'Deleting item' }), }, ], }, } // With Destructive Actions export const WithDestructiveActions: Story = { ...Template, args: { actions: [ { text: 'View Details', icon: 'eye' as const, callout: () => toast({ type: 'success', message: 'Viewing details' }), }, { text: 'Edit Item', icon: 'pencil' as const, callout: () => toast({ type: 'success', message: 'Editing item' }), }, { text: 'Delete Item', icon: 'trash' as const, destructive: true, callout: () => toast({ type: 'success', message: 'Deleting item' }), }, ], }, } // With Disabled Actions export const WithDisabledActions: Story = { ...Template, args: { actions: [ { text: 'View Details', icon: 'eye' as const, callout: () => toast({ type: 'success', message: 'Viewing details' }), }, { text: 'Edit Item', icon: 'pencil' as const, disabled: { value: true }, callout: () => toast({ type: 'success', message: 'Editing item' }), }, { text: 'Delete Item', icon: 'trash' as const, callout: () => toast({ type: 'success', message: 'Deleting item' }), }, ], }, } // With Disabled Actions and Tooltips export const WithDisabledActionsAndTooltips: Story = { ...Template, args: { actions: [ { text: 'View Details', icon: 'eye' as const, callout: () => toast({ type: 'success', message: 'Viewing details' }), }, { text: 'Edit Item', icon: 'pencil' as const, disabled: { value: true, tooltip: { tooltipContent: 'You do not have permission to edit this item', }, }, callout: () => toast({ type: 'success', message: 'Editing item' }), }, { text: 'Delete Item', icon: 'trash' as const, callout: () => toast({ type: 'success', message: 'Deleting item' }), }, ], }, } // With Secondary Content export const WithSecondaryContent: Story = { ...Template, args: { actions: [ { text: 'View Details', icon: 'eye' as const, callout: () => toast({ type: 'success', message: 'Viewing details' }), }, { text: 'Edit Item', icon: 'pencil' as const, secondaryContent: , callout: () => toast({ type: 'success', message: 'Editing item' }), }, { text: 'Delete Item', icon: 'trash' as const, callout: () => toast({ type: 'success', message: 'Deleting item' }), }, ], }, } // With Confirmation export const WithConfirmation: Story = { ...Template, args: { actions: [ { text: 'View Details', icon: 'eye' as const, callout: () => toast({ type: 'success', message: 'Viewing details' }), }, { text: 'Edit Item', icon: 'pencil' as const, callout: () => toast({ type: 'success', message: 'Editing item' }), }, { text: 'Delete Item', icon: 'trash' as const, destructive: true, confirmation: { type: 'red', header: 'Delete Item', body: 'Are you sure you want to delete this item? This action cannot be undone.', confirmCallout: () => toast({ type: 'success', message: 'Item deleted' }), }, }, ], }, } // With Navigation Links export const WithNavigationLinks: Story = { ...Template, args: { actions: generateNavLinks(3), }, } // With Disabled Navigation Links export const WithDisabledNavigationLinks: Story = { ...Template, args: { actions: generateNavLinks(3, true), }, } // With Toggle Actions const MenuWithToggle = () => { const [toggleState, setToggleState] = useState(true) const actions: MenuProps['actions'] = [ { text: 'View Details', icon: 'eye' as const, callout: () => toast({ type: 'success', message: 'Viewing details' }), }, { text: 'Edit Item', icon: 'pencil' as const, callout: () => toast({ type: 'success', message: 'Editing item' }), }, { text: 'Enable Feature', icon: 'toggle' as const, toggle: { checked: toggleState, callout: (value) => { setToggleState(value) toast({ type: 'success', message: `Feature ${value ? 'enabled' : 'disabled'}`, }) }, }, }, ] return } export const WithToggle: Story = { render: () => , } // With CSV Actions const MenuWithCSV = () => { const actions: MenuProps['actions'] = [ { text: 'View Details', icon: 'eye' as const, callout: () => toast({ type: 'success', message: 'Viewing details' }), }, { text: 'Edit Item', icon: 'pencil' as const, callout: () => toast({ type: 'success', message: 'Editing item' }), }, { csv: { linkName: 'Download CSV', csvName: 'Sample Data', csvFormat: { api: () => { return new Promise((resolve) => { setTimeout(() => { resolve(new Blob(['Sample CSV Data'])) }, 2000) }) }, params: {}, }, }, handleCsvAction: (downloading) => { toast({ type: 'info', message: downloading ? 'Downloading CSV...' : 'Download complete', }) }, }, ] return } export const WithCSV: Story = { render: () => , } // Comprehensive Example const ComprehensiveMenu = () => { const [toggleState, setToggleState] = useState(true) const actions: MenuProps['actions'] = [ { text: 'View Details', icon: 'eye' as const, callout: () => toast({ type: 'success', message: 'Viewing details' }), }, { text: 'Edit Item', icon: 'pencil' as const, secondaryContent: , callout: () => toast({ type: 'success', message: 'Editing item' }), }, { text: 'Enable Feature', icon: 'toggle' as const, toggle: { checked: toggleState, callout: (value) => { setToggleState(value) toast({ type: 'success', message: `Feature ${value ? 'enabled' : 'disabled'}`, }) }, }, hasDivider: true, }, { csv: { linkName: 'Download CSV', csvName: 'Sample Data', csvFormat: { api: () => { return new Promise((resolve) => { setTimeout(() => { resolve(new Blob(['Sample CSV Data'])) }, 2000) }) }, params: {}, }, }, handleCsvAction: (downloading) => { toast({ type: 'info', message: downloading ? 'Downloading CSV...' : 'Download complete', }) }, }, { text: 'Delete Item', icon: 'trash' as const, destructive: true, disabled: { value: true, tooltip: { tooltipContent: 'Cannot delete this item' }, }, confirmation: { type: 'red', header: 'Delete Item', body: 'Are you sure you want to delete this item? This action cannot be undone.', confirmCallout: () => toast({ type: 'success', message: 'Item deleted' }), }, }, ] return } export const Comprehensive: Story = { render: () => , }