close toasts notifications by clicking
Massimo Melina committed
Jul 4, 2024 at 11:53 UTC
856c4c667146f4502cd1c86ec6b6c08323a6a13b
1 file changed
+15
-5
frontend/src/toasts.ts
+15
-5
@@ -12,7 +12,7 @@ type Content = string | ReactElement
12
export function toast(content: Content, type: ToastType='info', { timeout=5_000 }: { timeout?: number } & Omit<ToastOptions, 'id' | 'content' | 'type'>={}) {
13
console.debug("toast", content)
14
const id = Math.random()
15
- toasts.push({ id, content, type })
15
+ toasts.push({ id, content, type, close })
16
const closed = pendingPromise()
17
setTimeout(close, timeout)
18
return {
@@ -29,12 +29,15 @@ export function toast(content: Content, type: ToastType='info', { timeout=5_000
29
}
30
31
interface ToastOptions extends Omit<Partial<HTMLAttributes<HTMLDivElement>>, 'id' | 'content'> {
32
- id: number
32
content: Content
33
type: ToastType
34
+}
35
+interface ToastRecord extends ToastOptions {
36
+ id: number
37
closed?: boolean
38
+ close: () => void
39
}
37
-const toasts = proxy<ToastOptions[]>([])
40
+const toasts = proxy<ToastRecord[]>([])
41
42
export function Toasts() {
43
const snap = useSnapshot(toasts)
@@ -44,7 +47,7 @@ export function Toasts() {
47
)
48
}
49
47
-function Toast({ content, type, closed, id, ...props }: ToastOptions) {
50
+function Toast({ content, type, closed, id, close, ...props }: ToastRecord) {
51
const [addClass, setAddClass] = useState('before')
52
const [height, setHeight] = useState('')
53
useEffect(() => {
@@ -59,7 +62,14 @@ function Toast({ content, type, closed, id, ...props }: ToastOptions) {
62
}, [addClass])
63
const ref = useRef<HTMLDivElement | null>()
64
content = useMemo(() => isValidElement(content) ? cloneElement(content) : content, [content]) // proxied elements are frozen, and crash
62
- return h('div', { ...props, ref, style: { height }, onTransitionEnd, className: `toast ${addClass} ${_.isString(type) ? 'toast-' + type : ''} ${props.className || ''}`},
65
+ return h('div', {
66
+ ...props,
67
+ ref,
68
+ style: { height },
69
+ onTransitionEnd,
70
+ onClick: close,
71
+ className: `toast ${addClass} ${_.isString(type) ? 'toast-' + type : ''} ${props.className || ''}`
72
+ },
73
h('div', { className: 'toast-icon' }, isValidElement(type) ? type : hIcon(type)),
74
h('div', { className: 'toast-content' }, content)
75
)