Skip to content

Commit 0f6661f

Browse files
committed
feat: show animation on one or more item delete
1 parent 3860672 commit 0f6661f

File tree

7 files changed

+70
-8
lines changed

7 files changed

+70
-8
lines changed

app/globals.css

+16
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,20 @@ body {
3131
.todo_checkbox:checked~.todo_content {
3232
text-decoration: line-through;
3333
color: var(--grayish-text);
34+
}
35+
36+
.animating {
37+
animation: slideIn 0.6s ease-in-out;
38+
}
39+
40+
@keyframes slideIn {
41+
0% {
42+
opacity: 1;
43+
transform: translateX(0);
44+
}
45+
46+
100% {
47+
opacity: 0.5;
48+
transform: translateX(-100%);
49+
}
3450
}

app/page.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import BackgroundImage from "@/components/BackgroundImage"
22
import DarkModeToggler from "@/components/DarkModeToggler"
33
import Form from "@/components/Form"
44
import TodosContents from "@/components/TodosContents"
5+
import AnimationProvider from "@/provider/AnimationProvider"
56
import ThemeProvider from "@/provider/ThemeProvider"
67
import TodoProvider from "@/provider/TodoProvider"
78

@@ -10,6 +11,7 @@ const Home = () => {
1011
return (
1112
<ThemeProvider>
1213
<TodoProvider>
14+
<AnimationProvider>
1315
<main className="bg-bg h-screen">
1416

1517
<BackgroundImage />
@@ -36,6 +38,7 @@ const Home = () => {
3638
<p className="text-grayish-text text-center md:mt-0 pb-10 mt-20">Drag and drop yo reorder list</p>
3739

3840
</main>
41+
</AnimationProvider>
3942
</TodoProvider>
4043
</ThemeProvider>
4144
)

components/ClearAllCompletedBtn.tsx

+12-3
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
11
'use client'
22
import React from 'react'
33
import { TodoContext } from '@/context/TodoContext'
4+
import { AnimationContext } from '@/context/AnimationContext'
45

56
const ClearAllCompletedBtn = ({ todos }: { todos: TodoType[] }) => {
67

78
const { setIsManipulated } = React.useContext(TodoContext)
9+
const {setAnimating} = React.useContext(AnimationContext)
810

911
const deleteAll = () => {
10-
const newTodos = todos.filter(todo => !todo.completed)
11-
localStorage.setItem('todos', JSON.stringify(newTodos))
12-
setIsManipulated(true)
12+
13+
const completedTodos = todos.filter(todo => todo.completed)
14+
setAnimating(completedTodos.map(todo => todo.id.toString()))
15+
16+
setTimeout(() => {
17+
const newTodos = todos.filter(todo => !todo.completed)
18+
localStorage.setItem('todos', JSON.stringify(newTodos))
19+
setIsManipulated(true)
20+
setAnimating([])
21+
}, 500);
1322
}
1423

1524
return (

components/ListItem.tsx

+15-4
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
import React from 'react'
33
import Image from 'next/image'
44
import { TodoContext } from '@/context/TodoContext'
5+
import { AnimationContext } from '@/context/AnimationContext'
56

67
const ListItem = ({ id, content, completed, todos }: ListItemProps) => {
78

89
const { setIsManipulated } = React.useContext(TodoContext)
10+
const {animating, setAnimating} = React.useContext(AnimationContext)
911

1012
const handleChange = () => {
1113
const todo = todos.find(todo => todo.id === Number(id))
@@ -15,14 +17,23 @@ const ListItem = ({ id, content, completed, todos }: ListItemProps) => {
1517
}
1618

1719
const deleteItem = () => {
18-
const newTodos = todos.filter(todo => todo.id !== Number(id))
19-
localStorage.setItem('todos', JSON.stringify(newTodos))
20-
setIsManipulated(true)
20+
setAnimating([id])
21+
22+
console.log(animating)
23+
24+
setTimeout(() => {
25+
const newTodos = todos.filter(todo => todo.id !== Number(id))
26+
localStorage.setItem('todos', JSON.stringify(newTodos))
27+
28+
setIsManipulated(true)
29+
30+
setAnimating([])
31+
}, 500)
2132
}
2233

2334
return (
2435
<>
25-
<div className="todo_item flex items-center justify-between w-full group px-5 py-2 relative">
36+
<div className={`${(animating.includes(id)) ? 'animating' : ''} todo_item flex items-center justify-between w-full group px-5 py-2 relative`}>
2637
<div className='flex items-center w-full'>
2738
<input
2839
onChange={handleChange}

components/TodosContents.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ const TodosContainer = () => {
4545
<div className="animate-pulse bg-grayish-text h-full rounded-md" />
4646
</div>
4747
:
48-
<div className="bg-card-bg rounded-md transition-all shadow-md py-2 mt-8 mb-10" >
48+
<div className="bg-card-bg rounded-md transition-all overflow-x-hidden shadow-md py-2 mt-8 mb-10" >
4949
{renderTodos()}
5050
<ListControls todos={todos} len={todos.filter(todo => !todo.completed).length} />
5151
</div>

context/AnimationContext.ts

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
'use client'
2+
import React from 'react'
3+
4+
export const AnimationContext = React.createContext({
5+
animating: [] as string[],
6+
setAnimating: (animating: string[] ) => { },
7+
})

provider/AnimationProvider.tsx

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
'use client'
2+
import React from 'react'
3+
import { AnimationContext } from '@/context/AnimationContext'
4+
5+
const AnimationProvider = ({ children }: ChildrenProps) => {
6+
7+
const [animating, setAnimating] = React.useState<string[]>([])
8+
9+
return (
10+
<AnimationContext.Provider value={{ animating, setAnimating }}>
11+
{children}
12+
</AnimationContext.Provider>
13+
)
14+
}
15+
16+
export default AnimationProvider

0 commit comments

Comments
 (0)