feat: add loading overlay to between navigations and to auth form events
This commit is contained in:
@@ -0,0 +1,10 @@
|
|||||||
|
import LoadingOverlay from '@/components/loading/LoadingOverlay'
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
function Loading() {
|
||||||
|
return (
|
||||||
|
<LoadingOverlay />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Loading
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import PingAnimation from './animations/PingAnimation';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
visible?: boolean;
|
||||||
|
bgOpacity?: number;
|
||||||
|
delay?: number;
|
||||||
|
} & React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>
|
||||||
|
|
||||||
|
const LoadingOverlay = ({ visible = true, bgOpacity = 30, delay = 0, children = <PingAnimation /> }: Props) => {
|
||||||
|
const [loaded, setLoaded] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Trigger fade-in after mount
|
||||||
|
const timeout = setTimeout(() => setLoaded(visible), 300);
|
||||||
|
return () => clearTimeout(timeout);
|
||||||
|
}, [visible]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
data-visible={visible}
|
||||||
|
data-loaded={loaded}
|
||||||
|
className={`absolute inset-0 flex items-center justify-center
|
||||||
|
backdrop-blur-sm bg-background/${bgOpacity}
|
||||||
|
opacity-0 transition-opacity duration-300 ease-in-out delay-${delay}
|
||||||
|
data-[loaded=false]:-z-100
|
||||||
|
data-[visible=true]:z-100
|
||||||
|
data-[visible=true]:opacity-100`}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LoadingOverlay
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
type Props = object
|
||||||
|
|
||||||
|
function PingAnimation({ }: Props) {
|
||||||
|
return (
|
||||||
|
<div className="relative w-16 h-16">
|
||||||
|
<div className="absolute inset-0 rounded-full border-4 border-foreground/30 animate-ping" />
|
||||||
|
<div className="absolute inset-0 flex items-center justify-center">
|
||||||
|
<div className="w-8 h-8 border-4 border-foreground border-t-transparent rounded-full animate-spin" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PingAnimation
|
||||||
@@ -1,14 +1,16 @@
|
|||||||
|
import LoadingOverlay from '@/components/loading/LoadingOverlay';
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isPending: boolean
|
isPending: boolean
|
||||||
} & Omit<React.FormHTMLAttributes<HTMLFormElement>, "id">;
|
} & Omit<React.FormHTMLAttributes<HTMLFormElement>, "id">;
|
||||||
|
|
||||||
function AuthFormWrapper({ children, ...restProps }: Props) {
|
function AuthFormWrapper({ children, isPending, ...restProps }: Props) {
|
||||||
return (
|
return (
|
||||||
<form {...restProps} className='p-6 lg:py-[75px] w-full flex items-center justify-center py-4 lg:items-center lg:px-10 px-4 drop-shadow-black h-full'>
|
<form {...restProps} className='p-6 lg:py-[75px] w-full flex items-center justify-center py-4 lg:items-center lg:px-10 px-4 drop-shadow-black h-full'>
|
||||||
<div className='h-full w-full px-4 sm:px-6 lg:p-0 flex flex-col max-h-[812px] max-w-[1200px] bg-container rounded-container overflow-clip lg:flex-row justify-between'>
|
<div className='relative h-full w-full px-4 sm:px-6 lg:p-0 flex flex-col max-h-[812px] max-w-[1200px] bg-container rounded-container overflow-clip lg:flex-row justify-between'>
|
||||||
{children}
|
{children}
|
||||||
|
<LoadingOverlay visible={isPending} />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user