Accordion

Roadmap

  • Add background options.

Accordions

Component Preview
<div class="accordion
  " role="tablist" aria-multiselectable="false">
      <!-- Use the accurate heading level to maintain the document outline -->
      <h2 id="chocolate_chip" class="accordion__heading">
          <button class="accordion__button" role="tab" aria-selected="true" aria-expanded="true" aria-controls="single-select-0">
              Chocolate Chip Cookie
              <i aria-hidden="true" focusable="false" class="fas fa-chevron-up"></i>
          </button>
      </h2>
      <div id="single-select-0" aria-labelledby="chocolate_chip" class="accordion__content bg--white">
          <p>Among the most popular of all cookie types, the chocolate chip cookie's invention was a happy accident. In 1930, Ruth Graves Wakefield, who ran the Toll House Inn in Whitman, Massachusetts, ran out of baker's chocolate and substituted for it with pieces of Nestle's® semi-sweet chocolate. </p>

      </div>
      <!-- Use the accurate heading level to maintain the document outline -->
      <h2 id="sugar" class="accordion__heading">
          <button class="accordion__button" role="tab" aria-selected="false" aria-expanded="false" aria-controls="single-select-1">
              Sugar Cookie
              <i aria-hidden="true" focusable="false" class="fas fa-chevron-up"></i>
          </button>
      </h2>
      <div id="single-select-1" aria-labelledby="sugar" class="accordion__content bg--white">
          <p>The sugar cookie is like the vanilla ice cream of cookies—everyone likes it but few claim it as their favorite. Basic ingredients like sugar, flour, butter, eggs, and vanilla make up this popular cookie type.</p>

      </div>
      <!-- Use the accurate heading level to maintain the document outline -->
      <h2 id="snickerdoodle" class="accordion__heading">
          <button class="accordion__button" role="tab" aria-selected="false" aria-expanded="false" aria-controls="single-select-2">
              Snickerdoodle Cookies
              <i aria-hidden="true" focusable="false" class="fas fa-chevron-up"></i>
          </button>
      </h2>
      <div id="single-select-2" aria-labelledby="snickerdoodle" class="accordion__content bg--white">
          <p>Although the origin of this beloved cookie is up for debate, there's no doubt it's a favorite during the holidays. Snickerdoodles are a type of drop cookie (any cookie that is formed by dropping spoonfuls of dough directly onto a baking sheet) that is coated in cinnamon and sugar. </p>

      </div>
      <!-- Use the accurate heading level to maintain the document outline -->
      <h2 id="oatmeal" class="accordion__heading">
          <button class="accordion__button" role="tab" aria-selected="false" aria-expanded="false" aria-controls="single-select-3">
              Oatmeal Raisin
              <i aria-hidden="true" focusable="false" class="fas fa-chevron-up"></i>
          </button>
      </h2>
      <div id="single-select-3" aria-labelledby="oatmeal" class="accordion__content bg--white">

          <p>Lorem ipsum dolor sit amet. Aut quia odio eum esse consequatur et dolor similique At consequuntur asperiores ut eius voluptas. Qui officiis modi eum possimus iusto eum quam eaque. Est aspernatur officiis a porro rerum eum nihil sint est iure quidem qui dicta cumque ex omnis temporibus. Eum iste pariatur et expedita unde qui vitae possimus nam voluptas esse aut ullam quam. Eum tempora fugit et fugit recusandae sed ipsa corrupti et labore asperiores in fuga atque est amet aliquid ut nihil animi.</p>

          <p>Vel laboriosam magni vel accusamus sint eum neque rerum et similique blanditiis est voluptatibus voluptas ea fugiat quas. Qui laudantium minima aut iure totam ut quibusdam dolorem rem dolor accusamus eum reiciendis ipsa qui facere nisi non ratione quia. Vel exercitationem optio sed eaque quisquam in voluptatem dolorem sed voluptas voluptas est ratione tenetur. Sit veritatis error <a href="https://www.loremipzum.com" target="_blank">Cum ipsam et veritatis similique et sapiente velit</a>. At repudiandae nisi 33 galisum quia est voluptatem odit ut placeat omnis sit impedit voluptatem.</p>

          <blockquote>
              <p>Sit veritatis error <a href="https://www.loremipzum.com" target="_blank">Cum ipsam et veritatis similique et sapiente velit</a>. At repudiandae nisi 33 galisum quia est voluptatem odit ut placeat omnis sit impedit voluptatem.</p>
          </blockquote>

          <p>Et veniam odit aut consequatur illum <a href="https://www.loremipzum.com" target="_blank">Aut reiciendis et adipisci laboriosam qui omnis culpa aut repudiandae sapiente</a>. Ut quae dolor qui odit fuga eos laboriosam reiciendis sed laudantium accusantium. Est minus sint eum porro adipisci qui sunt ipsum. Qui odio Quis ut saepe laborum et dolores animi aut esse necessitatibus? Quo dolores sunt et adipisci consectetur id enim suscipit. Aut maiores officiis et galisum minima id aliquid ullam. Et consequuntur cupiditate ut placeat velit ut inventore neque ab suscipit natus qui quaerat voluptatem. Et esse suscipit est maiores delectus et placeat quia in dolorum fuga. Est fugit odit est fugiat dolores qui error quia est incidunt quis sed repudiandae asperiores et internos quia!</p>

          <ul>
              <li>Vel exercitationem optio sed eaque quisquam in voluptatem dolorem sed voluptas voluptas est ratione tenetur. Sit veritatis error <a href="https://www.loremipzum.com" target="_blank">Cum ipsam et veritatis similique et sapiente velit</a>. At repudiandae nisi 33 galisum quia est voluptatem odit ut placeat omnis sit impedit voluptatem.</li>
              <li>Et veniam odit aut consequatur illum <a href="https://www.loremipzum.com" target="_blank">Aut reiciendis et adipisci laboriosam qui omnis culpa aut repudiandae sapiente</a>. Ut quae</li>
          </ul>
          <ol>
              <li>Vel exercitationem optio sed eaque quisquam in voluptatem dolorem sed voluptas voluptas est ratione tenetur. Sit veritatis error <a href="https://www.loremipzum.com" target="_blank">Cum ipsam et veritatis similique et sapiente velit</a>. At repudiandae nisi 33 galisum quia est voluptatem odit ut placeat omnis sit impedit voluptatem.</li>
              <li>Et veniam odit aut consequatur illum <a href="https://www.loremipzum.com" target="_blank">Aut reiciendis et adipisci laboriosam qui omnis culpa aut repudiandae sapiente</a>. Ut quae</li>
          </ol>
          <p>&nbsp;</p>

      </div>
  </div>
  • Content:
    .accordion .accordion__heading {
      margin: 0;
      margin-top: 1rem;
      font-size: 1rem;
      font-weight: 700; }
      .accordion .accordion__heading:not(:first-child) {
        margin-top: 1rem; }
      .accordion .accordion__heading button {
        all: inherit;
        font-size: 1.2rem;
        width: 100%;
        background-color: #edeceb;
        color: var(--brand-secondary);
        padding: 1.05rem;
        display: flex;
        justify-content: space-between;
        transition: all 0.2s ease-in-out;
        transition-property: background-color;
        cursor: pointer; }
        .accordion .accordion__heading button:focus {
          outline: 5px auto -webkit-focus-ring-color; }
        .accordion .accordion__heading button i, .accordion .accordion__heading button svg {
          color: currentColor;
          transform: rotate(-180deg) translate(0px, -0.1em);
          transition: all 0.3s ease-in-out;
          transition-property: transform, background-color;
          background-color: transparent;
          width: 30px !important;
          height: 30px;
          padding: 4px;
          display: flex;
          justify-content: center;
          align-items: center;
          margin: -0.3rem 0;
          border-radius: 50%; }
        .accordion .accordion__heading button:hover, .accordion .accordion__heading button:focus {
          background-color: #e3e2e0; }
          .accordion .accordion__heading button:hover i, .accordion .accordion__heading button:focus i {
            transform: rotate(-180deg) translate(0px, -0.2em); }
          .accordion .accordion__heading button:hover[aria-expanded="true"] i, .accordion .accordion__heading button:hover[aria-expanded="true"] svg, .accordion .accordion__heading button:focus[aria-expanded="true"] i, .accordion .accordion__heading button:focus[aria-expanded="true"] svg {
            transform: rotate(0deg) translate(0px, 0em); }
        .accordion .accordion__heading button[aria-expanded="true"] i, .accordion .accordion__heading button[aria-expanded="true"] svg {
          transform: rotate(0deg) translate(0px, 0.1em);
          background-color: #fafafa; }
    
    .accordion .accordion__content {
      padding: 1.05rem;
      border: 1px solid #edeceb; }
    
  • URL: /components/raw/accordion/accordion.css
  • Filesystem Path: src/components/accordion/accordion.css
  • Size: 2.1 KB
  • Content:
    (function () {
      function Accordion(element) {
        let thisAccordion = this;
    
        // Get the accordions, and if the accordion group is multiselectable.
        this.accordions = element.getElementsByClassName("accordion__heading");
        this.multiSelectible = element.getAttribute('aria-multiselectable') === 'true' || false;
    
        // For each of the accordions...
        for (let i = 0; i < this.accordions.length; i++) {
    
          // Get the accordion item's components.
          let itemComponents = this.accordionItemComponents(this.accordions[i]);
    
          // Check if the accordion is currently expanded at moment of click.
          let expanded = this.isAccordionOpen(itemComponents.btn);
    
          // If it is, un-hide its corresponding panel.
          itemComponents.panel.hidden = !expanded;
    
          // When the accordion's button is clicked...
          itemComponents.btn.onclick = () => {
    
            // Toggle the corresponding accordion.
            this.toggleAccordion(this.accordions[i]);
          }
        }
    
        // Add a listener that listens for when the URL is changed.
        window.addEventListener('popstate', function (event) {
    
          // Activate an accordion based upon the hash parameters in the URL.
          thisAccordion.activateAccordionByHash();
        });
    
        // Activate any accordion that is defined in the hash parameter if there is one.
        this.activateAccordionByHash();
      }
    
      // Gets the item components for 'accordion'.
      // Returns an object that contains 'btn' and 'panel' elements.
      Accordion.prototype.accordionItemComponents = function (accordion) {
        let btn = accordion.querySelector('button');
        let panel = accordion.nextElementSibling;
    
        return {
          'btn': btn,
          'panel': panel
        }
      }
    
      // Define whether 'accordion' is open with 'isOpen'.
      Accordion.prototype.accordionOpen = function (accordion, isOpen) {
        // Get the accordion item's components.
        let itemComponents = this.accordionItemComponents(accordion);
    
        // Set the relevant attributes for 'accordion' based on 'isOpen'.
        itemComponents.btn.setAttribute('aria-expanded', isOpen);
        itemComponents.btn.setAttribute('aria-selected', isOpen);
        itemComponents.panel.hidden = !isOpen;
      }
    
      // Activate an 'accordion'.
      Accordion.prototype.activateAccordion = function (accordion) {
    
        // Checks if multiple accordions can be open at once. If not, closes other accordions.
        if (!this.multiSelectible) {
          this.collapseAllAccordions();
        }
    
        // Open the accordion.
        this.accordionOpen(accordion, true);
      }
    
      // Activate any accordion that is defined in the hash parameter if there is one.
      Accordion.prototype.activateAccordionByHash = function () {
    
        // Get the hash parameter.
        let hash = window.location.hash.substr(1);
    
        // If the hash parameter is not empty...
        if (hash !== '') {
    
          // Get the accordion to focus.
          let accordionToFocus = document.getElementById(hash);
    
          // If the defined hash parameter finds an element...
          if (accordionToFocus !== null) {
    
            // Get the accordion wrapper of the hash parameter and this accordion wrapper to compare later.
            let accordionToFocusAccordionWrapper = accordionToFocus.parentElement
            let accordionWrapper = this.accordions[0].parentElement;
    
            // If the accordion wrapper defined by the hash and this accordion wrapper are the same...
            if (accordionToFocusAccordionWrapper === accordionWrapper) {
    
              // Activate the accordion defined in the hash parameters.
              this.activateAccordion(accordionToFocus);
            }
          }
        }
      }
    
      // Collapse all accordions in this accordion group.
      Accordion.prototype.collapseAllAccordions = function () {
    
        // For each accordion...
        for (let i = 0; i < this.accordions.length; i++) {
    
          // Close it.
          this.accordionOpen(this.accordions[i], false);
        }
      }
    
      // Check if an accordion is open by inspecting the aria attribute of the 'btn' controlling it.
      // Returns a boolean.
      Accordion.prototype.isAccordionOpen = function (btn) {
        return btn.getAttribute('aria-expanded') === 'true' || false;
      }
    
      // Toggle a specific 'accordion' open or closed.
      Accordion.prototype.toggleAccordion = function (accordion) {
        // Get the accordion's button element.
        let btn = accordion.querySelector('button');
    
        // Check if the accordion is currently expanded at moment of click.
        let expanded = this.isAccordionOpen(btn);
    
        // Checks if multiple accordions can be open at once. If not, closes other accordions.
        if (!this.multiSelectible && !expanded) {
          this.collapseAllAccordions();
        }
    
        // Toggle the accordion.
        this.accordionOpen(accordion, !expanded)
    
        // If the accordion is not open (but will be)...
        if (!expanded) {
    
          // Define historyString here to be used later.
          let historyString = '#' + btn.parentElement.id;
    
          // Change window location to add URL params
          if (window.history && history.pushState && historyString !== '#') {
            // NOTE: doesn't take into account existing params
            history.replaceState("", "", historyString);
          }
        }
    
        // Else if the accordion is closed...
        else {
    
          // Empty the history string.
          history.replaceState("", "", " ");
        }
      }
    
      // Instantiate accordions on the page.
      const accordions = document.getElementsByClassName("accordion");
    
      for (let i = 0; i < accordions.length; i++) {
        let accordion = new Accordion(accordions[i]);
      }
    }());
    
    
  • URL: /components/raw/accordion/accordion.js
  • Filesystem Path: src/components/accordion/accordion.js
  • Size: 5.5 KB
  • Content:
    @import '../../assets/scss/variables';
    /////// Accordions
    .accordion {
      .accordion__heading {
        margin: 0;
        margin-top: 1rem;
        font-size: 1rem;
        font-weight: $font-weight-bold;
    
        &:not(:first-child) {
          margin-top: 1rem;
        }
    
        button {
          all: inherit;
          font-size: 1.2rem;
          width: 100%;
          background-color: #edeceb;
          color: $secondary;
          padding: $md;
          display: flex;
          justify-content: space-between;
          transition: all 0.2s ease-in-out;
          transition-property: background-color;
          cursor: pointer;
    
          &:focus {
            outline: 5px auto -webkit-focus-ring-color;
          }
    
          i, svg {
            color: currentColor;
            transform: rotate(-180deg) translate(0px, -0.1em);
            transition: all 0.3s ease-in-out;
            transition-property: transform, background-color;
            background-color: transparent;
            width: 30px !important;
            height: 30px;
            padding: 4px;
            display: flex;
            justify-content: center;
            align-items: center;
            margin: -0.3rem 0;
            border-radius: 50%;
          }
    
          &:hover, &:focus {
            background-color: darken(#edeceb, 4%);
    
            i {
              transform: rotate(-180deg) translate(0px, -0.2em);
            }
    
            &[aria-expanded="true"] i, &[aria-expanded="true"] svg {
              transform: rotate(0deg) translate(0px, 0em);
            }
          }
    
          &[aria-expanded="true"] i, &[aria-expanded="true"] svg {
            transform: rotate(0deg) translate(0px, 0.1em);
            background-color: #fafafa;
          }
        }
      }
    
      .accordion__content {
        padding: $md;
        border: 1px solid #edeceb;
      }
    }
    
  • URL: /components/raw/accordion/accordion.scss
  • Filesystem Path: src/components/accordion/accordion.scss
  • Size: 1.7 KB