How To Create a Stunning Side Drawer with React-spring
• 4 min read
Introduction
A side drawer component is a common UI pattern used in all sorts of apps, ranging from mobile apps to web apps to desktop apps.
So what is a side drawer?
A side drawer component is a sliding panel that can be used to display additional information or actions.
At my job, I recently had to create a side drawer and due to specific constraints had to create it using react-spring. These are the steps I took to create one from scratch.
Requirements
- Button to toggle the side drawer.
- Secondly, animate the dimmed overlay and side drawer.
- Finally, clicking on the overlay should hide the overlay and side drawer.
Breaking it down
With the requirements taken into consideration I figured I should first break it down into steps:
- Show button
- Animate overlay on button click
- Animate side drawer
- Close on overlay click
Code-along
First and foremost, let's create the button that will handle the on-click event. The click event should toggle the state of the side drawer
JavaScriptexport default function App() {
const [show, setShow] = useState();
return (
<div className="App">
<button onClick={() => setShow((prevState) => !prevState)}>
Click me
</button>
</div>
);
}
Easy enough. Now, let's start hooking up react-spring to the state we just created. Thinking about how the animations will work first we want to display the overlay as well as push out the side drawer at the same time. The contents inside of the side drawer don’t really concern us too much but in order for the transitions to be used fluidly and prevent state management errors let’s use useTransitition.
useTransition is a hook provided to us by react-spring specifically for the task of tackling lifecycles!
JavaScriptconst transitions = useTransition(show, null, {
from: { position: 'fixed', opacity: 0, width: 0 },
enter: { opacity: 1, width: 320 },
leave: { opacity: 0, width: 0 },
});
Now let’s break down the hook itself. We are evaluating the show state we had set earlier and are declaring two styles to adjust: the opacity of the overlay and the width of the side drawer.
The Overlay
First, let’s code up the overlay; all we have to do is display a dimmed div.
JavaScript<div className="App">
<button onClick={() => setShow((prevState) => !prevState)}>Click me</button>
{transitions?.map(
({ item, key, props }) =>
item && (
<animated.div
key={key}
style={{ opacity: props.opacity }}
className="overlay"
/>
)
)}
</div>
Transitions must be mapped over. The key is for react to differentiate between the different items in the array. Because we are only interested in the overlay for the moment we will pass the opacity we declared in the previous hook.
Side drawer
Now lets go ahead and animate the inner side drawer as well.
JavaScript<div className="App">
<button onClick={() => setShow((prevState) => !prevState)}>Click me</button>
{transitions?.map(
({ item, key, props }) =>
item && (
<animated.div
key={key}
style={{ opacity: props.opacity }}
className="overlay">
<animated.div
style={{ width: props.width }}
className="drawer">
Hey look it's a side drawer!
</animated.div>
</animated.div>
)
)}
</div>
Similar to the overlay, we create our animated div and pass in the width from useTransition.
All that’s left to do is close the overlay when we click it for a great user experience.
JavaScript<animated.div style={{ width: props.width }} className="drawer">
Hey look it's a side drawer!
</animated.div>
<div className="fill" onClick={() => setShow(false)} />
Right next to the side drawer div we will put the div that handles the on-click event.
And with that, we’re done!
Heres a working example of the code:
If you see any typos or errors you can edit the article directly on GitHub
Hi, I'm Diego Ballesteros 👋.
Stay on top of the tech industry and grow as a developerwith a curated selection of articles and news alongside personal advice, observations, and insight. 🚀
No spam 🙅♂️. Unsubscribe whenever.
You may also like these articles:
- 2023-06-05T00:41:29.681Z
- 2022-10-25T11:29:26.663Z
- 2022-10-17T14:44:10.229Z
- 2022-10-10T14:02:10.349Z