loading-spinner.tsx 1.8 KB

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