Files
zeekay 464e1eece0 State a version once
A version written into a manifest is written into every manifest that wants it,
which is how eslint came to exist in a hundred and four forms across this estate
and how a package came to resolve twice at run time. The catalog moves the number
out of the manifest: a manifest names the package, the workspace names the
version.

Four are held below their latest because the newer release cannot be used, and
the reason is recorded rather than the version alone: @noble/hashes 2 renamed
every subpath the web3 stack imports, @splinetool/runtime 2 depends on a package
that was never published, @dynamic-labs 5.4.1 the same, and react-resizable-panels
3 points its types condition at the bundle.
2026-09-15 11:45:32 -07:00

483 lines
12 KiB
TypeScript

import { Button, ButtonColor, Toaster, toast } from '@signozhq/ui';
import type { Meta, StoryObj } from '@storybook/react-vite';
const meta: Meta<typeof Toaster> = {
title: 'Primitive Components/Sonner',
component: Toaster,
};
export default meta;
type Story = StoryObj<typeof Toaster>;
// Basic toast examples
export const BasicToasts: Story = {
render: () => (
<div className="stack-16" style={{ padding: 32 }}>
<h2 style={{ fontSize: 18, lineHeight: 1.55556, fontWeight: 600 }}>Basic Toast Examples</h2>
<div style={{ display: 'flex', gap: 16, flexWrap: '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="stack-16" style={{ padding: 32 }}>
<h2 style={{ fontSize: 18, lineHeight: 1.55556, fontWeight: 600 }}>
Toasts with Descriptions
</h2>
<div style={{ display: 'flex', gap: 16, flexWrap: '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="stack-16" style={{ padding: 32 }}>
<h2 style={{ fontSize: 18, lineHeight: 1.55556, fontWeight: 600 }}>Toasts with Actions</h2>
<div style={{ display: 'flex', gap: 16, flexWrap: '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="stack-16" style={{ padding: 32 }}>
<h2 style={{ fontSize: 18, lineHeight: 1.55556, fontWeight: 600 }}>Toast Positions</h2>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(2,minmax(0,1fr))', gap: 16 }}>
<div className="stack-8">
<h3 style={{ fontSize: 14, lineHeight: 1.42857, fontWeight: 500 }}>Top Positions</h3>
<div style={{ display: 'flex', gap: 8, flexWrap: '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="stack-8">
<h3 style={{ fontSize: 14, lineHeight: 1.42857, fontWeight: 500 }}>Bottom Positions</h3>
<div style={{ display: 'flex', gap: 8, flexWrap: '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="stack-16" style={{ padding: 32 }}>
<h2 style={{ fontSize: 18, lineHeight: 1.55556, fontWeight: 600 }}>Toast Durations</h2>
<div style={{ display: 'flex', gap: 16, flexWrap: '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="stack-16" style={{ padding: 32 }}>
<h2 style={{ fontSize: 18, lineHeight: 1.55556, fontWeight: 600 }}>Custom Styled Toasts</h2>
<div style={{ display: 'flex', gap: 16, flexWrap: 'wrap' }}>
<Button
onClick={() =>
toast.custom(() => (
<div
style={{
backgroundColor: '#3080ff',
color: '#fff',
padding: 16,
borderRadius: 4,
boxShadow:
'0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a',
}}
>
<div style={{ fontWeight: 600 }}>Custom Toast</div>
<div style={{ fontSize: 14, lineHeight: 1.42857, opacity: 0.9 }}>
This is a custom styled toast
</div>
</div>
))
}
variant="solid"
color="primary"
>
Custom Styled
</Button>
<Button
onClick={() =>
toast.custom(() => (
<div
style={{
backgroundImage: 'linear-gradient(to right in oklab, #ac4bff, #f6339a)',
color: '#fff',
padding: 16,
borderRadius: 4,
boxShadow:
'0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a',
}}
>
<div style={{ fontWeight: 600 }}>Gradient Toast</div>
<div style={{ fontSize: 14, lineHeight: 1.42857, opacity: 0.9 }}>
With gradient background
</div>
</div>
))
}
variant="solid"
color="primary"
>
Gradient Toast
</Button>
<Button
onClick={() =>
toast.custom(() => (
<div
style={{
backgroundColor: '#fac800',
color: '#000',
padding: 16,
borderRadius: 4,
boxShadow:
'0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a',
borderStyle: 'solid',
borderWidth: 2,
borderColor: '#cd8900',
}}
>
<div style={{ fontWeight: 600 }}>⚠️ Warning</div>
<div style={{ fontSize: 14, lineHeight: 1.42857 }}>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="stack-16" style={{ padding: 32 }}>
<h2 style={{ fontSize: 18, lineHeight: 1.55556, fontWeight: 600 }}>Toasts with Promises</h2>
<div style={{ display: 'flex', gap: 16, flexWrap: '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="stack-16" style={{ padding: 32 }}>
<h2 style={{ fontSize: 18, lineHeight: 1.55556, fontWeight: 600 }}>Multiple Toasts</h2>
<div style={{ display: 'flex', gap: 16, flexWrap: '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="stack-16" style={{ padding: 32 }}>
<h2 style={{ fontSize: 18, lineHeight: 1.55556, fontWeight: 600 }}>Sonner Toast Component</h2>
<p style={{ fontSize: 14, lineHeight: 1.42857, color: 'var(--muted-foreground)' }}>
Click the buttons below to see different types of toasts in action.
</p>
<div style={{ display: 'flex', gap: 16, flexWrap: 'wrap' }}>
<Button onClick={() => toast('Hello World!')} variant="solid" color="primary">
Show Toast
</Button>
</div>
<Toaster />
</div>
),
};