Franknoirot/loading states (#246)

* Add Loading state with long load time messaging

* Make /signin page respect user theme
This commit is contained in:
Frank Noirot
2023-08-09 15:41:41 -04:00
committed by GitHub
parent 968a67e654
commit dbb94d7e95
6 changed files with 90 additions and 16 deletions

View File

@ -5,6 +5,7 @@ import { User, useStore } from './useStore'
import { useNavigate } from 'react-router-dom'
import { useEffect } from 'react'
import { isTauri } from './lib/isTauri'
import Loading from './components/Loading'
// Wrapper around protected routes, used in src/Router.tsx
export const Auth = ({ children }: React.PropsWithChildren) => {
@ -30,5 +31,5 @@ export const Auth = ({ children }: React.PropsWithChildren) => {
}
}, [user, token, navigate, isLoading])
return isLoading ? <>Loading...</> : <>{children}</>
return isLoading ? <Loading /> : <>{children}</>
}

View File

@ -22,7 +22,7 @@ export const ActionButton = ({
children,
...props
}: ActionButtonProps) => {
const classNames = `group mono text-base flex items-center gap-2 rounded-sm border border-chalkboard-40 dark:border-chalkboard-60 hover:border-liquid-40 dark:hover:bg-chalkboard-90 p-[3px] ${
const classNames = `group mono text-base flex items-center gap-2 rounded-sm border border-chalkboard-40 dark:border-chalkboard-60 hover:border-liquid-40 dark:hover:bg-chalkboard-90 p-[3px] text-chalkboard-110 dark:text-chalkboard-10 hover:text-chalkboard-110 hover:dark:text-chalkboard-10 ${
icon ? 'pr-2' : 'px-2'
} ${className}`

View File

@ -0,0 +1,41 @@
import { useEffect, useState } from 'react'
const Loading = () => {
const [hasLongLoadTime, setHasLongLoadTime] = useState(false)
useEffect(() => {
const timer = setTimeout(() => {
setHasLongLoadTime(true)
}, 4000)
return () => clearTimeout(timer)
}, [setHasLongLoadTime])
return (
<div className="body-bg flex flex-col items-center justify-center h-screen">
<svg viewBox="0 0 10 10" className="w-8 h-8">
<circle cx="5" cy="5" r="4" stroke="var(--liquid-20)" fill="none" />
<circle
cx="5"
cy="5"
r="4"
stroke="var(--liquid-10)"
fill="none"
strokeDasharray="4, 4"
className="animate-spin origin-center"
/>
</svg>
<p className="mt-4 text-liquid-80 dark:text-liquid-20">
Loading KittyCAD Modeling App...
</p>
<p
className={
'mt-4 text-liquid-90 dark:text-liquid-10 transition-opacity duration-500' +
(hasLongLoadTime ? ' opacity-100' : ' opacity-0')
}
>
Loading is taking longer than expected.
</p>
</div>
)
}
export default Loading

View File

@ -55,6 +55,14 @@ button:disabled {
@apply bg-chalkboard-90 text-chalkboard-40 border-chalkboard-70;
}
a {
@apply text-liquid-80 hover:text-liquid-70;
}
.dark a {
@apply text-liquid-20 hover:text-liquid-10;
}
.mono {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;

View File

@ -1,16 +1,19 @@
import { faSignInAlt } from '@fortawesome/free-solid-svg-icons'
import { ActionButton } from '../components/ActionButton'
import { isTauri } from '../lib/isTauri'
import { useStore } from '../useStore'
import { Themes, useStore } from '../useStore'
import { invoke } from '@tauri-apps/api/tauri'
import { useNavigate } from 'react-router-dom'
import { VITE_KC_SITE_BASE_URL, VITE_KC_API_BASE_URL } from '../env'
import { getSystemTheme } from '../lib/getSystemTheme'
const SignIn = () => {
const navigate = useNavigate()
const { setToken } = useStore((s) => ({
const { setToken, theme } = useStore((s) => ({
setToken: s.setToken,
theme: s.theme,
}))
const appliedTheme = theme === Themes.System ? getSystemTheme() : theme
const signInTauri = async () => {
// We want to invoke our command to login via device auth.
try {
@ -25,11 +28,13 @@ const SignIn = () => {
}
return (
<main className="h-full min-h-screen bg-chalkboard-20 dark:text-chalkboard-100 m-0 p-0 pt-24">
<main className="body-bg h-full min-h-screen m-0 p-0 pt-24">
<div className="max-w-2xl mx-auto">
<div>
<img
src="/kittycad-logomark.svg"
src={`/kittycad-logomark${
appliedTheme === Themes.Dark ? '-light' : ''
}.svg`}
alt="KittyCAD"
className="w-48 inline-block"
/>
@ -37,7 +42,7 @@ const SignIn = () => {
Modeling App
</span>
</div>
<h1 className="font-bold text-2xl mt-12 mb-6 text-chalkboard-110">
<h1 className="font-bold text-2xl mt-12 mb-6">
Sign in to get started with the KittyCAD Modeling App
</h1>
<p className="py-4">
@ -51,14 +56,7 @@ const SignIn = () => {
<p className="py-4">
KCMA is currently in development. If you would like to be notified
when KCMA is ready for production, please sign up for our mailing list
at{' '}
<a
href="https://kittycad.io"
className="font-bold text-liquid-80 hover:text-liquid-70"
>
kittycad.io
</a>
.
at <a href="https://kittycad.io">kittycad.io</a>.
</p>
{isTauri() ? (
<ActionButton
@ -76,7 +74,7 @@ const SignIn = () => {
window.location.href.replace('signin', '')
)}`}
icon={{ icon: faSignInAlt }}
className="w-fit mt-4 dark:hover:bg-chalkboard-30"
className="w-fit mt-4"
>
Sign in
</ActionButton>