diff --git a/packages/bolt/app/components/ui/LoadingDots.tsx b/packages/bolt/app/components/ui/LoadingDots.tsx new file mode 100644 index 0000000..47d28b7 --- /dev/null +++ b/packages/bolt/app/components/ui/LoadingDots.tsx @@ -0,0 +1,27 @@ +import { memo, useEffect, useState } from 'react'; + +interface LoadingDotsProps { + text: string; +} + +export const LoadingDots = memo(({ text }: LoadingDotsProps) => { + const [dotCount, setDotCount] = useState(0); + + useEffect(() => { + const interval = setInterval(() => { + setDotCount((prevDotCount) => (prevDotCount + 1) % 4); + }, 500); + + return () => clearInterval(interval); + }, []); + + return ( +
+
+ {text} + {'.'.repeat(dotCount)} + ... +
+
+ ); +}); diff --git a/packages/bolt/app/routes/login.tsx b/packages/bolt/app/routes/login.tsx index b609027..2e27a0c 100644 --- a/packages/bolt/app/routes/login.tsx +++ b/packages/bolt/app/routes/login.tsx @@ -8,6 +8,7 @@ import { import { useFetcher, useLoaderData } from '@remix-run/react'; import { auth, type AuthAPI } from '@webcontainer/api'; import { useEffect, useState } from 'react'; +import { LoadingDots } from '~/components/ui/LoadingDots'; import { createUserSession, isAuthenticated, validateAccessToken } from '~/lib/.server/sessions'; import { CLIENT_ID, CLIENT_ORIGIN } from '~/lib/constants'; import { request as doRequest } from '~/lib/fetch'; @@ -96,12 +97,16 @@ export default function Login() { return (
-
-
-

Login

+ {redirected ? ( + + ) : ( +
+
+

Login

+
+
- {redirected ? 'Processing auth...' : } -
+ )}
); }