Skip to content

Commit

Permalink
Feat/add loader (#100)
Browse files Browse the repository at this point in the history
* feat(loader): first implementations

* feat(loader): add initial work

* feat(loader): remove unecessary code

* feat(loader): add case where time is entered

* feat(loader): add wip

* feat(loader): add base loader and its doc

* feat(loader): add wip

* feat(loader): fix bugs on icon size

* feat(loader): add props to mdx

* feat(loader): add percentage to useEffect

* feat(loader): fix typo

* feat(loader): change icon variant size
  • Loading branch information
Thiago Nunes Batista authored Sep 3, 2020
1 parent bd98be4 commit cd131e2
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 0 deletions.
138 changes: 138 additions & 0 deletions src/components/Loader/Loader.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import React, { useEffect, useRef, useState } from 'react'
import styled, { css, variant } from '@xstyled/styled-components'
import PropTypes from 'prop-types'
import { Typography } from '../'

export const Loader = ({ percentage, showPercentage, size, time, variant }) => {
const [circleLength, setCircleLength] = useState(0)
const externalCircleRef = useRef()

useEffect(() => {
const length = externalCircleRef.current.getTotalLength()
const percent = percentage / 100
const offsetIndeterminate = length * (1 - 0.75)
const offset = length * (1 - percent)
setCircleLength({ length, offset, offsetIndeterminate })
}, [percentage])

return (
<LoaderContainer time={time} size={size} variant={variant} circleLength={circleLength}>
<svg>
<circle />
<circle ref={externalCircleRef} />
</svg>
{showPercentage && percentage && size !== 'icon' && variant !== 'indeterminate' && (
<Typography color='primary' lineHeight='4' fontSize='4' fontWeight='1' as='span'>
{percentage} %
</Typography>
)}
</LoaderContainer>
)
}

const LoaderContainer = styled.div`
display: inline-block;
svg circle {
fill: none;
stroke-linecap: round;
stroke-dashoffset: ${({ circleLength }) => circleLength.offset};
}
svg circle {
stroke: ${({ theme }) => theme.colors.primary};
}
svg circle:nth-child(1) {
opacity: 0.25;
}
svg circle:nth-child(2) {
stroke-dasharray: ${({ circleLength }) => circleLength.length};
}
${variant({
prop: 'variant',
variants: {
determinate: css`
position: relative;
span {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
svg circle:nth-child(2) {
transform: rotate(-90deg) translate(0, -100%);
transform-origin: 100% 0;
}
`,
indeterminate: css`
svg {
animation: rotate ${({ time }) => time}s infinite linear;
}
svg circle {
stroke-dashoffset: ${({ circleLength }) => circleLength.offsetIndeterminate};
}
@keyframes rotate {
to {
transform: rotate(360deg);
}
}
`
}
})}
${variant({
prop: 'size',
variants: {
major: css`
&,
svg {
height: 96px;
width: 96px;
}
svg circle {
cx: 48;
cy: 48;
r: 43;
stroke-width: 9.6;
}
`,
icon: css`
&,
svg {
height: 20px;
width: 20px;
margin: 2px;
}
svg circle {
cx: 10;
cy: 10;
r: 8;
stroke-width: 2;
}
`
}
})}
`

Loader.propTypes = {
percentage: PropTypes.number,
showPercentage: PropTypes.bool,
size: PropTypes.oneOf(['icon', 'major']),
time: PropTypes.number,
variant: PropTypes.oneOf(['determinate', 'indeterminate'])
}

Loader.defaultProps = {
showPercentage: false,
size: 'major',
time: 5,
variant: 'indeterminate'
}

export default Loader
5 changes: 5 additions & 0 deletions src/components/Loader/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Loader from './Loader'

export { Loader }

export default Loader
1 change: 1 addition & 0 deletions src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from './Button'
export * from './Iconography'
export * from './Breadcrumb'
export * from './Checkbox'
export * from './Loader'
76 changes: 76 additions & 0 deletions src/stories/Loader.stories.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { Meta, Story, Preview, Props } from '@storybook/addon-docs/blocks'

import { Loader } from '../components'
import { ThemeProvider } from '../theme'

<Meta title='Data Display|Loader' component={Loader} />

# Loader

O componente `Loader` é utilizado para apresentar carregamentos de forma visual ao usuário. Estando disponível com os tamanhos `major` (padrão) e `icon`. Juntamente com as variants com tempo definido (`determinate`) e sem tempo definido (`indeterminate` - padrão).

<Preview>
<Story
name='Base'
parameters={{
design: {
type: 'figma',
url: 'https://www.figma.com/file/O3bKxIcsj2rc1FNIRclJyT/Saturn-System?node-id=245%3A0'
}
}}
>
<ThemeProvider>
<Loader />
</ThemeProvider>
</Story>
</Preview>

# Size

O `Loader` possuí a prop `size` que pode receber dois valores possíveis, `icon` e `major`, que indicam o tamanho do `Loader`, por padrão é `major`.

<Preview>
<Story
name='Size'
parameters={{
design: {
type: 'figma',
url: 'https://www.figma.com/file/O3bKxIcsj2rc1FNIRclJyT/Saturn-System?node-id=245%3A0'
}
}}
>
<ThemeProvider>
<Loader size='major' />
<Loader size='icon' />
</ThemeProvider>
</Story>
</Preview>

# Variants

O `Loader` recebe a prop `variant` que indica uma entre as duas variações possíveis, `determinate` e `indeterminate` - padrão.

Quando for a variação `determinate`, é necessário também passar uma prop chamada `percentage`, é um valor que indica a porcentagem de carregamento já realizado e junto com esta prop opcionalmente também é possível passar uma prop chamada `showPercentage` que é um booleano que define se esta porcentagem vai ser mostrada em texto, mas este texto só será exibido quando o `size` do `Loader` também for `major`.

Quando for a variação `indeterminate`, o tempo de ciclo do loader por padrão é 5 segundos, mas este valor pode ser passado passando um número pela prop `time` indicando o tempo desejado para o ciclo do loader.

<Preview>
<Story
name='Variants'
parameters={{
design: {
type: 'figma',
url: 'https://www.figma.com/file/O3bKxIcsj2rc1FNIRclJyT/Saturn-System?node-id=245%3A0'
}
}}
>
<ThemeProvider>
<Loader percentage={30} showPercentage={true} variant='determinate' />
<Loader percentage={30} variant='determinate' />
<Loader variant='indeterminate' />
<Loader variant='indeterminate' time={8} />
</ThemeProvider>
</Story>
</Preview>

<Props of={Loader} />

0 comments on commit cd131e2

Please sign in to comment.