Sometimes I want to create a nice, simple component that doesn’t require adding any additional dependencies. Before I made the decision to implement Material UI, I found myself creating a lot of components from scratch. Constantly searching through npm, installing packages, ensuring dependencies are kept up-to-date can cause your codebase to grow out of control.
The benefits of this component are that it’s super lightweight – I already had Styled Components installed, and the icons I pulled from my existing assets. As with most components in React, I wanted this to be reusable, simple and generalisable.
Honestly, sometimes I get lazy, and I let other people do the heavy lifting for me. However, a quick Google search let me down in this case. I couldn’t find what I was looking for anywhere. There were packages, vanilla JavaScript projects, jQuery… The search for how to create a React accordion using styled components was doing me dirty.
So, I thought I’d go back to my vanilla JS days and create one from scratch. This way, I could customise the look and feel to our website, and play with the functionality.
Let’s begin where software engineers always (sometimes? should but often don’t?) begin – the requirements.
Having a defined list of requirements meant I was less likely to encounter scope creep, or create something else entirely!
Ok, I know why you’re really here. There’s 3 key parts to this component:
As stated in the requirements, this shall be mobile responsive and resize on display or hide.
What’s going on under the hood here? The section itself will span the entire width of the page, and display the accordion in the centre. The transition property let’s the accordion grow or shrink in a smooth way that adds to user experience. The section height will change based on whether a dropdown is displayed, and if it is displayed on mobile.
The container simply adds some styling, and sets a maximum width based on a global variable maxWidth.
I wanted a simple aesthetic, so kept the background white, with dark grey writing. Each is separated by a thin border, and I’ve added some simple styling to the text. The icon displayed changes based on whether the index of the question in question (see what I did there?) is clicked, if so, display a “-”icon, otherwise it’s the standard “+”.
Given the requirement of reading data, I chose to map over this data and return each question. Each question has an onClick handler, that sets state to display that dropdown. Not forgetting some checks for whether a question is already clicked!
This is pretty simple – this is only displayed if clicked is true. Since this is handled using JS, this definitely does not optimise for SEO .Should you wish to do so, it’s better to handle displaying the dropdown using CSS so it isn’t unmounted each time it’s clicked.
In this case, the dropdown component is displayed with the text and any contact information from the data. This allowed me to add in contact information using a tags, instead of plain text.