github.com/grafana/pyroscope@v1.18.0/public/app/ui/LoadingOverlay.tsx (about)

     1  import React, { ReactNode, useEffect, useState } from 'react';
     2  import LoadingSpinner from '@pyroscope/ui/LoadingSpinner';
     3  import cx from 'classnames';
     4  import styles from './LoadingOverlay.module.css';
     5  
     6  /**
     7   * LoadingOverlay when 'active' will cover the entire parent's width/height with
     8   * an overlay and a loading spinner
     9   */
    10  export function LoadingOverlay({
    11    active = true,
    12    spinnerPosition = 'center',
    13    children,
    14    delay = 250,
    15  }: {
    16    /** where to position the spinner. use baseline when the component's vertical center is outside the viewport */
    17    spinnerPosition?: 'center' | 'baseline';
    18    active: boolean;
    19    children?: ReactNode;
    20    /** delay in ms before showing the overlay. this evicts a flick */
    21    delay?: number;
    22  }) {
    23    const [isVisible, setVisible] = useState(false);
    24  
    25    // Wait for `delay` ms before showing the overlay
    26    // So that it feels snappy when server is fast
    27    // https://www.nngroup.com/articles/progress-indicators/
    28    useEffect(() => {
    29      if (active) {
    30        const timeoutID = window.setTimeout(() => {
    31          setVisible(true);
    32        }, delay);
    33  
    34        return () => clearTimeout(timeoutID);
    35      }
    36  
    37      setVisible(false);
    38      return () => {};
    39    }, [active, delay]);
    40  
    41    return (
    42      <div>
    43        <div
    44          className={cx(
    45            styles.loadingOverlay,
    46            !isVisible ? styles.unactive : null
    47          )}
    48          style={{
    49            alignItems: spinnerPosition,
    50          }}
    51        >
    52          <LoadingSpinner size="46px" />
    53        </div>
    54        {children}
    55      </div>
    56    );
    57  }