CodeNewbie Community

Cover image for How I handle the Accordion Functionality [Walkthrough]
Vanza Setia
Vanza Setia

Posted on

How I handle the Accordion Functionality [Walkthrough]

In this article, I'm going to share my story on how I did the FAQ Accordion Card challenge. Hopefully this article is helpful for everyone, especially for those of you that doing this challenge.

Overview

Image from Unsplash by AltumCode (the image has been edited)

After learning JavaScript for about one month, I decided to do the challenge from Frontend Mentor. I chose the FAQ Accordion Card challenge because it had newbie difficulty and like it's said the description, "...This is an extremely common front-end pattern, so it's a great opportunity to get some practice in!"

Feel free to see my solution in your browser and the GitHub repository to get more information about the project. You can give your feedback to my solution on Frontend Mentor or just write it down in the comment of this blog post.

Your feedback can help me become a better developer!

The Challenge

Image from Unsplash by JESHOOTS.COM

The challenge is to build out this FAQ accordion card and get it looking as close to the design as possible.

The users should be able to:

  • View the optimal layout for the component depending on their device's screen size
  • See hover states for all interactive elements on the page
  • Hide/Show the answer to a question when the question is clicked

Additional challenge for accessibility:

  • User should be able to navigate this website using keyboard
  • User should be able to understand the page content when using screen reader

The Process

Image from Unsplash by UX Indonesia

Like any good developers, planning is the first thing to do before writing any code.

First, what I want the user should be able to do:

  • Toggle the accordion
  • Auto close the opened accordion, when the user open another accordion

Simple right? Now, I get the user story. Then what? It's time to write the pseudocode. You might say, "Wait! Wait! What is pseudocode?" Pseudocode is simply not a real code. The point is you only need to write the functionality without care about semicolon, syntax, best practices, etc. You can even write it in your language (English, Indonesia, etc).

This is my pseudocode 😊.

// Ingredients (DOM ELEMENTS)
all accordion buttons
all accordion panels

// Functionality
FUNCTION closedAllPanels {
  close all opened panels
}

FUNCTION openTheCurrentPanel (currentButton, currentPanel) {
  open the current panel
}

FUNCTION closedCurrentPanel (currentButton, currentPanel) {
  close the current panel
}

FUNCTION togglePanel {
  Get the currentButton
  Get the currentPanel
  IF the current panel is closed {
    * All opened panel to be closed
    * Open the current panel
  } ELSE {
    * Closed the current panel
  }
}
Enter fullscreen mode Exit fullscreen mode

Now, after I wrote the pseudocode. It's time to translate that pseudocode into JavaScript code.

Before continue to the JavaScript, let's take an overview on the HTML markup.

<div class="accordion__item">
  <h2 class="accordion__heading">
    <button
      id="firstAccordionBtn"
      class="accordion__trigger js-accordionBtn"
      type="button"
      aria-expanded="false"
      aria-controls="firstAccordion"
    >
      <span class="accordion__title"
        >How many team members can I invite?</span
      >
      <span class="accordion__icon" aria-hidden="true">
        <!-- prettier-ignore -->
        <svg width="10" height="7" xmlns="http://www.w3.org/2000/svg"><path d="M1 .799l4 4 4-4" stroke="#F47B56" stroke-width="2" fill="none" fill-rule="evenodd"/></svg>
      </span>
    </button>
  </h2>
  <div
    role="region"
    id="firstAccordion"
    class="accordion__panel js-accordionPanel"
    aria-labelledby="firstAccordionBtn"
    hidden
  >
    <p class="accordion__description">
      You can invite up to 2 additional users on the Free
      plan. There is no limit on team members for the
      Premium plan.
    </p>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

If you notice that there are two js classes, that is a sign that I am going to use those elements in JavaScript and it's also making it clear that only the element that has js class that will be used or manipulated by JavaScript.

The HTML markup is coming from Accordion Example | WAI-ARIA Authoring Practices 1.1 site. It really helped me to create an accessible accordion.

Now let's break down the pseudocode.

  1. I needed to select all accordion buttons and accordion panels. Here what I did:
const accordionButtons = 
  document.querySelectorAll(
    '.js-accordionBtn'
);
const accordionPanels = 
  document.querySelectorAll(
      '.js-accordionPanel'
);
Enter fullscreen mode Exit fullscreen mode
  1. Great! I made progress! Next, I needed to add click event to all buttons.
accordionButtons.forEach(button => {
  button.addEventListener('click', togglePanel);
});
Enter fullscreen mode Exit fullscreen mode
  1. After that create the togglePanel() function right above the event listener code.
const togglePanel = event => {
  const currentAccordionButton = event.currentTarget;
  const currentAccordionPanel =
    currentAccordionButton.parentElement.nextElementSibling;

  if (currentAccordionPanel.hasAttribute('hidden')) {
    closeAllOpenedPanel();
    openCurrentPanel(currentAccordionButton, currentAccordionPanel);
  } else {
    closeCurrentPanel(
      currentAccordionButton,
      currentAccordionPanel
    );
  }
};
Enter fullscreen mode Exit fullscreen mode
  • I used currentTarget instead of target to make sure that it always points the button element that I or users clicked and make it easier to target the accordion panel element.
  1. Amazing! Now It's time to create closeAllOpenedPanel() function first.
const closeAllOpenedPanel = () => {
  accordionPanels.forEach(panel => {
    panel.setAttribute('hidden', '');
  });
  accordionButtons.forEach(button => {
    button.setAttribute('aria-expanded', 'false');
  });
};
Enter fullscreen mode Exit fullscreen mode
  1. Next, it's to create openCurrentPanel() function.
const openCurrentPanel = (currentButton, currentPanel) => {
  currentPanel.removeAttribute('hidden');
  currentButton.setAttribute('aria-expanded', 'true');
};
Enter fullscreen mode Exit fullscreen mode
  1. Lastly create the closeCurrentPanel() function.
const closeCurrentPanel = (currentButton, currentPanel) => {
  currentPanel.setAttribute('hidden', '');
  currentButton.setAttribute('aria-expanded', 'false');
};
Enter fullscreen mode Exit fullscreen mode
  1. It's not finished yet! I could move the accordionPanels to live inside the closeAllOpenedPanel() function, since it's the only function that used accordionPanels. By doing this, I reduced the global variable. It makes my code more maintainable and also it's a good practice 👍.
const closeAllOpenedPanel = () => {
  const accordionPanels = document.querySelectorAll(
    '.js-accordionPanel');

  // The rest of the code still the same
};
Enter fullscreen mode Exit fullscreen mode

And finally! The result:

result


That's really cool!

Thanks!

Thank you everyone for reading it until this point. Hopefully this is helpful, especially for those of you who are currently doing this challenge. If you notice any mistakes or have feedback, feel free to write it down.

Thanks

Discussion (0)