-
Notifications
You must be signed in to change notification settings - Fork 11
/
ToastyEntry.tsx
109 lines (96 loc) · 2.43 KB
/
ToastyEntry.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import { Colors } from '../constants/Colors';
import { Icons } from '../icons/Icons';
import { closeToasty } from '../states/Toasty';
import { useDispatch } from '../states/store';
import React, { useCallback } from 'react';
import styled, { css, keyframes } from 'styled-components';
// == styles =======================================================================================
const Content = styled.div`
white-space: pre-wrap;
`;
const Icon = styled.img`
width: 24px;
height: 24px;
flex-shrink: 0;
margin-right: 8px;
`;
const openingKeyframes = keyframes`
0% {
opacity: 0.0;
transform: scale( 0.9 );
}
100% {
}
`;
const closingKeyframes = keyframes`
0% {
}
100% {
opacity: 0.0;
transform: scale( 0.9 );
}
`;
const Root = styled.div<{
kind: 'error' | 'warning' | 'info';
closing: boolean;
}>`
position: relative;
display: flex;
right: 0;
top: 0;
width: calc( 100% - 16px );
margin: 8px;
padding: 8px;
font-size: 12px;
background: ${ Colors.back2 };
box-shadow: ${ ( { kind } ) => (
kind === 'error' ? `0 0 0 1px ${ Colors.error }` :
kind === 'warning' ? `0 0 0 1px ${ Colors.warning }` :
kind === 'info' ? `0 0 0 1px ${ Colors.info }` :
'none'
) };
filter: drop-shadow( 0 0 2px ${ Colors.black } );
pointer-events: auto;
cursor: pointer;
${ ( { closing } ) => (
closing
? css`animation: 0.2s cubic-bezier(0.2, 0.0, 0.0, 1.0) ${ closingKeyframes };`
: css`animation: 0.2s cubic-bezier(0.2, 0.0, 0.0, 1.0) ${ openingKeyframes };`
) }
animation-fill-mode: forwards;
&:active {
background: ${ Colors.back1 };
}
`;
// == component ====================================================================================
const ToastyEntry = ( { id, kind, message, closing }: {
id: string;
kind: 'error' | 'warning' | 'info';
message: string;
closing: boolean;
} ): JSX.Element | null => {
const dispatch = useDispatch();
const icon = (
kind === 'error' ? Icons.Error :
kind === 'warning' ? Icons.Warning :
kind === 'info' ? Icons.Info :
null
);
const handleClick = useCallback(
() => closeToasty( { id, dispatch } ),
[ id, dispatch ]
);
return (
<Root
kind={ kind }
closing={ ( closing ? 1 : 0 ) as any as boolean } // fuck
onClick={ handleClick }
>
{ icon && <Icon as={ icon } /> }
<Content>
{ message }
</Content>
</Root>
);
};
export { ToastyEntry };