klarna/ui-react-components

View on GitHub
components/Loader/index.jsx

Summary

Maintainability
C
7 hrs
Test Coverage
// Based on http://codepen.io/skuester/pen/Hejbz

import React, { PropTypes } from 'react'
import classNamesBind from 'classnames/bind'
import defaultStyles from './styles.scss'

const colors = {
  blue: [0, 116, 200],
  white: [255, 255, 255]
}
colors.default = [158, 158, 160]

const sizes = {
  big: 30,
  small: 15,
  tiny: 10
}
sizes.default = 20

const gradients = [
  {x1: 0, y1: '0', x2: '0', y2: '1'},
  {x1: '1', y1: '0', x2: '0', y2: '1'},
  {x1: '1', y1: '1', x2: '0', y2: '0'},
  {x1: '0', y1: '1', x2: '0', y2: '0'},
  {x1: '0', y1: '1', x2: '1', y2: '0'},
  {x1: '0', y1: '0', x2: '1', y2: '1'}
]

export default function Loader ({ className, color, inline, size, styles }) {
  const classNames = classNamesBind.bind({ ...defaultStyles, ...styles })

  const _color = Array.isArray(color) ? color : colors[color] || colors.default
  const _size = sizes[size] || sizes.default
  const step = 0.2
  const stroke = 2
  const half = _size / 2
  const quarter = _size / 4
  const corner = _size * 0.433

  return (
    <svg width={_size} height={_size} className={classNames('loader', className, { inline })} viewBox={`-1 -1 ${_size + stroke} ${_size + stroke}`}>
      <defs>
        {
          gradients.map((props, index) => (
            <linearGradient key={`gradient-${index}`} id={`gradient-${_color.join('-')}-${index}`} gradientUnits='objectBoundingBox' {...props}>
              <stop offset='0%' stopColor={`rgba(${_color}, ${step * index})`} />
              <stop offset='100%' stopColor={`rgba(${_color}, ${step * (index + 1)})`} />
            </linearGradient>
          ))
        }
      </defs>
      <g fill='none' strokeWidth={stroke} transform={`translate(${half},${half})`}>
        <path d={`M ${corner},-${quarter} A ${half},${half} 0 0,1 ${corner},${quarter}`} stroke={`url(#gradient-${_color.join('-')}-0)`} />
        <path d={`M ${corner},${quarter} A ${half},${half} 0 0,1 0,${half}`} stroke={`url(#gradient-${_color.join('-')}-1)`} />
        <path d={`M 0,${half} A ${half},${half} 0 0,1 -${corner},${quarter}`} stroke={`url(#gradient-${_color.join('-')}-2)`} />
        <path d={`M -${corner},${quarter} A ${half},${half} 0 0,1 -${corner},-${quarter}`} stroke={`url(#gradient-${_color.join('-')}-3)`} />
        <path d={`M -${corner},-${quarter} A ${half},${half} 0 0,1 0,-${half}`} stroke={`url(#gradient-${_color.join('-')}-4)`} />
        <path d={`M 0,-${half} A ${half},${half} 0 0,1 ${corner},-${quarter}`} stroke={`url(#gradient-${_color.join('-')}-5)`} strokeLinecap='round'/>
      </g>
    </svg>
  )
}

Loader.propTypes = {
  className: PropTypes.string,
  color: PropTypes.oneOfType([
    PropTypes.oneOf(Object.keys(colors)),
    PropTypes.array
  ]),
  inline: PropTypes.bool,
  size: PropTypes.oneOf(Object.keys(sizes)),
  styles: PropTypes.object
}