Improve design of loading indicator

This commit is contained in:
MartinBraquet
2025-10-16 12:42:38 +02:00
parent a43480db92
commit 1fdcd24f28
2 changed files with 61 additions and 17 deletions

View File

@@ -1,34 +1,68 @@
import clsx from 'clsx'
import {useEffect, useRef} from 'react'
import FavIcon from "web/public/FavIcon";
export type SpinnerSize = 'sm' | 'md' | 'lg'
function getSizeClass(size: SpinnerSize) {
switch (size) {
case 'sm':
return 'h-4 w-4 border-2'
case 'md':
return 'h-6 w-6 border-4'
case 'lg':
default:
return 'h-8 w-8 border-4'
}
}
// function getSizeClass(size: SpinnerSize) {
// switch (size) {
// case 'sm':
// return 'h-4 w-4 border-2'
// case 'md':
// return 'h-6 w-6 border-4'
// case 'lg':
// default:
// return 'h-8 w-8 border-4'
// }
// }
export function LoadingIndicator(props: {
className?: string
spinnerClassName?: string
size?: SpinnerSize
size?: 'sm' | 'md' | 'lg'
}) {
const { className, spinnerClassName, size = 'lg' } = props
const {className, spinnerClassName} = props
const compassRef = useRef<HTMLDivElement>(null)
useEffect(() => {
const el = compassRef.current
if (!el) return
let angle = 0
let timeoutId: number
const randomTurn = () => {
// Randomly choose direction and angle
const direction = Math.random() > 0.5 ? 1 : -1
const delta = Math.random() * 75 + 5
angle = direction * delta
el.style.transform = `rotate(${angle}deg)`
// Random delay before next movement
const delay = Math.random() * 400 + 400
timeoutId = window.setTimeout(randomTurn, delay)
}
randomTurn()
return () => clearTimeout(timeoutId)
}, [])
return (
<div className={clsx('flex items-center justify-center', className)}>
<div className={clsx('flex items-center justify-center mt-8', className)}>
<div
ref={compassRef}
className={clsx(
'border-primary-500 inline-block animate-spin rounded-full border-solid border-r-transparent',
getSizeClass(size),
'inline-block transition-transform duration-700 ease-in-out',
// getSizeClass(size),
spinnerClassName
)}
role="status"
/>
>
<FavIcon className="dark:invert w-20 h-20"/>
</div>
</div>
)
}

10
web/pages/loading.tsx Normal file
View File

@@ -0,0 +1,10 @@
"use client";
import {LoadingIndicator} from "web/components/widgets/loading-indicator";
import {LovePage} from "web/components/love-page";
export default function Loading() {
return <LovePage trackPageView={'loading'}>
<LoadingIndicator/>
</LovePage>;
}