Skip to content

Commit 785cb0b

Browse files
committed
feat: add fade animation to streak card flip
1 parent 5ec0abf commit 785cb0b

File tree

2 files changed

+58
-22
lines changed

2 files changed

+58
-22
lines changed

src/components/ui/date-picker.tsx

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as React from "react";
22
import { ChevronLeft, ChevronRight } from "lucide-react";
3+
import { motion } from "framer-motion";
34

45
import { cn } from "@/lib/utils";
56

@@ -58,7 +59,10 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
5859

5960
for (let day = 1; day <= daysInCurrentMonth; day++) {
6061
days.push(
61-
<div
62+
<motion.div
63+
initial={{ opacity: 0 }}
64+
animate={{ opacity: 1 }}
65+
transition={{ delay: 0.01 * day }}
6266
key={day}
6367
className={cn(
6468
"grid-item place-self-center cursor-pointer rounded-lg w-[30px] h-[30px] flex items-center justify-center hover:bg-primary/30 transition-colors",
@@ -72,7 +76,7 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
7276
onClick={() => handleDateClick(day)}
7377
>
7478
{day}
75-
</div>
79+
</motion.div>
7680
);
7781
}
7882

@@ -89,24 +93,47 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
8993
{...props}
9094
>
9195
<div className="flex flex-row items-center gap-2 mb-2">
92-
<ChevronLeft
93-
onClick={handlePrevMonth}
94-
className="cursor-pointer rounded-md border-2 hover:bg-primary/30 hover:border-0 transition-colors"
95-
/>
96-
<span className="flex text-lg font-bold text-center">
96+
<motion.div
97+
initial={{ opacity: 0, x: -10 }}
98+
animate={{ opacity: 1, x: 0 }}
99+
transition={{ delay: 0.01 }}
100+
>
101+
<ChevronLeft
102+
onClick={handlePrevMonth}
103+
className="cursor-pointer rounded-md border-2 hover:bg-primary/30 hover:border-0 transition-colors"
104+
/>
105+
</motion.div>
106+
<motion.span
107+
initial={{ opacity: 0, y: -10 }}
108+
animate={{ opacity: 1, y: 0 }}
109+
transition={{ delay: 0.01 }}
110+
className="flex text-lg font-bold text-center"
111+
>
97112
{currentDate.toLocaleString("default", { month: "long" })}{" "}
98113
{currentDate.getFullYear()}
99-
</span>
100-
<ChevronRight
101-
onClick={handleNextMonth}
102-
className="cursor-pointer rounded-md border-2 hover:bg-primary/30 hover:border-0 transition-colors"
103-
/>
114+
</motion.span>
115+
<motion.div
116+
initial={{ opacity: 0, x: 10 }}
117+
animate={{ opacity: 1, x: 0 }}
118+
transition={{ delay: 0.01 }}
119+
>
120+
<ChevronRight
121+
onClick={handleNextMonth}
122+
className="cursor-pointer rounded-md border-2 hover:bg-primary/30 hover:border-0 transition-colors"
123+
/>
124+
</motion.div>
104125
</div>
105126
<div className="h-full w-full grid grid-cols-7 gap-1 p-2">
106127
{["S", "M", "T", "W", "T", "F", "S"].map((date, index) => (
107-
<div key={`${date}-${index}`} className="grid-item place-self-center">
128+
<motion.div
129+
initial={{ opacity: 0 }}
130+
animate={{ opacity: 1 }}
131+
transition={{ delay: 0.01 * index }}
132+
className="grid-item place-self-center"
133+
key={`${date}-${index}`}
134+
>
108135
{date}
109-
</div>
136+
</motion.div>
110137
))}
111138
{renderDays()}
112139
</div>

src/pages/Dashboard.tsx

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ import {
1111
MessageCircle,
1212
Map,
1313
HeartPulse,
14-
ArrowDown,
15-
ArrowUp
14+
CheckIcon
1615
} from 'lucide-react';
1716
import { Button } from '@/components/ui/button';
1817
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card';
@@ -185,7 +184,12 @@ const Dashboard: React.FC = () => {
185184
)}>
186185
{/* Current Streak Card - Check In Side */}
187186
{isCheckInSide ? (
188-
<div>
187+
<motion.div
188+
key="check-in-side"
189+
initial={{ opacity: 0 }}
190+
animate={{ opacity: 1 }}
191+
transition={{ duration: 0.5 }}
192+
>
189193
<CardHeader className="pb-2">
190194
<CardTitle className="flex items-center">
191195
<Trophy className="h-5 w-5 mr-2 text-primary" />
@@ -227,10 +231,15 @@ const Dashboard: React.FC = () => {
227231
Edit Streak Start Date
228232
</Button>
229233
</CardFooter>
230-
</div>
234+
</motion.div>
231235
) : (
232236
// Current Streak Card - Set Streak Start Date Side
233-
<div>
237+
<motion.div
238+
key="streak-start-side"
239+
initial={{ opacity: 0 }}
240+
animate={{ opacity: 1 }}
241+
transition={{ duration: 0.5 }}
242+
>
234243
<CardHeader className="pb-2">
235244
<CardTitle className="flex items-center">
236245
<Trophy className="h-5 w-5 mr-2 text-primary" />
@@ -241,7 +250,7 @@ const Dashboard: React.FC = () => {
241250
</CardDescription>
242251
</CardHeader>
243252
<CardContent>
244-
<div className="flex items-center justify-center py-6">
253+
<div className="flex items-center justify-center">
245254
{/* calculate the streak start date to display in DatePicker */}
246255
<DatePicker onDateChange={setSelectedDate} preselectedDate={new Date(Date.now() - streak * 24 * 60 * 60 * 1000)} />
247256
</div>
@@ -251,7 +260,7 @@ const Dashboard: React.FC = () => {
251260
onClick={handleStreakSet}
252261
className="w-full"
253262
>
254-
Set Streak Start Date
263+
Set Streak Start Date <CheckIcon />
255264
</Button>
256265
<Button
257266
variant="outline"
@@ -261,7 +270,7 @@ const Dashboard: React.FC = () => {
261270
Cancel
262271
</Button>
263272
</CardFooter>
264-
</div>
273+
</motion.div>
265274
)}
266275
</Card>
267276
</motion.div>

0 commit comments

Comments
 (0)