Remove client-side isLoggedIn value
[ProtonMail-WebClient.git] / packages / pass / components / Spotlight / SpotlightContent.tsx
blob59d42f0821c1c6766fea2e096bcc6cbcc73f273d
1 import { type ComponentType, type ElementType, type FC, type MouseEvent, type ReactNode, useCallback } from 'react';
3 import { c } from 'ttag';
5 import { Button } from '@proton/atoms';
6 import { Icon } from '@proton/components';
7 import { useSpotlight } from '@proton/pass/components/Spotlight/SpotlightProvider';
8 import { SpotlightMessage } from '@proton/pass/types';
9 import { pipe } from '@proton/pass/utils/fp/pipe';
10 import clsx from '@proton/utils/clsx';
12 import './SpotlightContent.scss';
14 export type BaseSpotlightMessage = {
15     className?: string;
16     hidden?: boolean;
17     id: string;
18     type: SpotlightMessage;
19     weak?: boolean;
20     onClose?: () => void;
23 export type DefaultSplotlightMessage = BaseSpotlightMessage & {
24     mode: 'default';
25     action?: { label: string; onClick: (e: MouseEvent<HTMLElement>) => void; type: 'link' | 'button' };
26     dense?: boolean;
27     icon?: ElementType;
28     message: ReactNode;
29     title: ReactNode;
32 export type CustomSplotlightMessage = BaseSpotlightMessage & {
33     mode: 'custom';
34     component: ComponentType<BaseSpotlightMessage>;
37 export type SpotlightMessageDefinition = DefaultSplotlightMessage | CustomSplotlightMessage;
39 export const SpotlightContent: FC<SpotlightMessageDefinition> = (props) => {
40     const { acknowledge } = useSpotlight();
42     const onClose = useCallback(() => {
43         if (props.type !== SpotlightMessage.NOOP) acknowledge(props.type);
44         props.onClose?.();
45     }, [props]);
47     return (
48         <div
49             className={clsx(
50                 props.className,
51                 props.mode === 'default' && props.weak && 'weak',
52                 `pass-spotlight-content flex items-center gap-4 p-4 pr-6 rounded relative mt-2`
53             )}
54         >
55             <Button
56                 icon
57                 pill
58                 shape="ghost"
59                 color="weak"
60                 size="small"
61                 className="absolute top-0 right-0"
62                 onClick={onClose}
63             >
64                 <Icon name="cross-circle-filled" color="var(--interaction-norm-contrast)" alt={c('Action').t`Close`} />
65             </Button>
67             {(() => {
68                 switch (props.mode) {
69                     case 'custom': {
70                         const { component, ...rest } = props;
71                         const Component = component;
72                         return <Component {...rest} onClose={onClose} />;
73                     }
75                     case 'default': {
76                         const { action, dense, icon: CustomIcon, message, title, weak } = props;
78                         const actionNode = (() => {
79                             switch (action?.type) {
80                                 case 'link':
81                                     return (
82                                         <button
83                                             onClick={pipe(action.onClick, onClose)}
84                                             className="unstyled text-sm color-invert px-3"
85                                         >
86                                             <span className="text-underline">{action.label}</span>
87                                         </button>
88                                     );
89                                 case 'button':
90                                     return (
91                                         <Button
92                                             pill
93                                             shape="solid"
94                                             color="norm"
95                                             size="small"
96                                             className="text-sm px-3"
97                                             onClick={pipe(action.onClick, onClose)}
98                                             style={{ backgroundColor: 'var(--interaction-norm-major-3)' }}
99                                         >
100                                             {action.label}
101                                         </Button>
102                                     );
103                             }
104                         })();
106                         return (
107                             <>
108                                 <div className="flex-1">
109                                     <strong className={clsx('block', !weak && 'color-invert')}>{title}</strong>
110                                     <span className={clsx('block text-sm', !weak && 'color-invert')}>{message}</span>
111                                     {!dense && <div className="mt-2">{actionNode}</div>}
112                                 </div>
114                                 {CustomIcon && (
115                                     <div {...(dense ? { style: { order: -1 } } : { className: 'mr-2' })}>
116                                         <CustomIcon />
117                                     </div>
118                                 )}
120                                 {dense && actionNode}
121                             </>
122                         );
123                     }
124                 }
125             })()}
126         </div>
127     );