loading-spinner.tsx 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. import { useTranslation } from 'react-i18next'
  2. import { useEffect, useState } from 'react'
  3. import OLSpinner, {
  4. OLSpinnerSize,
  5. } from '@/features/ui/components/ol/ol-spinner'
  6. import { isBootstrap5 } from '@/features/utils/bootstrap-5'
  7. import classNames from 'classnames'
  8. function LoadingSpinner({
  9. align,
  10. delay = 0,
  11. loadingText,
  12. size = 'sm',
  13. className,
  14. }: {
  15. align?: 'left' | 'center'
  16. delay?: 0 | 500 // 500 is our standard delay
  17. loadingText?: string
  18. size?: OLSpinnerSize
  19. className?: string
  20. }) {
  21. const { t } = useTranslation()
  22. const [show, setShow] = useState(false)
  23. useEffect(() => {
  24. // Ensure that spinner is displayed immediately if delay is 0
  25. if (delay === 0) {
  26. setShow(true)
  27. return
  28. }
  29. const timer = window.setTimeout(() => {
  30. setShow(true)
  31. }, delay)
  32. return () => {
  33. window.clearTimeout(timer)
  34. }
  35. }, [delay])
  36. if (!show) {
  37. return null
  38. }
  39. const extraClasses = isBootstrap5()
  40. ? [align === 'left' ? 'align-items-start' : 'align-items-center']
  41. : null
  42. return (
  43. <div className={classNames('loading', className, extraClasses)}>
  44. <OLSpinner size={size} />
  45. &nbsp;
  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. }