Skip to content

Commit 19fe959

Browse files
committed
feat (tasks): tasks frontend animations
1 parent 7ea7903 commit 19fe959

File tree

6 files changed

+64
-24
lines changed

6 files changed

+64
-24
lines changed

src/client/app/tasks/page.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -284,10 +284,10 @@ function TasksPageContent() {
284284
<AnimatePresence mode="wait">
285285
<motion.div
286286
key={view}
287-
initial={{ opacity: 0, y: 20 }}
288-
animate={{ opacity: 1, y: 0 }}
289-
exit={{ opacity: 0, y: -20 }}
290-
transition={{ duration: 0.2 }}
287+
initial={{ opacity: 0 }}
288+
animate={{ opacity: 1 }}
289+
exit={{ opacity: 0 }}
290+
transition={{ duration: 0.3 }}
291291
className="h-full"
292292
>
293293
{view === "list" ? (

src/client/components/tasks/CalendarView.js

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ import {
2323
import { cn } from "@utils/cn"
2424
import TaskCardCalendar from "./TaskCardCalendar"
2525

26+
const cellVariants = {
27+
hidden: { opacity: 0, y: -20, scale: 0.95 },
28+
visible: { opacity: 1, y: 0, scale: 1 }
29+
}
30+
2631
const CalendarDayCell = ({
2732
day,
2833
tasks,
@@ -37,15 +42,16 @@ const CalendarDayCell = ({
3742
const hasMoreTasks = tasks.length > 1
3843

3944
return (
40-
<div
45+
<motion.div
4146
onMouseEnter={() => setIsHovered(true)}
4247
onMouseLeave={() => setIsHovered(false)}
4348
onClick={() => onDayClick(day)}
49+
variants={cellVariants}
4450
className={cn(
4551
"border-r border-b border-neutral-800 p-2 flex flex-col gap-1 overflow-hidden relative min-h-[120px] rounded-lg",
4652
!isCurrentMonth && "bg-brand-black text-neutral-600",
4753
isSelected
48-
? "bg-brand-orange text-brand-black font-bold hover:bg-brand-orange"
54+
? "bg-brand-orange/90 text-brand-black font-bold hover:bg-brand-orange"
4955
: "hover:bg-neutral-800/70"
5056
)}
5157
>
@@ -99,7 +105,7 @@ const CalendarDayCell = ({
99105
</div>
100106
)}
101107
</div>
102-
</div>
108+
</motion.div>
103109
)
104110
}
105111

@@ -122,6 +128,14 @@ const CalendarView = ({ tasks, onSelectTask, onDayClick, onShowMoreClick }) => {
122128
onDayClick(day)
123129
}
124130

131+
const containerVariants = {
132+
hidden: { opacity: 1 },
133+
visible: {
134+
opacity: 1,
135+
transition: { staggerChildren: 0.02, delayChildren: 0.1 }
136+
}
137+
}
138+
125139
return (
126140
<div className="p-4 h-full flex flex-col bg-brand-black/50 backdrop-blur-sm rounded-xl border border-zinc-700/50">
127141
<header className="flex items-center justify-between mb-4">
@@ -150,7 +164,12 @@ const CalendarView = ({ tasks, onSelectTask, onDayClick, onShowMoreClick }) => {
150164
)
151165
)}
152166
</div>
153-
<div className="grid grid-cols-7 grid-rows-5 flex-1">
167+
<motion.div
168+
className="grid grid-cols-7 grid-rows-5 flex-1"
169+
variants={containerVariants}
170+
initial="hidden"
171+
animate="visible"
172+
>
154173
{daysInGrid.map((day) => {
155174
const tasksForDay = tasks.filter((task) =>
156175
isSameDay(task.scheduled_date, day)
@@ -168,7 +187,7 @@ const CalendarView = ({ tasks, onSelectTask, onDayClick, onShowMoreClick }) => {
168187
/>
169188
)
170189
})}
171-
</div>
190+
</motion.div>
172191
</div>
173192
)
174193
}

src/client/components/tasks/CreateTaskInput.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ const CreateTaskInput = ({ onTaskAdded, prompt, setPrompt }) => {
1414
const textarea = textareaRef.current
1515
if (textarea) {
1616
textarea.style.height = "auto"
17-
const scrollHeight = textarea.scrollHeight
18-
textarea.style.height = `${Math.min(Math.max(scrollHeight, 20), 100)}px`
17+
textarea.style.height = `${Math.min(textarea.scrollHeight, 100)}px`
1918
}
2019
}, [prompt])
2120

@@ -48,13 +47,13 @@ const CreateTaskInput = ({ onTaskAdded, prompt, setPrompt }) => {
4847
<div className="p-4 flex-shrink-0 bg-transparent">
4948
<div
5049
className={cn(
51-
"relative flex items-end bg-brand-black rounded-full p-1 transition-all overflow-hidden"
50+
"relative flex bg-brand-black rounded-full p-1 transition-all overflow-hidden min-h-[50px]"
5251
)}
5352
>
5453
<BorderTrail size={100} className="bg-brand-orange px-4" />
5554
<div
5655
className={cn(
57-
"relative flex gap-2 items-end bg-transparent p-1 transition-all w-full"
56+
"relative flex gap-2 items-stretch bg-transparent p-1 transition-all w-full"
5857
)}
5958
>
6059
<textarea
@@ -68,7 +67,7 @@ const CreateTaskInput = ({ onTaskAdded, prompt, setPrompt }) => {
6867
}
6968
}}
7069
placeholder=" "
71-
className="w-full rounded-l-full bg-transparent text-white placeholder-transparent border-1 border-brand-orange focus:ring-0 focus:ring-brand-black text-sm z-10 overflow-y-auto"
70+
className="w-full rounded-l-full bg-transparent text-white placeholder-transparent border-1 border-brand-orange focus:ring-0 focus:ring-brand-black text-sm z-10 overflow-y-auto self-stretch py-2"
7271
/>
7372
{!prompt && (
7473
<div className="absolute top-1/2 left-4 -translate-y-1/2 text-neutral-500 pointer-events-none z-0">
@@ -89,7 +88,7 @@ const CreateTaskInput = ({ onTaskAdded, prompt, setPrompt }) => {
8988
<button
9089
onClick={handleAddTask}
9190
disabled={isSaving || !prompt.trim()}
92-
className="p-3 bg-brand-orange rounded-r-full h-12 text-brand-black disabled:opacity-50 hover:bg-opacity-80 transition-colors z-10 flex-shrink-0"
91+
className="p-3 bg-brand-orange rounded-r-full h-full text-brand-black disabled:opacity-50 hover:bg-opacity-80 transition-colors z-10 flex-shrink-0"
9392
>
9493
{isSaving ? (
9594
<IconLoader size={18} className="animate-spin" />

src/client/components/tasks/ListView.js

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use client"
22
import React, { useMemo } from "react"
3-
import { AnimatePresence } from "framer-motion"
3+
import { AnimatePresence, motion } from "framer-motion"
44
import { IconSearch, IconChevronDown } from "@tabler/icons-react"
55
import { groupTasksByDate } from "@utils/taskUtils"
66
import TaskCardList from "./TaskCardList"
@@ -16,6 +16,14 @@ const ListView = ({
1616
}) => {
1717
const { today, tomorrow, future } = groupTasksByDate(oneTimeTasks)
1818

19+
const containerVariants = {
20+
hidden: { opacity: 1 }, // Let the parent control opacity
21+
visible: {
22+
opacity: 1,
23+
transition: { staggerChildren: 0.07 }
24+
}
25+
}
26+
1927
const sections = [
2028
{ title: "Today", tasks: today },
2129
{ title: "Tomorrow", tasks: tomorrow },
@@ -70,15 +78,20 @@ const ListView = ({
7078
title={`Active Workflows (${recurringTasks.length})`}
7179
defaultOpen={true}
7280
>
73-
<div className="space-y-3 pt-2">
81+
<motion.div
82+
className="space-y-3 pt-2"
83+
variants={containerVariants}
84+
initial="hidden"
85+
animate="visible"
86+
>
7487
{recurringTasks.map((task) => (
7588
<TaskCardList
7689
key={task.task_id}
7790
task={task}
7891
onSelectTask={onSelectTask}
7992
/>
8093
))}
81-
</div>
94+
</motion.div>
8295
</CollapsibleSection>
8396
)}
8497

@@ -90,15 +103,20 @@ const ListView = ({
90103
title={`${section.title} (${section.tasks.length})`}
91104
defaultOpen={true}
92105
>
93-
<div className="space-y-3 pt-2">
106+
<motion.div
107+
className="space-y-3 pt-2"
108+
variants={containerVariants}
109+
initial="hidden"
110+
animate="visible"
111+
>
94112
{section.tasks.map((task) => (
95113
<TaskCardList
96114
key={task.instance_id}
97115
task={task}
98116
onSelectTask={onSelectTask}
99117
/>
100118
))}
101-
</div>
119+
</motion.div>
102120
</CollapsibleSection>
103121
)
104122
)}

src/client/components/tasks/TaskCardCalendar.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const TaskCardCalendar = ({ task, onSelectTask }) => {
1919
}}
2020
className={cn(
2121
"w-full p-2 rounded-md text-xs font-medium text-white cursor-pointer truncate",
22-
"bg-neutral-700 hover:bg-neutral-600"
22+
"bg-brand-gray/20 hover:bg-brand-gray/80"
2323
)}
2424
>
2525
<div className="flex items-center gap-2">

src/client/components/tasks/TaskCardList.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,16 @@ const TaskCardList = ({ task, onSelectTask }) => {
4040
"clarification_answered"
4141
].includes(task.status)
4242

43+
const cardVariants = {
44+
hidden: { opacity: 0, y: -20, scale: 0.95 },
45+
visible: { opacity: 1, y: 0, scale: 1 }
46+
}
47+
4348
const cardContent = (
4449
<motion.div
4550
layout
46-
initial={{ opacity: 0 }}
47-
animate={{ opacity: 1 }}
48-
exit={{ opacity: 0 }}
51+
variants={cardVariants}
52+
exit={{ opacity: 0, transition: { duration: 0.1 } }}
4953
onClick={() => onSelectTask(task)}
5054
className="bg-brand-black p-4 rounded-lg border border-zinc-700 hover:border-brand-orange transition-all cursor-pointer relative"
5155
>

0 commit comments

Comments
 (0)