loading-spinner.tsx 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import { useTranslation } from 'react-i18next'
  2. import Icon from './icon'
  3. import { useEffect, useState } from 'react'
  4. import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
  5. import { Spinner } from 'react-bootstrap-5'
  6. import { setTimeout } from '@/utils/window'
  7. import classNames from 'classnames'
  8. function LoadingSpinner({
  9. align,
  10. delay = 0,
  11. loadingText,
  12. size,
  13. }: {
  14. align?: 'left' | 'center'
  15. delay?: 0 | 500 // 500 is our standard delay
  16. loadingText?: string
  17. size?: 'sm'
  18. }) {
  19. const { t } = useTranslation()
  20. const [show, setShow] = useState(false)
  21. useEffect(() => {
  22. const timer = setTimeout(() => {
  23. setShow(true)
  24. }, delay)
  25. return () => {
  26. window.clearTimeout(timer)
  27. }
  28. }, [delay])
  29. if (!show) {
  30. return null
  31. }
  32. const alignmentClass =
  33. align === 'left' ? 'align-items-start' : 'align-items-center'
  34. return (
  35. <BootstrapVersionSwitcher
  36. bs3={
  37. <div className="loading">
  38. <Icon type="refresh" fw spin />
  39. &nbsp;
  40. {loadingText || t('loading')}…
  41. </div>
  42. }
  43. bs5={
  44. <div className={classNames(`d-flex ${alignmentClass}`)}>
  45. <Spinner
  46. animation="border"
  47. aria-hidden="true"
  48. role="status"
  49. className="align-self-center"
  50. size={size}
  51. />
  52. &nbsp;
  53. {loadingText || t('loading')}…
  54. </div>
  55. }
  56. />
  57. )
  58. }
  59. export default LoadingSpinner
  60. export function FullSizeLoadingSpinner({
  61. delay = 0,
  62. minHeight,
  63. loadingText,
  64. }: {
  65. delay?: 0 | 500
  66. minHeight?: string
  67. loadingText?: string
  68. }) {
  69. return (
  70. <div className="full-size-loading-spinner-container" style={{ minHeight }}>
  71. <LoadingSpinner loadingText={loadingText} delay={delay} />
  72. </div>
  73. )
  74. }