loading-spinner.tsx 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import { useTranslation } from 'react-i18next'
  2. import { useEffect, useState } from 'react'
  3. import OLSpinner, { OLSpinnerSize } from '@/shared/components/ol/ol-spinner'
  4. import classNames from 'classnames'
  5. function LoadingSpinner({
  6. align,
  7. delay = 0,
  8. loadingText,
  9. size = 'sm',
  10. className,
  11. }: {
  12. align?: 'left' | 'center'
  13. delay?: 0 | 500 // 500 is our standard delay
  14. loadingText?: string
  15. size?: OLSpinnerSize
  16. className?: string
  17. }) {
  18. const { t } = useTranslation()
  19. const [show, setShow] = useState(false)
  20. useEffect(() => {
  21. // Ensure that spinner is displayed immediately if delay is 0
  22. if (delay === 0) {
  23. setShow(true)
  24. return
  25. }
  26. const timer = window.setTimeout(() => {
  27. setShow(true)
  28. }, delay)
  29. return () => {
  30. window.clearTimeout(timer)
  31. }
  32. }, [delay])
  33. if (!show) {
  34. return null
  35. }
  36. return (
  37. <div
  38. role="status"
  39. className={classNames(
  40. 'loading',
  41. className,
  42. align === 'left' ? 'align-items-start' : 'align-items-center'
  43. )}
  44. >
  45. <OLSpinner size={size} />
  46. {loadingText || `${t('loading')}…`}
  47. </div>
  48. )
  49. }
  50. export default LoadingSpinner
  51. export function FullSizeLoadingSpinner({
  52. delay = 0,
  53. minHeight,
  54. loadingText,
  55. size = 'sm',
  56. className,
  57. }: {
  58. delay?: 0 | 500
  59. minHeight?: string
  60. loadingText?: string
  61. size?: OLSpinnerSize
  62. className?: string
  63. }) {
  64. return (
  65. <div
  66. className={classNames('full-size-loading-spinner-container', className)}
  67. style={{ minHeight }}
  68. >
  69. <LoadingSpinner size={size} loadingText={loadingText} delay={delay} />
  70. </div>
  71. )
  72. }