Before we start
This is a small and easy guide about something you can do easily with React and CSS3.
First, a few things you need to know about before we start :
- ReactJS – Beginner
- CSS3 Transitions – Beginner
How-to
What we are building is something like this JQuery UI plugin.
We have content, and titles. When the user clicks on a title, it opens the accordion below while closing the others.
React modelisation
Let’s start with the simple HTML content that we want to have (For React very beginners) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
This is not a file we are making, but this is what we will try to model with React.
So, first things first, let’s put the content in a simple json object (there are many ways to get data to build react components but we’ll talk about that in another post).
backendData.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Then, we build our components for the ground up. First, the section component we’ll instantiate:
section.jsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
(I decided to put the data given by my “back-end” in a single JS object. Single responsibility, DRY code, let’s say I have reasons)
Then, we make the container component, that creates nested sections with our data:
container.jsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
So far so good, we get pretty much exactly the html code above if we instantiate our page with something like this :
1 2 3 4 |
|
Now on to setting up our closed/open states
Closed/Open states
First, let’s hide the sectionContents with some simple CSS.
1 2 3 |
|
The only thing to note here is that we will be using heights, from 0 to … what we need. So, to do so, we need to make it so that the overflow is hidden instead of toggling display:none
and display:block
Now, let’s trigger these changes in our components :
section.jsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
In here, assign a height based on the state of our component to our sectionContent. I chose 3em pretty randomly because I like fixed things, you can decide to calculate the height you need instead. The inherit and auto don’t work well with transitions, but they will work if you don’t need them. This state is changed when you click on the title. It triggers the toggleContent function that inverts the closed state.
So, now we have a closed and a open state. We toggle between them based on the state of our Section component, defined by how many times we clicked on that title.
If you are looking for a way to make tabs open all at once, stop here. If you’re looking for that JQueryUI style One tab only thing, keep on to the next part
Closing all of them when one is open
Single responsibility principles tells us our Sections don’t know about the other sections. That means our section cannot tell the others to close. The container, however, knows about all of the sections…
container.jsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
Now, we actually play with the state of the parent component. It keeps track of the id of the tab that is open, and starts with -1.
We pass the toggleOneSection callback to the child component (the section), it takes an id (the id of the thing we want to toggle), and it sets the openSectionIndex of the state accordingly to our argument, or back to nothing (-1).
We then build sections with an “open” prop, a boolean that will be the thing that is used to get the class of our sectionContent, instead of the Section’s state. React building the page on the go, from the javascript, in the way of a simple diff, the children will just be changed instead of generated again, which will trigger whatever we have on them (listeners, animations, etc…).
Now to the section :
section.jsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
As I said above, getContentToggleClass now uses the props instead of the state, and I got rid of the other state functions. The toggleContent internal callback now call the callback we called in the props, with that key that we gave it at the very beginning.
Now, up to animations
Animations
This is the very easy part. To trigger the animations, we just put a “transition” on the container selector, in the css.
style.css
1 2 3 4 5 6 7 8 |
|
This tells the interpreter that when the height changes, it has to take 0.3s to transition into the new height, with ease-in giving it a slow start for a cleaner interface (just a matter of preferences on this one).
And we now have our accordion menu.
Conclusion
You now have a clean accordion menu. I tend to add a few styling thing that I consider the bare minimum on that like :
1 2 3 4 |
|
But that’s just me. Also, you don’t need to use H2s, you can use whatever you want, links work too but remember to preventDefault if you use them.
Let me know what you thought about that guide, I may have missed things here and there, and thank you for reading!
Last minute edit :
You can check the code on Github. Download it, run it, check it out!