Better toasts, a bit responsive and more
parent
bd0a9b5c6e
commit
70ab93de0a
@ -1,35 +1,57 @@
|
|||||||
import { useStore } from '../context.jsx'
|
import { createContext } from 'preact'
|
||||||
|
import { useContext, useState } from 'preact/hooks'
|
||||||
|
import { Icon } from './Icon.jsx'
|
||||||
|
|
||||||
let globalToastId = 0
|
let globalToastId = 0
|
||||||
|
|
||||||
export const Toasts = () => {
|
const ToastContext = createContext([])
|
||||||
const { toasts } = useStore()
|
|
||||||
|
export const ToastProvider = ({ children }) => {
|
||||||
|
const [toasts, setToasts] = useState([])
|
||||||
|
|
||||||
|
const removeToast = uid => {
|
||||||
|
setToasts(toasts => toasts.filter(t => t.uid !== uid))
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<ToastContext.Provider value={{ toasts, setToasts }}>
|
||||||
|
{children}
|
||||||
<div class="toasts">
|
<div class="toasts">
|
||||||
{toasts.map(({ i, removed, message }) => (
|
{toasts.map(({ uid, removed, message }) => (
|
||||||
<div key={i} class={removed ? 'toast removed' : 'toast'}>
|
<div key={uid} class={removed ? 'toast removed' : 'toast'}>
|
||||||
{message}
|
<p>{message}</p>
|
||||||
|
<div class="toast-close" onClick={() => removeToast(uid)}>
|
||||||
|
<Icon name="close" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
</ToastContext.Provider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const cleanToasts = setToasts => {
|
export const useToasts = () => {
|
||||||
setToasts(ts => ts.filter((t, i) => !t.removed))
|
const { setToasts } = useContext(ToastContext)
|
||||||
}
|
|
||||||
|
|
||||||
export const showToast = (_toasts, setToasts) => message => {
|
const showToast = (message, { duration } = {}) => {
|
||||||
const toast = { i: globalToastId++, removed: false, message }
|
duration ??= 3000
|
||||||
|
|
||||||
|
const toast = { uid: globalToastId++, removed: false, message }
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setToasts(ts => ts.map(t => (t === toast ? { ...t, removed: true } : t)))
|
setToasts(toasts => toasts.map(t => (t === toast ? { ...t, removed: true } : t)))
|
||||||
}, 3000)
|
}, duration)
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
cleanToasts(setToasts)
|
setToasts(toasts => toasts.filter(t => !t.removed))
|
||||||
}, 4000)
|
}, duration + 1000)
|
||||||
|
|
||||||
setToasts(ts => [...ts.slice(-5), toast])
|
setToasts(ts => [...ts.slice(-5), toast])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const clearToasts = () => {
|
||||||
|
setToasts([])
|
||||||
|
}
|
||||||
|
|
||||||
|
return [showToast, clearToasts]
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue