# All files / src/Spinner Spinner.tsx

100% Statements 24/24
90.9% Branches 10/11
100% Functions 1/1
100% Lines 20/20

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    9770x
    70x

    70x

    70x

    70x

    1079x
    1079x
    1079x
    1079x
    1079x
    1079x
    1079x
    1079x
    1079x

    1079x

    1079x

    1079x
    1002x

    77x

    70x
     import React from 'react'
    import {
      StyledCircle,
      StyledSpinnerContainer,
      StyledSpinnerContainerWithLabel,
      StyledSpinnerOverlay,
      StyledSpinnerOverlayContainer,
      StyledSpinnerOverlayLabel,
      StyledSpinnerSVG,
    } from './Spinner.styles'
    import { SpinnerProps, SpinnerSize } from './Spinner.types'

    const radiusMap: { [size in SpinnerSize]: number } = {
      xs: 18.5,
      sm: 18,
      md: 20,
      lg: 20.5,
    }

    export const defaultSpinnerSize = 'lg'

    /**

     Spinners indicate a loading state on either a full page or smaller component,
     like a menu, select or button.

     @since 10.19.0

     @see [Storybook](https://procore.github.io/core/core-react/latest/?path=/story/demos-spinner--demo)

     @see [Design Guidelines](https://design.procore.com/spinner)

     */
    export const Spinner = React.forwardRef<HTMLDivElement, SpinnerProps>(
      function Spinner(
        {
          children,
          className = '',
          color,
          label,
          loading = false,
          size = defaultSpinnerSize,
          variant,
          centered = false,
          ...props
        },
        ref
      ) {
        const mountTime = React.useRef(Date.now())

        const circle = (
          <StyledSpinnerContainer
            className={!children ? className : ''}
            $color={color}
            $size={size}
            $variant={variant}
            ref={ref}
          >
            <StyledSpinnerSVG
              viewBox="0 0 48 48"
              xmlns="http://www.w3.org/2000/svg"
              mountTime={mountTime.current}
            >
              <StyledCircle
                cx="24"
                cy="24"
                r={radiusMap[size]}
                mountTime={mountTime.current}
              />
            </StyledSpinnerSVG>
          </StyledSpinnerContainer>
        )

        if (!children) {
          return circle
        }

        return (
          <StyledSpinnerOverlayContainer
            $loading={loading}
            className={className}
            $centered={centered}
            {...props}
          >
            <StyledSpinnerOverlay />
            <StyledSpinnerContainerWithLabel>
              {circle}
              <StyledSpinnerOverlayLabel>{label}</StyledSpinnerOverlayLabel>
            </StyledSpinnerContainerWithLabel>
            {children}
          </StyledSpinnerOverlayContainer>
        )
      }
    )

    Spinner.displayName = 'Spinner'