Issue
there is an example with content dropdown: https://codesandbox.io/s/expand-content-4pc09c?fil...
But the appearance of content on the button is quite fast. I need to set smoothness using the transition property, but it didn't work.
As far as I understand, you need to add some kind of appearance effect with the help of visability
, but here there is a link to useState also tried to set a property for the content: transition: all 0.5s ease-out;
but the animation is not happening
I also tried change styles like that:
const styles = {
height: expand ? "auto" : "0px",
maxHeight: expand ? "auto" : "0px",
overflow: expand ? "visible" : "hidden"
};
but it turns out that i have the same result
Solution
You have to keep on mind various things to make it works. In your codepen there's a typo in visibility
animation in styles.css. I attached you a working snippet but I'm explaining you some important topics about how it works.
Explanation
First of all if you're toggling styles with you styles
variable it'll no respect transition as it will be rendered as inline styles, so the approach I use was create a new .wrapper__content.expanded
class and the class is the one that'll be toggled with the state.
Second about CSS properties:
visibility
cannot be transitioned as it doesn't have 'in-between' values, when the time of the transition (let's suppose 300ms) had passed it will change tovisible
orhidden
with no intermediate values, that's why it cannot be 'animated'. But if you still want to add this property for accessibility purposes you can add atransition-delay
to this property timing to trigger the change when height transition had finish.height
property is a difficult one to animate because it needs explicit values to work and I recommend you not to change theheight: auto
that comes by default, as it'll be adapting to its content (avoiding overflow issues). Instead of transitioning this property you should usemax-height
in collapsed state with a value of 0 and in expanded state with a value that your content will never reach (1000px in my snippet). This will do the trick, don't forget to addoverflow:hidden;
to hide the content when it's collapsed.
I think this answer will fulfill you requirements, but any questions feel free to ask. Hope it helps.
const App =() => {
const [expand, setExpand] = React.useState(false);
const onToggle = () => {
setExpand(!expand);
};
return (
<div className="wrapper">
<div className="wrapper__expand">
<button onClick={onToggle} className="wrapper__expand-btn">
+
</button>
Expand
</div>
<div className={expand ? 'wrapper__content expanded' : 'wrapper__content'}>
expanded content
</div>
</div>
);
}
ReactDOM.render( < App / > , document.getElementById("root"));
.App {
font-family: sans-serif;
text-align: center;
}
.wrapper {
display: flex;
flex-direction: column;
}
.wrapper__expand {
display: flex;
column-gap: 10px;
}
.wrapper__content {
margin-top: 10px;
overflow: hidden;
max-height: 0;
transition: max-height .5s ease-in-out;
}
.wrapper__content.expanded {
max-height: 1000px;
}
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
Answered By - Franco Gabriel
Answer Checked By - - Marilyn (ReactFix Volunteer)