Add progress bar to top of page for nicer loading indicator styles
This commit is contained in:
parent
708c15eba8
commit
d3a06e1ca8
12 changed files with 133 additions and 34 deletions
|
@ -1,19 +0,0 @@
|
|||
import React from 'react';
|
||||
import Spinner from '@/components/elements/Spinner';
|
||||
import { CSSTransition } from 'react-transition-group';
|
||||
|
||||
interface Props {
|
||||
visible: boolean;
|
||||
children?: React.ReactChild;
|
||||
}
|
||||
|
||||
const ListRefreshIndicator = ({ visible, children }: Props) => (
|
||||
<CSSTransition timeout={250} in={visible} appear={true} unmountOnExit={true} classNames={'fade'}>
|
||||
<div className={'flex items-center mb-2'}>
|
||||
<Spinner size={'tiny'}/>
|
||||
<p className={'ml-2 text-sm text-neutral-400'}>{children || 'Refreshing listing...'}</p>
|
||||
</div>
|
||||
</CSSTransition>
|
||||
);
|
||||
|
||||
export default ListRefreshIndicator;
|
73
resources/scripts/components/elements/ProgressBar.tsx
Normal file
73
resources/scripts/components/elements/ProgressBar.tsx
Normal file
|
@ -0,0 +1,73 @@
|
|||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { useStoreActions, useStoreState } from 'easy-peasy';
|
||||
import { randomInt } from '@/helpers';
|
||||
import { CSSTransition } from 'react-transition-group';
|
||||
|
||||
const BarFill = styled.div`
|
||||
${tw`h-full bg-cyan-400`};
|
||||
transition: 250ms ease-in-out;
|
||||
box-shadow: 0 -2px 10px 2px hsl(178, 78%, 57%);
|
||||
`;
|
||||
|
||||
export default () => {
|
||||
const interval = useRef<number>(null);
|
||||
const timeout = useRef<number>(null);
|
||||
const [ visible, setVisible ] = useState(false);
|
||||
const progress = useStoreState(state => state.progress.progress);
|
||||
const continuous = useStoreState(state => state.progress.continuous);
|
||||
const setProgress = useStoreActions(actions => actions.progress.setProgress);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
timeout.current && clearTimeout(timeout.current);
|
||||
interval.current && clearInterval(interval.current);
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setVisible((progress || 0) > 0);
|
||||
|
||||
if (progress === 100) {
|
||||
// @ts-ignore
|
||||
timeout.current = setTimeout(() => setProgress(undefined), 500);
|
||||
}
|
||||
}, [ progress ]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!continuous) {
|
||||
interval.current && clearInterval(interval.current);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!progress || progress === 0) {
|
||||
setProgress(randomInt(20, 30));
|
||||
}
|
||||
}, [ continuous ]);
|
||||
|
||||
useEffect(() => {
|
||||
if (continuous) {
|
||||
interval.current && clearInterval(interval.current);
|
||||
if ((progress || 0) >= 90) {
|
||||
setProgress(90);
|
||||
} else {
|
||||
// @ts-ignore
|
||||
interval.current = setTimeout(() => setProgress(progress + randomInt(1, 5)), 500);
|
||||
}
|
||||
}
|
||||
}, [ progress, continuous ]);
|
||||
|
||||
return (
|
||||
<div className={'w-full fixed'} style={{ height: '2px' }}>
|
||||
<CSSTransition
|
||||
timeout={250}
|
||||
appear={true}
|
||||
in={visible}
|
||||
unmountOnExit={true}
|
||||
classNames={'fade'}
|
||||
>
|
||||
<BarFill style={{ width: progress === undefined ? '100%' : `${progress}%` }}/>
|
||||
</CSSTransition>
|
||||
</div>
|
||||
);
|
||||
};
|
Reference in a new issue