48 lines
1.1 KiB
TypeScript
48 lines
1.1 KiB
TypeScript
import { useEffect } from 'react'
|
|
import { create } from 'zustand'
|
|
|
|
import type { FC } from 'react'
|
|
|
|
type OverlayStore = {
|
|
active: boolean
|
|
setActive: (v: boolean) => void }
|
|
|
|
|
|
export const useOverlayStore = create<OverlayStore> (set => ({
|
|
active: false,
|
|
setActive: v => set ({ active: v }) }))
|
|
|
|
|
|
const RouteBlockerOverlay: FC = () => {
|
|
const active = useOverlayStore (s => s.active)
|
|
|
|
useEffect (() => {
|
|
if (active)
|
|
{
|
|
document.body.style.overflow = 'hidden'
|
|
document.body.setAttribute ('aria-busy', 'true')
|
|
}
|
|
else
|
|
{
|
|
document.body.style.overflow = ''
|
|
document.body.removeAttribute ('aria-busy')
|
|
}
|
|
}, [active])
|
|
|
|
if (!(active))
|
|
return null
|
|
|
|
return (
|
|
<div
|
|
role="progressbar"
|
|
aria-label="Loading"
|
|
className="fixed inset-0 z-[9999] bg-black/50 backdrop-blur-sm pointer-events-auto">
|
|
<div className="absolute inset-0 flex items-center justify-center">
|
|
<div className="rounded-2xl bg-black/60 text-white px-6 py-3 text-sm">
|
|
Loading...
|
|
</div>
|
|
</div>
|
|
</div>)
|
|
}
|
|
|
|
export default RouteBlockerOverlay |