main
tsx 82 lines 2.8 KB
Raw
1 /**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8 import {
9 BanIcon,
10 ExclamationIcon,
11 InformationCircleIcon,
12 XIcon,
13 } from '@heroicons/react/solid';
14 import {CustomContentProps, SnackbarContent, useSnackbar} from 'notistack';
15 import {forwardRef} from 'react';
16 import {MessageLevel, MessageSource} from '../lib/stores';
17
18 // https://notistack.com/examples/advanced/custom-component#custom-variant-(typescript)
19 declare module 'notistack' {
20 interface VariantOverrides {
21 message: {
22 title: string;
23 level: MessageLevel;
24 codeframe: string | undefined;
25 };
26 }
27 }
28
29 interface MessageProps extends CustomContentProps {
30 title: string;
31 level: MessageLevel;
32 source: MessageSource;
33 codeframe: string | undefined;
34 }
35
36 const Message = forwardRef<HTMLDivElement, MessageProps>(
37 ({id, title, level, source, codeframe}, ref) => {
38 const {closeSnackbar} = useSnackbar();
39 const isDismissible = source !== MessageSource.Playground;
40
41 return (
42 <SnackbarContent
43 ref={ref}
44 className="flex items-start justify-between gap-3 px-4 py-3 text-sm bg-white border rounded-md shadow w-toast">
45 <div className="flex gap-3 w-toast-body">
46 {level === MessageLevel.Warning ? (
47 <div className="flex items-center justify-center flex-none rounded-md w-7 h-7 bg-amber-100">
48 <ExclamationIcon className="w-5 h-5 text-amber-600" />
49 </div>
50 ) : level === MessageLevel.Error ? (
51 <div className="flex items-center justify-center flex-none bg-red-100 rounded-md w-7 h-7">
52 <BanIcon className="w-5 h-5 text-red-600" />
53 </div>
54 ) : (
55 <div className="flex items-center justify-center flex-none rounded-md bg-sky-100 w-7 h-7">
56 <InformationCircleIcon className="w-5 h-5 text-sky-600" />
57 </div>
58 )}
59 <div className="flex flex-col justify-center gap-1 w-toast-title">
60 <p className="w-full">{title}</p>
61 {codeframe ? (
62 <pre className="overflow-x-auto break-words whitespace-pre-wrap">
63 <code className="text-xs">{codeframe}</code>
64 </pre>
65 ) : null}
66 </div>
67 </div>
68 {isDismissible ? (
69 <button
70 className="flex items-center justify-center flex-none transition-colors duration-150 ease-in rounded-md justify-self-end group w-7 h-7 hover:bg-gray-200"
71 onClick={() => closeSnackbar(id)}>
72 <XIcon className="w-5 h-5 fill-gray-500 group-hover:fill-gray-800" />
73 </button>
74 ) : null}
75 </SnackbarContent>
76 );
77 },
78 );
79
80 Message.displayName = 'MessageComponent';
81
82 export default Message;