2023-01-19 13:31:49 +00:00
|
|
|
import clsx from 'clsx';
|
2023-05-05 02:02:31 +00:00
|
|
|
import { AlertCircle, AlertTriangle, CheckCircle, XCircle } from 'lucide-react';
|
2023-01-19 13:31:49 +00:00
|
|
|
import { PropsWithChildren, ReactNode } from 'react';
|
|
|
|
|
|
|
|
import { Icon } from '@@/Icon';
|
|
|
|
|
2023-05-05 02:02:31 +00:00
|
|
|
type AlertType = 'success' | 'error' | 'info' | 'warn';
|
2023-01-19 13:31:49 +00:00
|
|
|
|
|
|
|
const alertSettings: Record<
|
|
|
|
AlertType,
|
|
|
|
{ container: string; header: string; body: string; icon: ReactNode }
|
|
|
|
> = {
|
|
|
|
success: {
|
|
|
|
container:
|
|
|
|
'border-green-4 bg-green-2 th-dark:bg-green-3 th-dark:border-green-5',
|
|
|
|
header: 'text-green-8',
|
|
|
|
body: 'text-green-7',
|
|
|
|
icon: CheckCircle,
|
|
|
|
},
|
|
|
|
error: {
|
|
|
|
container:
|
|
|
|
'border-error-4 bg-error-2 th-dark:bg-error-3 th-dark:border-error-5',
|
|
|
|
header: 'text-error-8',
|
|
|
|
body: 'text-error-7',
|
|
|
|
icon: XCircle,
|
|
|
|
},
|
|
|
|
info: {
|
|
|
|
container:
|
|
|
|
'border-blue-4 bg-blue-2 th-dark:bg-blue-3 th-dark:border-blue-5',
|
|
|
|
header: 'text-blue-8',
|
|
|
|
body: 'text-blue-7',
|
|
|
|
icon: AlertCircle,
|
|
|
|
},
|
2023-05-05 02:02:31 +00:00
|
|
|
warn: {
|
|
|
|
container:
|
|
|
|
'border-warning-4 bg-warning-2 th-dark:bg-warning-3 th-dark:border-warning-5',
|
|
|
|
header: 'text-warning-8',
|
|
|
|
body: 'text-warning-7',
|
|
|
|
icon: AlertTriangle,
|
|
|
|
},
|
2023-01-19 13:31:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
export function Alert({
|
|
|
|
color,
|
|
|
|
title,
|
2023-09-05 16:06:36 +00:00
|
|
|
className,
|
2023-01-19 13:31:49 +00:00
|
|
|
children,
|
2023-09-05 16:06:36 +00:00
|
|
|
}: PropsWithChildren<{
|
|
|
|
color: AlertType;
|
|
|
|
title?: string;
|
|
|
|
className?: string;
|
|
|
|
}>) {
|
2023-01-19 13:31:49 +00:00
|
|
|
const { container, header, body, icon } = alertSettings[color];
|
|
|
|
|
|
|
|
return (
|
2023-09-05 16:06:36 +00:00
|
|
|
<AlertContainer className={clsx(container, className)}>
|
2023-05-05 02:02:31 +00:00
|
|
|
{title ? (
|
|
|
|
<>
|
|
|
|
<AlertHeader className={header}>
|
|
|
|
<Icon icon={icon} />
|
|
|
|
{title}
|
|
|
|
</AlertHeader>
|
2023-09-05 16:06:36 +00:00
|
|
|
<AlertBody className={body} hasTitle={!!title}>
|
|
|
|
{children}
|
|
|
|
</AlertBody>
|
2023-05-05 02:02:31 +00:00
|
|
|
</>
|
|
|
|
) : (
|
2023-09-05 16:06:36 +00:00
|
|
|
<AlertBody
|
|
|
|
className={clsx(body, 'flex items-start gap-2')}
|
|
|
|
hasTitle={!!title}
|
|
|
|
>
|
|
|
|
<Icon icon={icon} className="!mt-0.5 flex-none" /> {children}
|
2023-05-05 02:02:31 +00:00
|
|
|
</AlertBody>
|
|
|
|
)}
|
2023-01-19 13:31:49 +00:00
|
|
|
</AlertContainer>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function AlertContainer({
|
|
|
|
className,
|
|
|
|
children,
|
|
|
|
}: PropsWithChildren<{ className?: string }>) {
|
|
|
|
return (
|
2023-02-12 21:04:24 +00:00
|
|
|
<div className={clsx('rounded-md border-2 border-solid', 'p-3', className)}>
|
2023-01-19 13:31:49 +00:00
|
|
|
{children}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function AlertHeader({
|
|
|
|
className,
|
|
|
|
children,
|
|
|
|
}: PropsWithChildren<{ className?: string }>) {
|
|
|
|
return (
|
|
|
|
<h4
|
2023-05-05 02:02:31 +00:00
|
|
|
className={clsx(
|
|
|
|
'text-base',
|
|
|
|
'!m-0 mb-2 flex items-center gap-2',
|
|
|
|
className
|
|
|
|
)}
|
2023-01-19 13:31:49 +00:00
|
|
|
>
|
|
|
|
{children}
|
|
|
|
</h4>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function AlertBody({
|
|
|
|
className,
|
2023-09-05 16:06:36 +00:00
|
|
|
hasTitle,
|
2023-01-19 13:31:49 +00:00
|
|
|
children,
|
2023-09-05 16:06:36 +00:00
|
|
|
}: PropsWithChildren<{ className?: string; hasTitle: boolean }>) {
|
|
|
|
return (
|
|
|
|
<div className={clsx('text-sm', className, { 'ml-6': hasTitle })}>
|
|
|
|
{children}
|
|
|
|
</div>
|
|
|
|
);
|
2023-01-19 13:31:49 +00:00
|
|
|
}
|