Skip to content
Snippets Groups Projects
loading-fallback.tsx 3.48 KiB
Newer Older
  • Learn to ignore specific revisions
  • Matthias Feyll's avatar
    Matthias Feyll committed
    import React, { useEffect, useState } from 'react';
    import { Col, Container, Row } from 'react-bootstrap';
    import logo from '/public/logo.png';
    
    interface DelayedRenderProps {
        children: React.ReactNode;
        loading?: {
            minimumLoadingTime: number;
            component: () => JSX.Element
        }
    }
    
    export const SplashScreen = () => {
        const [dots, setDots] = useState('');
    
        useEffect(() => {
            const dotsInterval = setInterval(() => {
                setDots(prev => prev.length >= 3 ? '' : prev + '.');
            }, 500);
    
            return () => clearInterval(dotsInterval);
        }, []);
    
        return (
            <div className="splash-screen-overlay">
                <Container fluid className="h-100 d-flex align-items-center justify-content-center bg-bg-primary">
                    <Row>
                        <Col className="text-center">
                            <div className="loading-bounce mb-4">
                                <img
                                    src={logo}
                                    alt="Logo"
                                    className="img-fluid"
                                    style={{ width: '120px', height: '120px', objectFit: 'contain' }}
                                />
                            </div>
                            <div className="loading-text">
                                <span className="h4 text-secondary">Loading</span>
                                <span className="h4 text-secondary dots-width">{dots}</span>
                            </div>
                        </Col>
                    </Row>
                </Container>
    
                <style>
                    {`
                        .splash-screen-overlay {
                            position: fixed;
                            top: 0;
                            left: 0;
                            width: 100%;
                            height: 100%;
                            background-color: #f8f9fa;
                            z-index: 0;
                            display: flex;
                            align-items: center;
                            justify-content: center;
                        }
    
                        .loading-bounce {
                            animation: bounce 1s infinite;
                        }
    
                        @keyframes bounce {
                            0%, 100% {
                                transform: translateY(0);
                            }
                            50% {
                                transform: translateY(-20px);
                            }
                        }
    
                        .loading-text {
                            display: flex;
                            justify-content: center;
                            align-items: center;
                        }
    
                        .dots-width {
                            min-width: 24px;
                            text-align: left;
                            margin-left: 2px;
                        }
                    `}
                </style>
            </div>
        );
    };
    
    export const DelayedRender: React.FC<DelayedRenderProps> = ({
        children,
        loading
    }) => {
        const [shouldRender, setShouldRender] = useState(false);
    
        useEffect(() => {
            if (!loading) {
                setShouldRender(true);
                return;
            }
    
            const timer = setTimeout(() => {
                setShouldRender(true);
            }, loading.minimumLoadingTime);
    
            return () => clearTimeout(timer);
        }, [loading]);
    
        if (!shouldRender && loading) {
            const LoadingComponent = loading.component;
            return <LoadingComponent />;
        }
    
        return <>{children}</>;
    };
    
    export default DelayedRender;