71 lines
2.1 KiB
TypeScript
71 lines
2.1 KiB
TypeScript
import { X } from 'lucide-react';
|
|
import { ReactNode } from 'react';
|
|
import { Box } from './Box';
|
|
import { IconButton } from './IconButton';
|
|
import { Surface } from './Surface';
|
|
import { Text } from './Text';
|
|
|
|
export interface ToastProps {
|
|
children: ReactNode;
|
|
title?: string;
|
|
onClose: () => void;
|
|
icon?: ReactNode;
|
|
intent?: 'primary' | 'success' | 'warning' | 'critical';
|
|
isVisible: boolean;
|
|
isExiting: boolean;
|
|
progress?: number;
|
|
}
|
|
|
|
export const Toast = ({
|
|
children,
|
|
title,
|
|
onClose,
|
|
icon,
|
|
intent = 'primary',
|
|
isVisible,
|
|
isExiting,
|
|
progress
|
|
}: ToastProps) => {
|
|
const intentColors = {
|
|
primary: 'var(--ui-color-intent-primary)',
|
|
success: 'var(--ui-color-intent-success)',
|
|
warning: 'var(--ui-color-intent-warning)',
|
|
critical: 'var(--ui-color-intent-critical)',
|
|
};
|
|
|
|
return (
|
|
<Box
|
|
style={{
|
|
transform: isVisible && !isExiting ? 'translateX(0)' : 'translateX(100%)',
|
|
opacity: isVisible && !isExiting ? 1 : 0,
|
|
transition: 'all 0.3s ease-in-out',
|
|
width: '24rem'
|
|
}}
|
|
>
|
|
<Surface variant="muted" rounded="xl" shadow="xl" style={{ border: `1px solid ${intentColors[intent]}33`, overflow: 'hidden' }}>
|
|
{progress !== undefined && (
|
|
<Box height="1px" bg="rgba(255,255,255,0.1)">
|
|
<Box height="100%" bg={intentColors[intent]} style={{ width: `${progress}%`, transition: 'width 0.1s linear' }} />
|
|
</Box>
|
|
)}
|
|
<Box padding={4} display="flex" gap={3}>
|
|
{icon && (
|
|
<Box padding={2} rounded="lg" bg="var(--ui-color-bg-surface-muted)" flexShrink={0}>
|
|
{icon}
|
|
</Box>
|
|
)}
|
|
<Box flex={1} minWidth="0">
|
|
<Box display="flex" alignItems="start" justifyContent="between" gap={2}>
|
|
{title && <Text size="sm" weight="bold" variant="high" truncate>{title}</Text>}
|
|
<IconButton icon={X} size="sm" variant="ghost" onClick={onClose} title="Close" />
|
|
</Box>
|
|
<Box marginTop={1}>
|
|
{children}
|
|
</Box>
|
|
</Box>
|
|
</Box>
|
|
</Surface>
|
|
</Box>
|
|
);
|
|
};
|