mirror of
https://github.com/yangshun/tech-interview-handbook.git
synced 2025-08-03 04:04:24 +08:00
ui: add Alert
This commit is contained in:
@ -11,6 +11,10 @@ module.exports = {
|
||||
},
|
||||
colors: {
|
||||
primary: colors.purple,
|
||||
danger: colors.rose,
|
||||
info: colors.sky,
|
||||
success: colors.emerald,
|
||||
warning: colors.amber,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
84
packages/ui/src/Alert/Alert.tsx
Normal file
84
packages/ui/src/Alert/Alert.tsx
Normal file
@ -0,0 +1,84 @@
|
||||
import clsx from 'clsx';
|
||||
import type { ReactNode } from 'react';
|
||||
import {
|
||||
CheckCircleIcon,
|
||||
ExclamationTriangleIcon,
|
||||
InformationCircleIcon,
|
||||
XCircleIcon,
|
||||
} from '@heroicons/react/20/solid';
|
||||
|
||||
export type AlertVariant = 'danger' | 'info' | 'success' | 'warning';
|
||||
|
||||
type Props = Readonly<{
|
||||
children: ReactNode;
|
||||
title?: string;
|
||||
variant: AlertVariant;
|
||||
}>;
|
||||
|
||||
const classes: Record<
|
||||
AlertVariant,
|
||||
Readonly<{
|
||||
backgroundClass: string;
|
||||
bodyClass: string;
|
||||
icon: (props: React.ComponentProps<'svg'>) => JSX.Element;
|
||||
iconClass: string;
|
||||
titleClass: string;
|
||||
}>
|
||||
> = {
|
||||
danger: {
|
||||
backgroundClass: 'bg-danger-50',
|
||||
bodyClass: 'text-danger-700',
|
||||
icon: XCircleIcon,
|
||||
iconClass: 'text-danger-400',
|
||||
titleClass: 'text-danger-800',
|
||||
},
|
||||
info: {
|
||||
backgroundClass: 'bg-info-50',
|
||||
bodyClass: 'text-info-700',
|
||||
icon: InformationCircleIcon,
|
||||
iconClass: 'text-info-400',
|
||||
titleClass: 'text-info-800',
|
||||
},
|
||||
success: {
|
||||
backgroundClass: 'bg-success-50',
|
||||
bodyClass: 'text-success-700',
|
||||
icon: CheckCircleIcon,
|
||||
iconClass: 'text-success-400',
|
||||
titleClass: 'text-success-800',
|
||||
},
|
||||
warning: {
|
||||
backgroundClass: 'bg-warning-50',
|
||||
bodyClass: 'text-warning-700',
|
||||
icon: ExclamationTriangleIcon,
|
||||
iconClass: 'text-warning-400',
|
||||
titleClass: 'text-warning-800',
|
||||
},
|
||||
};
|
||||
|
||||
export default function Alert({ children, title, variant }: Props) {
|
||||
const {
|
||||
backgroundClass,
|
||||
iconClass,
|
||||
titleClass,
|
||||
bodyClass,
|
||||
icon: Icon,
|
||||
} = classes[variant];
|
||||
|
||||
return (
|
||||
<div className={clsx('rounded-md p-4', backgroundClass)}>
|
||||
<div className="flex">
|
||||
<div className="flex-shrink-0">
|
||||
<Icon aria-hidden="true" className={clsx('h-5 w-5', iconClass)} />
|
||||
</div>
|
||||
<div className="ml-3 space-y-2">
|
||||
{title && (
|
||||
<h3 className={clsx('text-sm font-medium', titleClass)}>{title}</h3>
|
||||
)}
|
||||
<div className={clsx('text-sm', bodyClass)}>
|
||||
<p>{children}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -2,7 +2,7 @@ import clsx from 'clsx';
|
||||
import Link from 'next/link';
|
||||
import type { UrlObject } from 'url';
|
||||
|
||||
import Spinner from '../Spinner';
|
||||
import { Spinner } from '../';
|
||||
|
||||
export type ButtonAddOnPosition = 'end' | 'start';
|
||||
export type ButtonDisplay = 'block' | 'inline';
|
||||
|
@ -1,4 +0,0 @@
|
||||
import Button from './Button';
|
||||
|
||||
export * from './Button';
|
||||
export default Button;
|
@ -1,4 +0,0 @@
|
||||
import Spinner from './Spinner';
|
||||
|
||||
export * from './Spinner';
|
||||
export default Spinner;
|
@ -1,4 +1,6 @@
|
||||
export { default as Button } from './Button';
|
||||
export * from './Button';
|
||||
export { default as Spinner } from './Spinner';
|
||||
export * from './Spinner';
|
||||
export * from './Alert/Alert';
|
||||
export { default as Alert } from './Alert/Alert';
|
||||
export * from './Button/Button';
|
||||
export { default as Button } from './Button/Button';
|
||||
export * from './Spinner/Spinner';
|
||||
export { default as Spinner } from './Spinner/Spinner';
|
||||
|
Reference in New Issue
Block a user