mirror of
https://github.com/hanzoai/o11y-components.git
synced 2026-10-30 14:54:15 +00:00
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.
483 lines
12 KiB
TypeScript
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>
|
|
),
|
|
};
|