Skip to content

Commit 6621804

Browse files
Lukas742MarcusNotheis
authored andcommitted
feat(Loader): Initial Implementation (#153)
1 parent 3ae27e8 commit 6621804

File tree

9 files changed

+208
-1
lines changed

9 files changed

+208
-1
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { JSSTheme } from '../../interfaces/JSSTheme';
2+
3+
//todo use theme colors when available
4+
export const styles = ({ parameters }: JSSTheme) => ({
5+
'@keyframes scroll': {
6+
'0%': { backgroundPosition: '-100% 0' },
7+
'100%': { backgroundPosition: '200% 0' }
8+
},
9+
loader: {
10+
height: '0.25rem',
11+
width: '100%',
12+
'&$loaderDeterminate': {
13+
background: `linear-gradient(to right, ${parameters.sapUiContentIconColor}, ${parameters.sapUiContentIconColor})`,
14+
backgroundColor: 'rgba(8, 84, 160, 0.15)',
15+
backgroundRepeat: 'repeat-y'
16+
},
17+
'&$loaderIndeterminate': {
18+
background: `linear-gradient(
19+
to right,
20+
rgba(8, 84, 160, 0) 0px,
21+
rgba(8, 84, 160, 1) calc(50% - 2rem),
22+
${parameters.sapUiContentIconColor} calc(50% - 2rem),
23+
${parameters.sapUiContentIconColor} calc(50% + 2rem),
24+
rgba(8, 84, 160, 1) calc(50% + 2rem),
25+
rgba(8, 84, 160, 0) 100%
26+
)`,
27+
backgroundColor: 'rgba(8, 84, 160, 0.15)',
28+
backgroundSize: '40%',
29+
backgroundRepeat: 'repeat-y',
30+
animation: '$scroll 1.2s linear infinite'
31+
}
32+
},
33+
loaderDeterminate: {},
34+
loaderIndeterminate: {}
35+
});
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { renderThemedComponent } from '@shared/tests/utils';
2+
import React from 'react';
3+
import { LoaderType } from '@ui5/webcomponents-react/lib/LoaderType';
4+
import { Loader } from '@ui5/webcomponents-react/lib/Loader';
5+
6+
describe('Loader', () => {
7+
test('indeterminate', () => {
8+
const wrapper = renderThemedComponent(<Loader type={LoaderType.Indeterminate} />);
9+
expect(wrapper).toMatchSnapshot();
10+
});
11+
12+
test('determinate', () => {
13+
const wrapper = renderThemedComponent(<Loader type={LoaderType.Determinate} />);
14+
expect(wrapper).toMatchSnapshot();
15+
});
16+
17+
test('determinate with progress prop', () => {
18+
const wrapper = renderThemedComponent(<Loader type={LoaderType.Determinate} progress="42%" />);
19+
expect(wrapper).toMatchSnapshot();
20+
});
21+
22+
test('default', () => {
23+
const wrapper = renderThemedComponent(<Loader />);
24+
expect(wrapper).toMatchSnapshot();
25+
});
26+
27+
test('with Custom Class Name', () => {
28+
const wrapper = renderThemedComponent(<Loader className="myTestClass" />);
29+
expect(wrapper).toMatchSnapshot();
30+
});
31+
});
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`Loader default 1`] = `
4+
<div
5+
aria-busy="true"
6+
class="Loader--loader- Loader--loaderIndeterminate-"
7+
data-component-name="Loader"
8+
role="progressbar"
9+
style="background-size:40%"
10+
title="Please wait"
11+
/>
12+
`;
13+
14+
exports[`Loader determinate 1`] = `
15+
<div
16+
aria-busy="true"
17+
class="Loader--loader- Loader--loaderDeterminate-"
18+
data-component-name="Loader"
19+
role="progressbar"
20+
style="background-size:0px"
21+
title="Please wait"
22+
/>
23+
`;
24+
25+
exports[`Loader determinate with progress prop 1`] = `
26+
<div
27+
aria-busy="true"
28+
class="Loader--loader- Loader--loaderDeterminate-"
29+
data-component-name="Loader"
30+
role="progressbar"
31+
style="background-size:42%"
32+
title="Please wait"
33+
/>
34+
`;
35+
36+
exports[`Loader indeterminate 1`] = `
37+
<div
38+
aria-busy="true"
39+
class="Loader--loader- Loader--loaderIndeterminate-"
40+
data-component-name="Loader"
41+
role="progressbar"
42+
style="background-size:40%"
43+
title="Please wait"
44+
/>
45+
`;
46+
47+
exports[`Loader with Custom Class Name 1`] = `
48+
<div
49+
aria-busy="true"
50+
class="Loader--loader- myTestClass Loader--loaderIndeterminate-"
51+
data-component-name="Loader"
52+
role="progressbar"
53+
style="background-size:40%"
54+
title="Please wait"
55+
/>
56+
`;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { select, text } from '@storybook/addon-knobs';
2+
import React from 'react';
3+
import { Loader } from '@ui5/webcomponents-react/lib/Loader';
4+
import { LoaderType } from '@ui5/webcomponents-react/lib/LoaderType';
5+
6+
export const renderLoader = () => (
7+
<Loader type={select('type', LoaderType, LoaderType.Indeterminate)} progress={text('progress', '40%')} />
8+
);
9+
renderLoader.story = {
10+
name: 'Default'
11+
};
12+
13+
export default {
14+
title: 'Components | Loader',
15+
component: Loader
16+
};
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { StyleClassHelper } from '@ui5/webcomponents-react-base/lib/StyleClassHelper';
2+
import { LoaderType } from '@ui5/webcomponents-react/lib/LoaderType';
3+
import React, { CSSProperties, FC, forwardRef, RefObject, useMemo } from 'react';
4+
import { createUseStyles } from 'react-jss';
5+
import { CommonProps } from '../../interfaces/CommonProps';
6+
import { JSSTheme } from '../../interfaces/JSSTheme';
7+
import { styles } from './Loader.jss';
8+
9+
export interface LoaderProps extends CommonProps {
10+
type?: LoaderType;
11+
progress?: CSSProperties['width'];
12+
}
13+
14+
const useStyles = createUseStyles<JSSTheme, keyof ReturnType<typeof styles>>(styles, { name: 'Loader' });
15+
16+
const Loader: FC<LoaderProps> = forwardRef((props: LoaderProps, ref: RefObject<HTMLDivElement>) => {
17+
const { className, type, progress, tooltip, slot, style } = props;
18+
const classes = useStyles(props);
19+
20+
const loaderClasses = StyleClassHelper.of(classes.loader);
21+
if (className) {
22+
loaderClasses.put(className);
23+
}
24+
loaderClasses.put(classes[`loader${type}`]);
25+
26+
const inlineStyles = useMemo(() => {
27+
const backgroundSize = type !== LoaderType.Determinate ? '40%' : progress;
28+
return {
29+
...style,
30+
backgroundSize
31+
};
32+
}, [progress, style, type]);
33+
34+
return (
35+
<div
36+
ref={ref}
37+
className={loaderClasses.valueOf()}
38+
data-component-name="Loader"
39+
aria-busy="true"
40+
role="progressbar"
41+
title={tooltip || 'Please wait'}
42+
slot={slot}
43+
style={inlineStyles}
44+
/>
45+
);
46+
});
47+
48+
Loader.defaultProps = {
49+
type: LoaderType.Indeterminate,
50+
progress: '0px'
51+
};
52+
53+
Loader.displayName = 'Loader';
54+
55+
export { Loader };

packages/main/src/enums/LoaderType.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export enum LoaderType {
2+
Determinate = 'Determinate',
3+
Indeterminate = 'Indeterminate'
4+
}

packages/main/src/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ import { Tokenizer } from './lib/Tokenizer';
107107
import { ValueState } from './lib/ValueState';
108108
import { VariantManagement } from './lib/VariantManagement';
109109
import { VerticalAlign } from './lib/VerticalAlign';
110+
import { Loader } from './lib/Loader';
111+
import { LoaderType } from './lib/LoaderType';
110112

111113
export {
112114
ActionSheet,
@@ -213,5 +215,7 @@ export {
213215
Tokenizer,
214216
ValueState,
215217
VariantManagement,
216-
VerticalAlign
218+
VerticalAlign,
219+
Loader,
220+
LoaderType
217221
};

packages/main/src/lib/Loader.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { Loader } from '../components/Loader';
2+
3+
export { Loader };

packages/main/src/lib/LoaderType.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { LoaderType } from '../enums/LoaderType';
2+
3+
export { LoaderType };

0 commit comments

Comments
 (0)