feat(frontend): add loading bar indicator (#1170)

This commit is contained in:
Jakob Ankarhem
2021-03-14 14:46:04 +01:00
committed by GitHub
parent 9e5adeb610
commit 3d6b343413
5 changed files with 282 additions and 8 deletions

View File

@@ -0,0 +1,73 @@
import { NProgress } from '@tanem/react-nprogress';
import React, { useEffect, useState } from 'react';
import ReactDOM from 'react-dom';
import { useRouter } from 'next/router';
interface BarProps {
progress: number;
isFinished: boolean;
}
const Bar = ({ progress, isFinished }: BarProps) => {
return (
<div
className={`fixed top-0 left-0 z-50 w-full transition-opacity ease-out duration-400 ${
isFinished ? 'opacity-0' : 'opacity-100'
}`}
>
<div
className="duration-300 bg-indigo-400 transition-width"
style={{
height: '3px',
width: `${progress * 100}%`,
}}
/>
</div>
);
};
const NProgressBar = ({ loading }: { loading: boolean }) => (
<NProgress isAnimating={loading}>
{({ isFinished, progress }) => (
<Bar progress={progress} isFinished={isFinished} />
)}
</NProgress>
);
const MemoizedNProgress = React.memo(NProgressBar);
const LoadingBar = (): React.ReactPortal | null => {
const [mounted, setMounted] = useState(false);
const [loading, setLoading] = useState(false);
const router = useRouter();
useEffect(() => {
setMounted(true);
}, []);
useEffect(() => {
const handleLoading = () => {
setLoading(true);
};
const handleFinishedLoading = () => {
setLoading(false);
};
router.events.on('routeChangeStart', handleLoading);
router.events.on('routeChangeComplete', handleFinishedLoading);
router.events.on('routeChangeError', handleFinishedLoading);
return () => {
router.events.off('routeChangeStart', handleLoading);
router.events.off('routeChangeComplete', handleFinishedLoading);
router.events.off('routeChangeError', handleFinishedLoading);
};
}, [router]);
return mounted
? ReactDOM.createPortal(
<MemoizedNProgress loading={loading} />,
document.body
)
: null;
};
export default LoadingBar;

View File

@@ -16,6 +16,7 @@ import { InteractionProvider } from '../context/InteractionContext';
import StatusChecker from '../components/StatusChacker';
import { PublicSettingsResponse } from '../../server/interfaces/api/settingsInterfaces';
import { SettingsProvider } from '../context/SettingsContext';
import LoadingBar from '../components/LoadingBar';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const loadLocaleData = (locale: AvailableLocales): Promise<any> => {
@@ -113,6 +114,7 @@ const CoreApp: Omit<NextAppComponentType, 'origGetInitialProps'> = ({
defaultLocale="en"
messages={loadedMessages}
>
<LoadingBar />
<SettingsProvider currentSettings={currentSettings}>
<InteractionProvider>
<ToastProvider components={{ Toast }}>