mirror of
https://github.com/hanzoai/o11y-components.git
synced 2026-10-30 14:54:15 +00:00
498 lines
12 KiB
TypeScript
498 lines
12 KiB
TypeScript
import { Button, ButtonColor, Toaster, toast } from '@signozhq/ui';
|
|
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
import { generateDocs } from '../utils/generateDocs.js';
|
|
|
|
const SonnerExamples = [
|
|
`import { Toaster, toast } from '@signozhq/ui';
|
|
|
|
export default function MyComponent() {
|
|
const showToast = () => {
|
|
toast('Hello World!');
|
|
};
|
|
|
|
return (
|
|
<div>
|
|
<button onClick={showToast}>Show Toast</button>
|
|
<Toaster />
|
|
</div>
|
|
);
|
|
}`,
|
|
`import { Toaster, toast } from '@signozhq/ui';
|
|
|
|
export default function MyComponent() {
|
|
const showSuccessToast = () => {
|
|
toast.success('Success! Your action was completed.');
|
|
};
|
|
|
|
const showErrorToast = () => {
|
|
toast.error('Error! Something went wrong.');
|
|
};
|
|
|
|
return (
|
|
<div>
|
|
<button onClick={showSuccessToast}>Success Toast</button>
|
|
<button onClick={showErrorToast}>Error Toast</button>
|
|
<Toaster />
|
|
</div>
|
|
);
|
|
}`,
|
|
];
|
|
|
|
const SonnerDocs = generateDocs({
|
|
packageName: '@signozhq/ui',
|
|
description: 'A toast component for displaying notifications and alerts.',
|
|
examples: SonnerExamples,
|
|
});
|
|
|
|
const meta: Meta<typeof Toaster> = {
|
|
title: 'Old Components/Sonner',
|
|
component: Toaster,
|
|
parameters: {
|
|
docs: {
|
|
description: {
|
|
component: SonnerDocs,
|
|
},
|
|
},
|
|
},
|
|
tags: ['autodocs'],
|
|
};
|
|
|
|
export default meta;
|
|
type Story = StoryObj<typeof Toaster>;
|
|
|
|
// Basic toast examples
|
|
export const BasicToasts: Story = {
|
|
render: () => (
|
|
<div className="p-8 space-y-4">
|
|
<h2 className="text-lg font-semibold">Basic Toast Examples</h2>
|
|
<div className="flex gap-4 flex-wrap">
|
|
<Button onClick={() => toast('Hello World!')} variant="solid" color="primary">
|
|
Default Toast
|
|
</Button>
|
|
<Button
|
|
onClick={() => toast.success('Success! Your action was completed.')}
|
|
variant="solid"
|
|
color="primary"
|
|
>
|
|
Success Toast
|
|
</Button>
|
|
<Button
|
|
onClick={() => toast.error('Error! Something went wrong.')}
|
|
variant="solid"
|
|
color="destructive"
|
|
>
|
|
Error Toast
|
|
</Button>
|
|
<Button
|
|
onClick={() => toast.warning('Warning! Please check your input.')}
|
|
variant="solid"
|
|
color="warning"
|
|
>
|
|
Warning Toast
|
|
</Button>
|
|
<Button
|
|
onClick={() => toast.info('Info: Here is some information.')}
|
|
variant="solid"
|
|
color="secondary"
|
|
>
|
|
Info Toast
|
|
</Button>
|
|
</div>
|
|
<Toaster />
|
|
</div>
|
|
),
|
|
};
|
|
|
|
// Toast with descriptions
|
|
export const ToastWithDescriptions: Story = {
|
|
render: () => (
|
|
<div className="p-8 space-y-4">
|
|
<h2 className="text-lg font-semibold">Toasts with Descriptions</h2>
|
|
<div className="flex gap-4 flex-wrap">
|
|
<Button
|
|
onClick={() =>
|
|
toast('File uploaded', {
|
|
description: 'Your file has been successfully uploaded to the server.',
|
|
})
|
|
}
|
|
variant="solid"
|
|
color="primary"
|
|
>
|
|
With Description
|
|
</Button>
|
|
<Button
|
|
onClick={() =>
|
|
toast.error('Upload failed', {
|
|
description: 'The file could not be uploaded. Please try again.',
|
|
})
|
|
}
|
|
variant="solid"
|
|
color="destructive"
|
|
>
|
|
Error with Description
|
|
</Button>
|
|
<Button
|
|
onClick={() =>
|
|
toast.success('Account created', {
|
|
description: 'Welcome! Your account has been successfully created.',
|
|
})
|
|
}
|
|
variant="solid"
|
|
color="primary"
|
|
>
|
|
Success with Description
|
|
</Button>
|
|
</div>
|
|
<Toaster />
|
|
</div>
|
|
),
|
|
};
|
|
|
|
// Toast with actions
|
|
export const ToastWithActions: Story = {
|
|
render: () => (
|
|
<div className="p-8 space-y-4">
|
|
<h2 className="text-lg font-semibold">Toasts with Actions</h2>
|
|
<div className="flex gap-4 flex-wrap">
|
|
<Button
|
|
onClick={() =>
|
|
toast('Undo action', {
|
|
action: {
|
|
label: 'Undo',
|
|
onClick: () => console.log('Undo clicked'),
|
|
},
|
|
})
|
|
}
|
|
variant="solid"
|
|
color="primary"
|
|
>
|
|
With Action Button
|
|
</Button>
|
|
<Button
|
|
onClick={() =>
|
|
toast.error('Delete item', {
|
|
description: 'This action cannot be undone.',
|
|
action: {
|
|
label: 'Undo',
|
|
onClick: () => console.log('Undo delete'),
|
|
},
|
|
})
|
|
}
|
|
variant="solid"
|
|
color="destructive"
|
|
>
|
|
Error with Action
|
|
</Button>
|
|
<Button
|
|
onClick={() =>
|
|
toast('Download complete', {
|
|
description: 'Your file has been downloaded.',
|
|
action: {
|
|
label: 'Open',
|
|
onClick: () => console.log('Open file'),
|
|
},
|
|
})
|
|
}
|
|
variant="solid"
|
|
color="primary"
|
|
>
|
|
Success with Action
|
|
</Button>
|
|
</div>
|
|
<Toaster />
|
|
</div>
|
|
),
|
|
};
|
|
|
|
// Toast positions
|
|
export const ToastPositions: Story = {
|
|
render: () => (
|
|
<div className="p-8 space-y-4">
|
|
<h2 className="text-lg font-semibold">Toast Positions</h2>
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<div className="space-y-2">
|
|
<h3 className="text-sm font-medium">Top Positions</h3>
|
|
<div className="flex gap-2 flex-wrap">
|
|
<Button
|
|
onClick={() => toast('Top left', { position: 'top-left' })}
|
|
variant="outlined"
|
|
size="sm"
|
|
color={ButtonColor.None}
|
|
>
|
|
Top Left
|
|
</Button>
|
|
<Button
|
|
onClick={() => toast('Top center', { position: 'top-center' })}
|
|
variant="outlined"
|
|
size="sm"
|
|
color={ButtonColor.None}
|
|
>
|
|
Top Center
|
|
</Button>
|
|
<Button
|
|
onClick={() => toast('Top right', { position: 'top-right' })}
|
|
variant="outlined"
|
|
size="sm"
|
|
color={ButtonColor.None}
|
|
>
|
|
Top Right
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<h3 className="text-sm font-medium">Bottom Positions</h3>
|
|
<div className="flex gap-2 flex-wrap">
|
|
<Button
|
|
onClick={() => toast('Bottom left', { position: 'bottom-left' })}
|
|
variant="outlined"
|
|
size="sm"
|
|
color={ButtonColor.None}
|
|
>
|
|
Bottom Left
|
|
</Button>
|
|
<Button
|
|
onClick={() => toast('Bottom center', { position: 'bottom-center' })}
|
|
variant="outlined"
|
|
size="sm"
|
|
color={ButtonColor.None}
|
|
>
|
|
Bottom Center
|
|
</Button>
|
|
<Button
|
|
onClick={() => toast('Bottom right', { position: 'bottom-right' })}
|
|
variant="outlined"
|
|
size="sm"
|
|
color={ButtonColor.None}
|
|
>
|
|
Bottom Right
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<Toaster />
|
|
</div>
|
|
),
|
|
};
|
|
|
|
// Toast durations
|
|
export const ToastDurations: Story = {
|
|
render: () => (
|
|
<div className="p-8 space-y-4">
|
|
<h2 className="text-lg font-semibold">Toast Durations</h2>
|
|
<div className="flex gap-4 flex-wrap">
|
|
<Button
|
|
onClick={() => toast('Quick message', { duration: 1000 })}
|
|
variant="solid"
|
|
color="primary"
|
|
>
|
|
1 Second
|
|
</Button>
|
|
<Button
|
|
onClick={() => toast('Standard message', { duration: 4000 })}
|
|
variant="solid"
|
|
color="primary"
|
|
>
|
|
4 Seconds
|
|
</Button>
|
|
<Button
|
|
onClick={() => toast('Long message', { duration: 8000 })}
|
|
variant="solid"
|
|
color="primary"
|
|
>
|
|
8 Seconds
|
|
</Button>
|
|
<Button
|
|
onClick={() => toast('Persistent message', { duration: Infinity })}
|
|
variant="solid"
|
|
color="warning"
|
|
>
|
|
Persistent
|
|
</Button>
|
|
</div>
|
|
<Toaster />
|
|
</div>
|
|
),
|
|
};
|
|
|
|
// Toast with custom styling
|
|
export const CustomStyledToasts: Story = {
|
|
render: () => (
|
|
<div className="p-8 space-y-4">
|
|
<h2 className="text-lg font-semibold">Custom Styled Toasts</h2>
|
|
<div className="flex gap-4 flex-wrap">
|
|
<Button
|
|
onClick={() =>
|
|
toast.custom(() => (
|
|
<div className="bg-blue-500 text-white p-4 rounded-lg shadow-lg">
|
|
<div className="font-semibold">Custom Toast</div>
|
|
<div className="text-sm opacity-90">This is a custom styled toast</div>
|
|
</div>
|
|
))
|
|
}
|
|
variant="solid"
|
|
color="primary"
|
|
>
|
|
Custom Styled
|
|
</Button>
|
|
<Button
|
|
onClick={() =>
|
|
toast.custom(() => (
|
|
<div className="bg-gradient-to-r from-purple-500 to-pink-500 text-white p-4 rounded-lg shadow-lg">
|
|
<div className="font-semibold">Gradient Toast</div>
|
|
<div className="text-sm opacity-90">With gradient background</div>
|
|
</div>
|
|
))
|
|
}
|
|
variant="solid"
|
|
color="primary"
|
|
>
|
|
Gradient Toast
|
|
</Button>
|
|
<Button
|
|
onClick={() =>
|
|
toast.custom(() => (
|
|
<div className="bg-yellow-400 text-black p-4 rounded-lg shadow-lg border-2 border-yellow-600">
|
|
<div className="font-semibold">⚠️ Warning</div>
|
|
<div className="text-sm">Custom warning style</div>
|
|
</div>
|
|
))
|
|
}
|
|
variant="solid"
|
|
color="warning"
|
|
>
|
|
Custom Warning
|
|
</Button>
|
|
</div>
|
|
<Toaster />
|
|
</div>
|
|
),
|
|
};
|
|
|
|
// Toast with promises
|
|
export const ToastWithPromises: Story = {
|
|
render: () => (
|
|
<div className="p-8 space-y-4">
|
|
<h2 className="text-lg font-semibold">Toasts with Promises</h2>
|
|
<div className="flex gap-4 flex-wrap">
|
|
<Button
|
|
onClick={() => {
|
|
const promise = new Promise((resolve) => setTimeout(resolve, 2000));
|
|
toast.promise(promise, {
|
|
loading: 'Loading...',
|
|
success: 'Success!',
|
|
error: 'Error!',
|
|
});
|
|
}}
|
|
variant="solid"
|
|
color="primary"
|
|
>
|
|
Promise Toast
|
|
</Button>
|
|
<Button
|
|
onClick={() => {
|
|
const promise = new Promise((resolve, reject) => {
|
|
setTimeout(() => {
|
|
if (Math.random() > 0.5) {
|
|
resolve('Success');
|
|
} else {
|
|
reject(new Error('Failed'));
|
|
}
|
|
}, 2000);
|
|
});
|
|
toast.promise(promise, {
|
|
loading: 'Processing your request...',
|
|
success: 'Request completed successfully!',
|
|
error: 'Request failed. Please try again.',
|
|
});
|
|
}}
|
|
variant="solid"
|
|
color="primary"
|
|
>
|
|
Random Promise
|
|
</Button>
|
|
<Button
|
|
onClick={() => {
|
|
const promise = new Promise((resolve) => setTimeout(resolve, 3000));
|
|
toast.promise(promise, {
|
|
loading: 'Uploading file...',
|
|
success: 'File uploaded successfully!',
|
|
error: 'Upload failed. Please try again.',
|
|
});
|
|
}}
|
|
variant="solid"
|
|
color="primary"
|
|
>
|
|
File Upload
|
|
</Button>
|
|
</div>
|
|
<Toaster />
|
|
</div>
|
|
),
|
|
};
|
|
|
|
// Multiple toasts
|
|
export const MultipleToasts: Story = {
|
|
render: () => (
|
|
<div className="p-8 space-y-4">
|
|
<h2 className="text-lg font-semibold">Multiple Toasts</h2>
|
|
<div className="flex gap-4 flex-wrap">
|
|
<Button
|
|
onClick={() => {
|
|
toast('First toast');
|
|
setTimeout(() => toast('Second toast'), 500);
|
|
setTimeout(() => toast('Third toast'), 1000);
|
|
setTimeout(() => toast('Fourth toast'), 1500);
|
|
}}
|
|
variant="solid"
|
|
color="primary"
|
|
>
|
|
Show Multiple
|
|
</Button>
|
|
<Button
|
|
onClick={() => {
|
|
toast.success('Success 1');
|
|
toast.error('Error 1');
|
|
toast.warning('Warning 1');
|
|
toast.info('Info 1');
|
|
}}
|
|
variant="solid"
|
|
color="primary"
|
|
>
|
|
Different Types
|
|
</Button>
|
|
<Button
|
|
onClick={() => {
|
|
toast('Toast 1', { position: 'top-left' });
|
|
toast('Toast 2', { position: 'top-right' });
|
|
toast('Toast 3', { position: 'bottom-left' });
|
|
toast('Toast 4', { position: 'bottom-right' });
|
|
}}
|
|
variant="solid"
|
|
color="primary"
|
|
>
|
|
Different Positions
|
|
</Button>
|
|
</div>
|
|
<Toaster />
|
|
</div>
|
|
),
|
|
};
|
|
|
|
// Default story for component display
|
|
export const Default: Story = {
|
|
render: () => (
|
|
<div className="p-8 space-y-4">
|
|
<h2 className="text-lg font-semibold">Sonner Toast Component</h2>
|
|
<p className="text-sm text-muted-foreground">
|
|
Click the buttons below to see different types of toasts in action.
|
|
</p>
|
|
<div className="flex gap-4 flex-wrap">
|
|
<Button onClick={() => toast('Hello World!')} variant="solid" color="primary">
|
|
Show Toast
|
|
</Button>
|
|
</div>
|
|
<Toaster />
|
|
</div>
|
|
),
|
|
};
|