Show proper spinners

This commit is contained in:
Dane Everitt 2019-12-22 14:53:27 -08:00
parent 5a31771b4b
commit 446d5be62b
No known key found for this signature in database
GPG key ID: EEA66103B3D71F53
6 changed files with 31 additions and 73 deletions

View file

@ -7,6 +7,7 @@ import { Actions, useStoreActions } from 'easy-peasy';
import { StaticContext } from 'react-router'; import { StaticContext } from 'react-router';
import FlashMessageRender from '@/components/FlashMessageRender'; import FlashMessageRender from '@/components/FlashMessageRender';
import { ApplicationStore } from '@/state'; import { ApplicationStore } from '@/state';
import Spinner from '@/components/elements/Spinner';
export default ({ history, location: { state } }: RouteComponentProps<{}, StaticContext, { token?: string }>) => { export default ({ history, location: { state } }: RouteComponentProps<{}, StaticContext, { token?: string }>) => {
const [ code, setCode ] = useState(''); const [ code, setCode ] = useState('');
@ -71,7 +72,7 @@ export default ({ history, location: { state } }: RouteComponentProps<{}, Static
disabled={isLoading || code.length !== 6} disabled={isLoading || code.length !== 6}
> >
{isLoading ? {isLoading ?
<span className={'spinner white'}>&nbsp;</span> <Spinner size={'tiny'} className={'mx-auto'}/>
: :
'Continue' 'Continue'
} }

View file

@ -11,6 +11,7 @@ import Field from '@/components/elements/Field';
import { httpErrorToHuman } from '@/api/http'; import { httpErrorToHuman } from '@/api/http';
import { FlashMessage } from '@/state/flashes'; import { FlashMessage } from '@/state/flashes';
import ReCAPTCHA from 'react-google-recaptcha'; import ReCAPTCHA from 'react-google-recaptcha';
import Spinner from '@/components/elements/Spinner';
type OwnProps = RouteComponentProps & { type OwnProps = RouteComponentProps & {
clearFlashes: ActionCreator<void>; clearFlashes: ActionCreator<void>;
@ -63,7 +64,7 @@ const LoginContainer = ({ isSubmitting, setFieldValue, values, submitForm, handl
className={'btn btn-primary btn-jumbo'} className={'btn btn-primary btn-jumbo'}
> >
{isSubmitting ? {isSubmitting ?
<span className={'spinner white'}>&nbsp;</span> <Spinner size={'tiny'} className={'mx-auto'}/>
: :
'Login' 'Login'
} }

View file

@ -8,6 +8,7 @@ import LoginFormContainer from '@/components/auth/LoginFormContainer';
import FlashMessageRender from '@/components/FlashMessageRender'; import FlashMessageRender from '@/components/FlashMessageRender';
import { Actions, useStoreActions } from 'easy-peasy'; import { Actions, useStoreActions } from 'easy-peasy';
import { ApplicationStore } from '@/state'; import { ApplicationStore } from '@/state';
import Spinner from '@/components/elements/Spinner';
type Props = Readonly<RouteComponentProps<{ token: string }> & {}>; type Props = Readonly<RouteComponentProps<{ token: string }> & {}>;
@ -89,7 +90,7 @@ export default (props: Props) => {
disabled={isLoading || !canSubmit()} disabled={isLoading || !canSubmit()}
> >
{isLoading ? {isLoading ?
<span className={'spinner white'}>&nbsp;</span> <Spinner size={'tiny'} className={'mx-auto'}/>
: :
'Reset Password' 'Reset Password'
} }

View file

@ -3,17 +3,27 @@ import classNames from 'classnames';
export type SpinnerSize = 'large' | 'normal' | 'tiny'; export type SpinnerSize = 'large' | 'normal' | 'tiny';
export default ({ size, centered }: { size?: SpinnerSize; centered?: boolean }) => ( interface Props {
size?: SpinnerSize;
centered?: boolean;
className?: string;
}
export default ({ size, centered, className }: Props) => (
centered ? centered ?
<div className={classNames('flex justify-center', { 'm-20': size === 'large', 'm-6': size !== 'large' })}> <div className={classNames(`flex justify-center ${className}`, { 'm-20': size === 'large', 'm-6': size !== 'large' })}>
<div className={classNames('spinner-circle spinner-white', { <div
'spinner-lg': size === 'large', className={classNames('spinner-circle spinner-white', {
'spinner-sm': size === 'tiny', 'spinner-lg': size === 'large',
})}/> 'spinner-sm': size === 'tiny',
})}
/>
</div> </div>
: :
<div className={classNames('spinner-circle spinner-white', { <div
'spinner-lg': size === 'large', className={classNames(`spinner-circle spinner-white ${className}`, {
'spinner-sm': size === 'tiny', 'spinner-lg': size === 'large',
})}/> 'spinner-sm': size === 'tiny',
})}
/>
); );

View file

@ -1,5 +1,9 @@
textarea, select, input, button { textarea, select, input, button {
outline: none; @apply .outline-none;
}
button:focus, button:focus-visible {
@apply .outline-none;
} }
input[type=number]::-webkit-outer-spin-button, input[type=number]::-webkit-outer-spin-button,

View file

@ -1,62 +1,3 @@
.spinner {
@apply .h-4 .relative .bg-transparent;
pointer-events: none;
&.spinner-xl {
@apply .h-16;
}
&:after {
@apply .border-2 .border-neutral-400 .absolute .block .h-4 .w-4 .rounded-full;
animation: spinners--spin 500ms infinite linear;
border-top-color: transparent !important;
border-right-color: transparent !important;
content: '';
left: calc(50% - (1em / 2));
}
&.spinner-relative:after {
@apply .relative;
}
&.spinner-xl:after {
@apply .h-16 .w-16;
left: calc(50% - (4rem / 2));
}
/**
* Speeds
*/
&.spin-slow:after {
animation: spinners--spin 1200ms infinite linear;
}
/**
* Spinner Colors
*/
&.blue:after, &.text-blue:after {
@apply .border-primary-500;
}
&.white:after, &.text-white:after {
@apply .border-white;
}
&.spinner-thick:after {
@apply .border-4;
}
}
@keyframes spinners--spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.spinner-circle { .spinner-circle {
@apply .w-8 .h-8; @apply .w-8 .h-8;
border: 3px solid hsla(211, 12%, 43%, 0.2); border: 3px solid hsla(211, 12%, 43%, 0.2);