-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* 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
Showing
4 changed files
with
220 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import Loader from './Loader' | ||
|
||
export { Loader } | ||
|
||
export default Loader |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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} /> |