Skip to content

Commit

Permalink
add ripple loader component from trendkite-ui (#329)
Browse files Browse the repository at this point in the history
* add ripple loader component from trendkite-ui

* update ripple loader to render without div nesting

* add storybook knobs in loader overview example

* refactor loader class name

Co-authored-by: Haosheng Li <haosheng.li@cision.com>
  • Loading branch information
lihnick and lihnick authored Aug 9, 2021
1 parent cf49de4 commit 8174a39
Show file tree
Hide file tree
Showing 9 changed files with 259 additions and 0 deletions.
9 changes: 9 additions & 0 deletions example/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
Typography,
Modal,
Kite,
Loader,
// IMPORT_INJECTOR
} from '@cision/rover-ui';

Expand Down Expand Up @@ -474,6 +475,14 @@ const App = () => {
<Kite.Header>Success Kite!</Kite.Header>
</Kite>
</Section>
<Section title="Loader">
<div>
<Loader size="sm" />
</div>
<div>
<Loader />
</div>
</Section>

{/** USAGE_INJECTOR */}
</div>
Expand Down
80 changes: 80 additions & 0 deletions src/components/Loader/Loader.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
@keyframes LOADERRIPPLE {
0% {
transform: scale(0, 0);
opacity: 1;
}

100% {
transform: scale(0.9, 0.9);
opacity: 0;
}
}

.Loader {
display: flex;
flex-flow: row nowrap;
align-items: center;
justify-content: center;
}

.Loader::before {
content: '';
background-color: transparent;
position: absolute;
opacity: 1;
width: 50px;
height: 50px;
border-radius: 50%;
border: 5px solid #0092c2;
animation: LOADERRIPPLE 1.8s infinite;
transform: scale(0, 0);
animation-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1);
animation-delay: 0s;
}

.Loader::after {
content: '';
background-color: transparent;
position: absolute;
opacity: 1;
width: 50px;
height: 50px;
border-radius: 50%;
border: 5px solid #0092c2;
animation: LOADERRIPPLE 1.8s infinite;
transform: scale(0, 0);
animation-timing-function: cubic-bezier(0.3, 0.61, 0.335, 1);
animation-delay: -0.9s;
}

.sm,
.sm::before,
.sm::after {
width: 10px;
height: 10px;
margin: auto;
}

.md,
.md::before,
.md::after {
width: 20px;
height: 20px;
margin: auto;
}

.lg,
.lg::before,
.lg::after {
width: 50px;
height: 50px;
margin: auto;
}

.xl,
.xl::before,
.xl::after {
width: 100px;
height: 100px;
margin: auto;
}
40 changes: 40 additions & 0 deletions src/components/Loader/Loader.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react';

import { render } from '@testing-library/react';
import '@testing-library/jest-dom';

import Loader from '.';

describe('Loader', () => {
it('renders', () => {
render(<Loader />);
});

describe('when rendered with custom style with width and height', () => {
it('should override the default loader sizes', () => {
const { getByTestId } = render(
<Loader
data-testid="loaderElem"
style={{ width: '123px', height: '123px' }}
/>
);

const loaderElem = getByTestId('loaderElem') as HTMLDivElement;
expect(loaderElem.style.width).toBe('123px');
});
});

describe('when rendered with additional class names', () => {
it('should not replace the default classes', () => {
const { getByTestId } = render(
<Loader data-testid="loaderElem" className="Loader" />
);

const loaderElem = getByTestId('loaderElem') as HTMLDivElement;
const loaderClasses = loaderElem.className
.split(' ')
.filter((classes) => classes.match('\\w*(Loader)\\w*'));
expect(loaderClasses.length).toBe(2);
});
});
});
28 changes: 28 additions & 0 deletions src/components/Loader/Loader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';

import classNames from 'classnames';

import styles from './Loader.module.css';

export type Size = 'sm' | 'md' | 'lg' | 'xl';

interface LoaderProps extends React.HTMLAttributes<HTMLDivElement> {
size?: Size;
}

const Loader: React.FC<LoaderProps> = ({ size = 'lg', ...rest }) => {
const mainClass = classNames(
styles.Loader,
rest.className,
`${styles[size]}`
);

const prop = {
...rest,
className: mainClass,
};

return <div {...prop} />;
};

export default Loader;
16 changes: 16 additions & 0 deletions src/components/Loader/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# \<Loader\>

render a loading icon

### Valid Sizes

Size is optional, defaults to large when omitted

- sm
- md
- lg
- xl

```jsx
<Loader size="md" />
```
1 change: 1 addition & 0 deletions src/components/Loader/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './Loader';
83 changes: 83 additions & 0 deletions src/components/Loader/story.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import React from 'react';
import { storiesOf } from '@storybook/react';
import { select } from '@storybook/addon-knobs';

import Loader from './Loader';
import Readme from './README.md';

import { Wrap } from '../../stories/storybook-helpers';

const FlexWrapper = (props) => (
<div
style={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignContent: 'center',
alignItems: 'center',
marginTop: '100px',
marginBottom: '100px',
}}
{...props}
/>
);

storiesOf('Planets/Loader', module)
.addParameters({
readme: {
sidebar: Readme,
},
})
.add(
'Overview',
() => (
<FlexWrapper>
<Loader size={select('size', ['sm', 'md', 'lg', 'xl'], 'lg')} />
</FlexWrapper>
),
{
info: {
inline: false,
source: true,
},
}
)
.add(
'Examples',
() => (
<>
<Wrap>
<Loader size="sm" />
</Wrap>
<Wrap>
<Loader size="md" />
</Wrap>
<Wrap>
<Loader size="lg" />
</Wrap>
<Wrap>
<Loader size="xl" />
</Wrap>
<Wrap>
<Loader style={{ marginLeft: '0' }} />
</Wrap>
<Wrap>
<Loader style={{ marginRight: '0' }} />
</Wrap>
<Wrap>
<div style={{ width: '50%' }}>
<Loader size="lg" />
</div>
</Wrap>
<Wrap>
<Loader style={{ marginTop: '75px', marginBottom: '75px' }} />
</Wrap>
</>
),
{
info: {
inline: false,
source: true,
},
}
);
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ export { default as InputTime } from './components/InputTime';
export { default as Typography } from './components/Typography';
export { default as Modal } from './components/Modal';
export { default as Kite } from './components/Kite';
export { default as Loader } from './components/Loader';
1 change: 1 addition & 0 deletions src/stories/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import '../components/Input/story';
import '../components/Input/Checkbox/story';
import '../components/InputTime/story';
import '../components/Typography/story';
import '../components/Loader/story';

/*
* STAR SYSTEMS
Expand Down

0 comments on commit 8174a39

Please sign in to comment.