loading-spinner.tsx 1.6 KB

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