Add loading skeleton component and enhance loading animations in App
This commit is contained in:
52
src/App.css
52
src/App.css
@@ -529,8 +529,60 @@
|
||||
@keyframes loading-shimmer {
|
||||
0% {
|
||||
background-position: -200% 0;
|
||||
opacity: 0.8;
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
background-position: 200% 0;
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loading-wave {
|
||||
0% {
|
||||
left: -100%;
|
||||
}
|
||||
100% {
|
||||
left: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loading-pulse {
|
||||
0%, 100% {
|
||||
opacity: 0.6;
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.loading-skeleton {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.loading-skeleton::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.08), transparent);
|
||||
animation: loading-wave 2s infinite ease-in-out;
|
||||
}
|
||||
|
||||
/* Enhanced loading skeleton styles */
|
||||
.loading-skeleton {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.loading-skeleton:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
66
src/App.tsx
66
src/App.tsx
@@ -24,6 +24,36 @@ interface Stats {
|
||||
totalKills: number
|
||||
}
|
||||
|
||||
// Loading Skeleton Component
|
||||
const LoadingSkeleton = ({ width = '60px', height = '40px', className = '' }: { width?: string, height?: string, className?: string }) => (
|
||||
<div
|
||||
className={`loading-skeleton ${className}`}
|
||||
style={{
|
||||
width,
|
||||
height,
|
||||
background: 'linear-gradient(135deg, var(--bg-secondary) 0%, var(--border-color) 50%, var(--bg-secondary) 100%)',
|
||||
backgroundSize: '200% 200%',
|
||||
animation: 'loading-shimmer 2.5s infinite ease-in-out, loading-pulse 1.5s infinite ease-in-out',
|
||||
borderRadius: '8px',
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
boxShadow: '0 2px 8px rgba(0,0,0,0.08)'
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: '-100%',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
background: 'linear-gradient(90deg, transparent, rgba(255,255,255,0.12), transparent)',
|
||||
animation: 'loading-wave 2.5s infinite ease-in-out'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
function App() {
|
||||
const { t } = useTranslation()
|
||||
|
||||
@@ -195,14 +225,7 @@ function App() {
|
||||
<div className="stat-icon">👥</div>
|
||||
<div className="stat-number">
|
||||
{loading ? (
|
||||
<div style={{
|
||||
width: '60px',
|
||||
height: '40px',
|
||||
background: 'linear-gradient(90deg, var(--bg-secondary) 25%, var(--border-color) 50%, var(--bg-secondary) 75%)',
|
||||
backgroundSize: '200% 100%',
|
||||
animation: 'loading-shimmer 1.5s infinite',
|
||||
borderRadius: '4px'
|
||||
}} />
|
||||
<LoadingSkeleton width="70px" height="32px" />
|
||||
) : (
|
||||
stats.totalPlayers.toLocaleString()
|
||||
)}
|
||||
@@ -213,14 +236,7 @@ function App() {
|
||||
<div className="stat-icon">🔗</div>
|
||||
<div className="stat-number">
|
||||
{loading ? (
|
||||
<div style={{
|
||||
width: '60px',
|
||||
height: '40px',
|
||||
background: 'linear-gradient(90deg, var(--bg-secondary) 25%, var(--border-color) 50%, var(--bg-secondary) 75%)',
|
||||
backgroundSize: '200% 100%',
|
||||
animation: 'loading-shimmer 1.5s infinite',
|
||||
borderRadius: '4px'
|
||||
}} />
|
||||
<LoadingSkeleton width="70px" height="32px" />
|
||||
) : (
|
||||
stats.totalConnects.toLocaleString()
|
||||
)}
|
||||
@@ -231,14 +247,7 @@ function App() {
|
||||
<div className="stat-icon">⏱️</div>
|
||||
<div className="stat-number">
|
||||
{loading ? (
|
||||
<div style={{
|
||||
width: '80px',
|
||||
height: '40px',
|
||||
background: 'linear-gradient(90deg, var(--bg-secondary) 25%, var(--border-color) 50%, var(--bg-secondary) 75%)',
|
||||
backgroundSize: '200% 100%',
|
||||
animation: 'loading-shimmer 1.5s infinite',
|
||||
borderRadius: '4px'
|
||||
}} />
|
||||
<LoadingSkeleton width="90px" height="32px" />
|
||||
) : (
|
||||
formatPlayTime(stats.totalPlayTime)
|
||||
)}
|
||||
@@ -249,14 +258,7 @@ function App() {
|
||||
<div className="stat-icon">🎯</div>
|
||||
<div className="stat-number">
|
||||
{loading ? (
|
||||
<div style={{
|
||||
width: '60px',
|
||||
height: '40px',
|
||||
background: 'linear-gradient(90deg, var(--bg-secondary) 25%, var(--border-color) 50%, var(--bg-secondary) 75%)',
|
||||
backgroundSize: '200% 100%',
|
||||
animation: 'loading-shimmer 1.5s infinite',
|
||||
borderRadius: '4px'
|
||||
}} />
|
||||
<LoadingSkeleton width="70px" height="32px" />
|
||||
) : (
|
||||
stats.totalKills.toLocaleString()
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user