import type { Meta, StoryObj } from '@storybook/nextjs-vite'; import { Button } from '../components/ui/button'; import { CommandApprovalToast, ToastCard, Toaster, showCommandApprovalToast, showToast, type ToastVariant, } from '../components/ui/toaster'; import { toast } from '../hooks/use-toast'; import { ToolTypeValues } from '../types/tool.types'; const meta = { title: 'UI/Toaster', component: ToastCard, parameters: { layout: 'padded', docs: { description: { component: 'Toast notifications built on Sonner with a custom ODS-styled card. Render `` once near your app root, then call `toast({...})` or `showToast({...})` from anywhere.', }, }, }, argTypes: { variant: { control: 'select', options: ['default', 'success', 'warning', 'error', 'info'] satisfies ToastVariant[], }, title: { control: 'text' }, description: { control: 'text' }, duration: { control: { type: 'number', min: 0, step: 500 } }, dismissible: { control: 'boolean' }, }, args: { id: 'preview', variant: 'warning', title: 'Device Package limit', description: 'Extra devices will be billed at pay-as-you-go rates, charged separately from your plan. Upgrade to lock in a lower device price.', duration: 4000, dismissible: true, }, } satisfies Meta; export default meta; type Story = StoryObj; /** * Static preview of every variant — no interaction needed. */ export const AllVariants: Story = { render: () => (
), }; /** * Interactive playground — tweak args to change the preview card. */ export const Playground: Story = { render: (args) => , }; /** * Command approval toast — collapsed state. * Shows the toast header with the warning dot, title, description, close * button, progress bar, and a "Show Command" toggle to expand details. */ export const CommandApprovalCollapsed: Story = { render: () => ( ), }; /** * Command approval toast — expanded state. * Reveals the command preview with its tool icon and the Approve / Reject * action row below the description. */ export const CommandApprovalExpanded: Story = { render: () => ( ), }; /** * Command approval toast rendered once per supported tool to demonstrate * the tool-icon mapping. */ export const CommandApprovalPerTool: Story = { render: () => { const tools = [ { toolType: ToolTypeValues.FLEET_MDM, command: 'fleetctl query --hosts mac-* "SELECT * FROM system_info"' }, { toolType: ToolTypeValues.OPENFRAME_RMM, command: 'rmm run-script "Reboot Endpoint" --agent all' }, { toolType: ToolTypeValues.MESHCENTRAL, command: 'meshctrl deviceaction --id --action reset' }, { toolType: ToolTypeValues.AUTHENTIK, command: 'ak revoke-session --user pavlo@flamingo.cx' }, { toolType: ToolTypeValues.OSQUERY, command: 'osqueryi "SELECT * FROM processes WHERE name = \'xx_email.exe\'"' }, { toolType: ToolTypeValues.OPENFRAME, command: 'openframe agent upgrade --tenant acme' }, ] as const; return (
{tools.map((t) => ( ))}
); }, }; /** * Fire the command approval toast as a real Sonner toast. */ export const CommandApprovalLive: Story = { render: () => (
), }; /** * Trigger real toasts via Sonner. Click a button to fire a toast in the * bottom-right corner using the actual `toast()` API. */ export const LiveTriggers: Story = { render: () => (
), };