I have a Sidebar on left of my App, and it is set on 300px wide. When I click on a button, the Sidebar goes from 300px to 50px.
I change this width with a state :
const [isMinimized, setIsMinimized] = useState(false);
[...]
<div className={`${isMinimized ? 'w-16' : '2xl:w-80 w-56'} relative bg-white`}>
I'd like to set an animation when the sidebar minimize. I tried to add an animation on my div, but does not work.
Is it possible ?
CodePudding user response:
You can specify a className when isMinimized is true ( for Example isMinimzed ? 'animatedScrollbar w-16' : '2xl:w-80 w-56') and add your transition as css using the className of the minimized state .
CodePudding user response:
You need to add transition-width
so tailwind adds transition-property:width
to the element's style properties.
You can do this all within JSX with tailwind classes. No need for other code. Check below
function MyApp() {
const [isMinimized, setIsMinimized] = React.useState(false);
return (
<div >
<div
className = {
`${isMinimized ? 'w-16' : '2xl:w-80 w-56'} relative bg-black duration-1000 transition-width ease-in-out`
} >
MY DIV
</div>
<button
onClick = {() => setIsMinimized(!isMinimized)}
>
CLICK
</button>
</div>
)
}
ReactDOM.createRoot(
document.getElementById("root")
).render( <
MyApp / >
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
Or see jsFiddle
If you want to add custom transition durations or behaviors you would need to change tailwind config. Read more here tailwind transition
CodePudding user response:
Use Web Animation API
First create a ref
object of the element you change its width.
const ref = useRef(null);
And use it:
<div ref={ref} className={relative bg-white`}>
Call this function on click.
const onClick = () => {
const { current } = ref;
if (current) {
const keyframe = [{ width: "300px" }, { width: "50px" }];
const options = {
duration: 1000,
fill: "forwards",
delay: 0,
easing: "ease-in",
};
const newKeyframeEffect = new KeyframeEffect(current, keyframe, options);
const animation = new Animation(newKeyframeEffect, document.timeline);
animation.play();
animation.onfinish = () => {
}
}
};
Do whatever you need in onfinish
functoin.
If you need to change the width of the element back to 300px
, do this:
Track if the element is expanded.
const [isExpended, setIsExpended] = useState(false)
If expanded, change its width from 300px
to 50px
. Else vise versa.
const keyframe = isExpended ? [{ width: "50px" }, { width: "300px" }]: [{ width: "300px" }, { width: "50px" }];
When the animation finishes, change the isExpended
state.
setIsExpended(!isExpended)
Example code
const App = () => {
const ref = useRef(null)
const [isExpended, setIsExpended] = useState(false)
const onClick = () => {
const { current } = ref;
if (current) {
const keyframe = isExpended ? [{ width: "50px" }, { width: "300px" }]: [{ width: "300px" }, { width: "50px" }];
const options = {
duration: 1000,
fill: "forwards",
delay: 0,
easing: "ease-in",
};
const newKeyframeEffect = new KeyframeEffect(current, keyframe, options);
const animation = new Animation(newKeyframeEffect, document.timeline);
animation.play();
animation.onfinish = () => setIsExpended(!isExpended);
}
};
return <div ref={ref} style={{width: "300px", background: "red"}}>
<button onClick={onClick} type="button">Click</button>
</div>
}
Try this
https://stackblitz.com/edit/react-17rkkx?file=src/App.js
Reference
- useRef - https://reactjs.org/docs/hooks-reference.html#useref
- Web Animation API - https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API