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: () => (