Skip to content

Commit

Permalink
feat(Loader/Spinner): Add delay prop (#197)
Browse files Browse the repository at this point in the history
Only show the component after the `delay` is over

Closes #67
  • Loading branch information
MarcusNotheis authored Oct 21, 2019
1 parent 0ad70bc commit de2310d
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 12 deletions.
5 changes: 5 additions & 0 deletions packages/main/src/components/Loader/Loader.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,9 @@ describe('Loader', () => {
const wrapper = renderThemedComponent(<Loader className="myTestClass" />);
expect(wrapper).toMatchSnapshot();
});

test('with delay', () => {
const wrapper = renderThemedComponent(<Loader delay={1000} />);
expect(wrapper).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,5 @@ exports[`Loader with Custom Class Name 1`] = `
title="Please wait"
/>
`;

exports[`Loader with delay 1`] = `null`;
10 changes: 7 additions & 3 deletions packages/main/src/components/Loader/demo.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { select, text } from '@storybook/addon-knobs';
import React from 'react';
import { number, select, text } from '@storybook/addon-knobs';
import { Loader } from '@ui5/webcomponents-react/lib/Loader';
import { LoaderType } from '@ui5/webcomponents-react/lib/LoaderType';
import React from 'react';

export const renderLoader = () => (
<Loader type={select('type', LoaderType, LoaderType.Indeterminate)} progress={text('progress', '40%')} />
<Loader
type={select('type', LoaderType, LoaderType.Indeterminate)}
progress={text('progress', '40%')}
delay={number('delay', 0)}
/>
);
renderLoader.story = {
name: 'Default'
Expand Down
24 changes: 21 additions & 3 deletions packages/main/src/components/Loader/index.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
import { StyleClassHelper } from '@ui5/webcomponents-react-base/lib/StyleClassHelper';
import { LoaderType } from '@ui5/webcomponents-react/lib/LoaderType';
import React, { CSSProperties, FC, forwardRef, RefObject, useMemo } from 'react';
import React, { CSSProperties, FC, forwardRef, RefObject, useEffect, useMemo, useState } from 'react';
import { createUseStyles } from 'react-jss';
import { CommonProps } from '../../interfaces/CommonProps';
import { JSSTheme } from '../../interfaces/JSSTheme';
import { styles } from './Loader.jss';

export interface LoaderProps extends CommonProps {
/*
* Delay in ms until the Loader will be displayed
*/
delay?: number;
type?: LoaderType;
progress?: CSSProperties['width'];
}

const useStyles = createUseStyles<JSSTheme, keyof ReturnType<typeof styles>>(styles, { name: 'Loader' });

const Loader: FC<LoaderProps> = forwardRef((props: LoaderProps, ref: RefObject<HTMLDivElement>) => {
const { className, type, progress, tooltip, slot, style } = props;
const { className, type, progress, tooltip, slot, style, delay } = props;
const classes = useStyles(props);
const [isVisible, setIsVisible] = useState(delay === 0);

const loaderClasses = StyleClassHelper.of(classes.loader);
if (className) {
Expand All @@ -31,6 +36,18 @@ const Loader: FC<LoaderProps> = forwardRef((props: LoaderProps, ref: RefObject<H
};
}, [progress, style, type]);

useEffect(() => {
if (delay > 0) {
setTimeout(() => {
setIsVisible(true);
}, delay);
}
}, []);

if (!isVisible) {
return null;
}

return (
<div
ref={ref}
Expand All @@ -47,7 +64,8 @@ const Loader: FC<LoaderProps> = forwardRef((props: LoaderProps, ref: RefObject<H

Loader.defaultProps = {
type: LoaderType.Indeterminate,
progress: '0px'
progress: '0px',
delay: 0
};

Loader.displayName = 'Loader';
Expand Down
5 changes: 5 additions & 0 deletions packages/main/src/components/Spinner/Spinner.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,9 @@ describe('Spinner', () => {
const wrapper = renderThemedComponent(<Spinner size={Size.Large} className="testClassName1337" />);
expect(wrapper).toMatchSnapshot();
});

test('with delay', () => {
const wrapper = renderThemedComponent(<Spinner size={Size.Large} delay={2000} />);
expect(wrapper).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,5 @@ exports[`Spinner with custom class name 1`] = `
Loading...
</div>
`;

exports[`Spinner with delay 1`] = `null`;
19 changes: 16 additions & 3 deletions packages/main/src/components/Spinner/demo.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
import { select } from '@storybook/addon-knobs';
import React from 'react';
import { number, select } from '@storybook/addon-knobs';
import { Size } from '@ui5/webcomponents-react/lib/Size';
import { Spinner } from '@ui5/webcomponents-react/lib/Spinner';
import React, { useMemo } from 'react';

export const renderSpinner = () => <Spinner size={select('size', Size, Size.Medium)} />;
let spinnerKey = 0;

const Demo = (props) => {
const { delay } = props;

const spinner = useMemo(() => {
spinnerKey++;
return <Spinner key={`${spinnerKey}`} size={select('size', Size, Size.Medium)} delay={delay} />;
}, [delay]);

return spinner;
};

export const renderSpinner = () => <Demo delay={number('delay', 2000)} />;
renderSpinner.story = {
name: 'Default'
};
Expand Down
24 changes: 21 additions & 3 deletions packages/main/src/components/Spinner/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import { StyleClassHelper } from '@ui5/webcomponents-react-base/lib/StyleClassHelper';
import React, { forwardRef, RefObject, FC } from 'react';
import { Size } from '@ui5/webcomponents-react/lib/Size';
import React, { FC, forwardRef, RefObject, useEffect, useState } from 'react';
import { createUseStyles } from 'react-jss';
import { CommonProps } from '../../interfaces/CommonProps';
import { Size } from '@ui5/webcomponents-react/lib/Size';
import { styles } from './Spinner.jss';

export interface SpinnerProps extends CommonProps {
/*
* Delay in ms until the Spinner will be displayed
*/
delay?: number;
size?: Size;
}

const useStyles = createUseStyles(styles, { name: 'Spinner' });

const Spinner: FC<SpinnerProps> = forwardRef((props: SpinnerProps, ref: RefObject<HTMLDivElement>) => {
const { className, size, tooltip, slot, style } = props;
const { className, size, tooltip, slot, style, delay } = props;
const classes = useStyles();
const [isVisible, setIsVisible] = useState(delay === 0);

const spinnerClasses = StyleClassHelper.of(classes.spinner);
if (className) {
Expand All @@ -22,6 +27,18 @@ const Spinner: FC<SpinnerProps> = forwardRef((props: SpinnerProps, ref: RefObjec

spinnerClasses.put(classes[`spinner${size}`]);

useEffect(() => {
if (delay > 0) {
setTimeout(() => {
setIsVisible(true);
}, delay);
}
}, []);

if (!isVisible) {
return null;
}

return (
<div
ref={ref}
Expand All @@ -42,6 +59,7 @@ const Spinner: FC<SpinnerProps> = forwardRef((props: SpinnerProps, ref: RefObjec
});

Spinner.defaultProps = {
delay: 0,
size: Size.Medium
};

Expand Down

0 comments on commit de2310d

Please sign in to comment.