Reputation: 219
I don't know why my transition works in one direction only, with the gif it is better understood, I want it to work both ways, when the completed tasks appear and disappear, thanks for reading.
Component TaskItem:
import React, { memo } from 'react'
import styled from "styled-components"
//STYLES
const DIV = styled.div`
max-height: ${
props => !props.show && props.done ? "0px" : "150px"
};
opacity: ${
props => !props.show && props.done ? "0": "1"
};
padding: ${
props => !props.show && props.done ? "0px":"12px 15px"
};
overflow: hidden;
transition: max-height, opacity 1s;
`;
const TR = styled.tr`
:nth-child(even) {background-color: #f3f3f3;}
border-bottom: ${
props => !props.show && props.done ? "none": "1px solid #dddddd"
};;
`;
const TD = styled.td`
/* padding: ${props => {
if (props.show && props.done) {
return "12px 15px"
}
else if (!props.show && props.done) {
return "0"
}
return "12px 15px"
}}; */
/* overflow: hidden;
transition: all 0.3s; */
`;
function TaskRow({ task, toggleDoneTask, show }) {
return (
<TR show={show} done={task.done}>
<TD>
<DIV show={show} done={task.done}>
{task.title}
</DIV>
</TD>
<TD>
<DIV show={show} done={task.done}>
{task.description}
</DIV>
</TD>
<TD>
<DIV show={show} done={task.done}>
<input type="checkbox"
checked={task.done}
onChange={toggleDoneTask}
/>
</DIV>
</TD>
</TR>
)
}
export default memo(TaskRow, (prev, next) => {
//COMPARE TASK OBJECT
const prevTaskKeys = Object.keys(prev.task);
const nextTaskKeys = Object.keys(next.task);
const sameLength = prevTaskKeys.length === nextTaskKeys.length;
const sameEntries = prevTaskKeys.every(key => {
return nextTaskKeys.includes(key) && prev.task[key] === next.task[key];
});
//COMPARE PROP SHOW, CHECK IF SHOW CONTROL CHANGE
const sameShow = prev.show === next.show
return sameLength && sameEntries && sameShow;
})
Component Tasks:
import React, { useEffect, useReducer } from 'react'
import TaskItem from "./TaskItem";
function saveLocalStorage(tasks) {
localStorage.setItem('tasks', JSON.stringify(tasks))
}
function TasksReducer(taskItems, { type, task }) {
switch (type) {
case 'UPDATE_TAKS': {
let taskItemsCopy = [...taskItems].map((task) => ({ ...task }))
let newItems = taskItemsCopy.map((t) => {
if (t.id === task.id) {
t.done = !t.done
};
return t;
})
saveLocalStorage(newItems)
return newItems
}
case 'ADD_TASK': {
const newItems = [...taskItems, task]
saveLocalStorage(newItems)
return newItems
}
default:
window.alert('INVALID ACTION')
break;
}
}
const initialState = JSON.parse(localStorage.getItem('tasks')) || []
//STYLES
const styleTable = {
'borderCollapse': 'collapse',
'margin': '25px 0',
'fontSize': '0.9em',
'fontFamily': 'sans-serif',
'minWidth': '400px',
'boxShadow': '0 0 20px rgba(0, 0, 0, 0.15)'
}
const styleTr = {
'backgroundColor': '#009879',
'color': '#ffffff',
'textAlign': 'left'
}
const styleTh = {
padding: '12px 15px'
}
function Tasks({ newTask, show }) {
const [taskItems, dispatch] = useReducer(TasksReducer, initialState);
useEffect(() => {
if (!newTask) return
newTaskHandler({ id: taskItems.length + 1, ...newTask })
}, [newTask])
const newTaskHandler = (task) => {
dispatch({ type: 'ADD_TASK', task })
}
const toggleDoneTask = (task) => {
dispatch({ type: 'UPDATE_TAKS', task })
}
return (
<React.Fragment>
<h1>learning react </h1>
<table style={styleTable}>
<thead>
<tr style={styleTr}>
<th style={styleTh}>Title</th>
<th style={styleTh}>Description</th>
<th style={styleTh}>Done</th>
</tr>
</thead>
<tbody>
{
taskItems.map((task) => {
return <TaskItem
task={task}
key={task.id}
show={show}
toggleDoneTask={() => toggleDoneTask(task)}>
</TaskItem>
})
}
</tbody>
</table>
</React.Fragment>
)
}
export default Tasks
If the complete code is required:
---IGNORE-- It looks like your post is mostly code; please add some more details.
Upvotes: 1
Views: 420
Reputation: 10382
when using transition, if you declare for multiple properties then you need to set transition-duration (and any other prop you want) to each of then. the way you wrote only opacity
had transition-duration set. you need to add to max-height also:
transition: max-height 1s, opacity 1s;
Upvotes: 2