Skip to content

Commit ab72282

Browse files
committed
feat(pages): add page entry animations for improved UX
Wraps main page content in `motion.div` to introduce smooth fade-in and subtle scale or vertical slide animations on page load. This enhances the user experience by providing visual feedback and a more fluid transition between different sections of the application.
1 parent f390ca5 commit ab72282

6 files changed

Lines changed: 62 additions & 16 deletions

File tree

src/features/about/AboutPage.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44

55
import { useTranslation } from 'react-i18next';
6+
import { motion } from 'motion/react';
67
import { Card } from '@/shared/components/ui/card';
78
import { Badge } from '@/shared/components/ui/badge';
89
import { Button } from '@/shared/components/ui/button';
@@ -22,7 +23,12 @@ export function AboutPage() {
2223
};
2324

2425
return (
25-
<div className="flex flex-col items-center justify-center min-h-[80vh] space-y-8">
26+
<motion.div
27+
initial={{ opacity: 0, scale: 0.95 }}
28+
animate={{ opacity: 1, scale: 1 }}
29+
transition={{ duration: 0.3 }}
30+
className="flex flex-col items-center justify-center min-h-[80vh] space-y-8"
31+
>
2632
{/* App Icon & Title */}
2733
<div className="flex flex-col items-center space-y-4">
2834
<img
@@ -129,6 +135,6 @@ export function AboutPage() {
129135
<p className="text-xs text-muted-foreground/50">
130136
{t('about.copyright')}
131137
</p>
132-
</div>
138+
</motion.div>
133139
);
134140
}

src/features/auth/LoginPage.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import { useState } from 'react';
66
import { useTranslation } from 'react-i18next';
7+
import { motion } from 'motion/react';
78
import { useAuthStore } from '@/features/auth/auth.store';
89
import { useCliProxyStore } from '@/features/settings/cliProxy.store';
910
import { Button } from '@/shared/components/ui/button';
@@ -55,7 +56,12 @@ export function LoginPage() {
5556
};
5657

5758
return (
58-
<div className="flex min-h-screen items-center justify-center bg-background p-4">
59+
<motion.div
60+
initial={{ opacity: 0, scale: 0.95 }}
61+
animate={{ opacity: 1, scale: 1 }}
62+
transition={{ duration: 0.3 }}
63+
className="flex min-h-screen items-center justify-center bg-background p-4"
64+
>
5965
<Card className="w-full max-w-md">
6066
<CardHeader className="space-y-1 text-center">
6167
<div className="mb-4 flex justify-center">
@@ -204,6 +210,6 @@ export function LoginPage() {
204210
</form>
205211
</CardContent>
206212
</Card>
207-
</div>
213+
</motion.div>
208214
);
209215
}

src/features/dashboard/DashboardPage.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { useTranslation } from 'react-i18next';
2+
import { motion } from 'motion/react';
23
import { Card, CardContent, CardHeader, CardTitle } from '@/shared/components/ui/card';
34
import { Button } from '@/shared/components/ui/button';
45
import {
@@ -59,7 +60,12 @@ export function DashboardPage() {
5960
} = useDashboardPresenter();
6061

6162
return (
62-
<div className="space-y-6 animate-fade-in p-2">
63+
<motion.div
64+
initial={{ opacity: 0, y: 20 }}
65+
animate={{ opacity: 1, y: 0 }}
66+
transition={{ duration: 0.4 }}
67+
className="space-y-6 p-2"
68+
>
6369
{/* Header Section */}
6470
<div className="flex items-center justify-between mb-6">
6571
<div className="flex flex-col gap-1">
@@ -697,6 +703,6 @@ export function DashboardPage() {
697703
</>
698704
)}
699705
</div>
700-
</div>
706+
</motion.div>
701707
);
702708
}

src/features/providers/ProvidersPage.tsx

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { useTranslation } from 'react-i18next';
2+
import { motion } from 'motion/react';
23
import { PROVIDERS } from '@/constants';
34
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/shared/components/ui/card';
45
import { Button } from '@/shared/components/ui/button';
@@ -94,7 +95,12 @@ export function ProvidersPage() {
9495

9596
if (!isAuthenticated) {
9697
return (
97-
<div className="space-y-6">
98+
<motion.div
99+
initial={{ opacity: 0, y: 20 }}
100+
animate={{ opacity: 1, y: 0 }}
101+
transition={{ duration: 0.4 }}
102+
className="space-y-6"
103+
>
98104
<div>
99105
<h1 className="text-3xl font-bold">{t('providers.title', 'Providers')}</h1>
100106
</div>
@@ -104,12 +110,17 @@ export function ProvidersPage() {
104110
<p className="text-muted-foreground">{t('providers.connectPrompt')}</p>
105111
</CardContent>
106112
</Card>
107-
</div>
113+
</motion.div>
108114
);
109115
}
110116

111117
return (
112-
<div className="space-y-8">
118+
<motion.div
119+
initial={{ opacity: 0, y: 20 }}
120+
animate={{ opacity: 1, y: 0 }}
121+
transition={{ duration: 0.4 }}
122+
className="space-y-8"
123+
>
113124
<AlertDialog open={!!fileToDelete} onOpenChange={(open) => !open && setFileToDelete(null)}>
114125
<AlertDialogContent className="border-border/50">
115126
<AlertDialogHeader>
@@ -590,6 +601,6 @@ export function ProvidersPage() {
590601
</DialogFooter>
591602
</DialogContent>
592603
</Dialog>
593-
</div>
604+
</motion.div>
594605
);
595606
}

src/features/quota/QuotaPage.tsx

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { useTranslation } from 'react-i18next';
2+
import { motion } from 'motion/react';
23
import { Card, CardContent } from '@/shared/components/ui/card';
34
import { Button } from '@/shared/components/ui/button';
45
import { RefreshCw, AlertCircle, Loader2, LayoutGrid, List, Eye, EyeOff } from 'lucide-react';
@@ -28,7 +29,12 @@ export function QuotaPage() {
2829

2930
if (!isAuthenticated) {
3031
return (
31-
<div className="space-y-6">
32+
<motion.div
33+
initial={{ opacity: 0, y: 20 }}
34+
animate={{ opacity: 1, y: 0 }}
35+
transition={{ duration: 0.4 }}
36+
className="space-y-6"
37+
>
3238
<div>
3339
<h1 className="text-3xl font-bold">{t('quota.title')}</h1>
3440
</div>
@@ -38,12 +44,17 @@ export function QuotaPage() {
3844
<p className="text-muted-foreground">{t('quota.connectPrompt')}</p>
3945
</CardContent>
4046
</Card>
41-
</div>
47+
</motion.div>
4248
);
4349
}
4450

4551
return (
46-
<div className="space-y-6">
52+
<motion.div
53+
initial={{ opacity: 0, y: 20 }}
54+
animate={{ opacity: 1, y: 0 }}
55+
transition={{ duration: 0.4 }}
56+
className="space-y-6"
57+
>
4758
{/* Header & Refresh */}
4859
<div className="flex items-center justify-between">
4960
<div>
@@ -165,6 +176,6 @@ export function QuotaPage() {
165176
})}
166177
</div>
167178
)}
168-
</div>
179+
</motion.div>
169180
);
170181
}

src/features/settings/SettingsPage.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import { useEffect } from 'react';
66
import { useTranslation } from 'react-i18next';
7+
import { motion } from 'motion/react';
78
import { useThemeStore } from '@/features/settings/theme.store';
89
import { useLanguageStore } from '@/features/settings/language.store';
910
import { useAuthStore } from '@/features/auth/auth.store';
@@ -80,7 +81,12 @@ export function SettingsPage() {
8081
] as const;
8182

8283
return (
83-
<div className="space-y-6">
84+
<motion.div
85+
initial={{ opacity: 0, y: 20 }}
86+
animate={{ opacity: 1, y: 0 }}
87+
transition={{ duration: 0.4 }}
88+
className="space-y-6"
89+
>
8490
<div>
8591
<h1 className="text-3xl font-bold">{t('settings.title')}</h1>
8692
</div>
@@ -399,6 +405,6 @@ export function SettingsPage() {
399405
</Button>
400406
</CardContent>
401407
</Card>
402-
</div>
408+
</motion.div>
403409
);
404410
}

0 commit comments

Comments
 (0)