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
|
||||
|
||||
export const Toasts = () => {
|
||||
const { toasts } = useStore()
|
||||
const ToastContext = createContext([])
|
||||
|
||||
export const ToastProvider = ({ children }) => {
|
||||
const [toasts, setToasts] = useState([])
|
||||
|
||||
const removeToast = uid => {
|
||||
setToasts(toasts => toasts.filter(t => t.uid !== uid))
|
||||
}
|
||||
|
||||
return (
|
||||
<ToastContext.Provider value={{ toasts, setToasts }}>
|
||||
{children}
|
||||
<div class="toasts">
|
||||
{toasts.map(({ i, removed, message }) => (
|
||||
<div key={i} class={removed ? 'toast removed' : 'toast'}>
|
||||
{message}
|
||||
{toasts.map(({ uid, removed, message }) => (
|
||||
<div key={uid} class={removed ? 'toast removed' : 'toast'}>
|
||||
<p>{message}</p>
|
||||
<div class="toast-close" onClick={() => removeToast(uid)}>
|
||||
<Icon name="close" />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</ToastContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
const cleanToasts = setToasts => {
|
||||
setToasts(ts => ts.filter((t, i) => !t.removed))
|
||||
}
|
||||
export const useToasts = () => {
|
||||
const { setToasts } = useContext(ToastContext)
|
||||
|
||||
export const showToast = (_toasts, setToasts) => message => {
|
||||
const toast = { i: globalToastId++, removed: false, message }
|
||||
const showToast = (message, { duration } = {}) => {
|
||||
duration ??= 3000
|
||||
|
||||
const toast = { uid: globalToastId++, removed: false, message }
|
||||
|
||||
setTimeout(() => {
|
||||
setToasts(ts => ts.map(t => (t === toast ? { ...t, removed: true } : t)))
|
||||
}, 3000)
|
||||
setToasts(toasts => toasts.map(t => (t === toast ? { ...t, removed: true } : t)))
|
||||
}, duration)
|
||||
|
||||
setTimeout(() => {
|
||||
cleanToasts(setToasts)
|
||||
}, 4000)
|
||||
setToasts(toasts => toasts.filter(t => !t.removed))
|
||||
}, duration + 1000)
|
||||
|
||||
setToasts(ts => [...ts.slice(-5), toast])
|
||||
}
|
||||
|
||||
const clearToasts = () => {
|
||||
setToasts([])
|
||||
}
|
||||
|
||||
return [showToast, clearToasts]
|
||||
}
|
||||
|
Loading…
Reference in New Issue