-
-
Save nichoth/5e6cebe043835cfe2b1d21613f4fa5d5 to your computer and use it in GitHub Desktop.
Watch this tutorial: https://youtu.be/2k-iYzWZu2w
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
accordion-group { | |
background-color: #f7f7f7; | |
border-radius: 0.25em; | |
display: block; | |
margin-block-end: 1.5em; | |
padding: 0.5em 1em; | |
width: 100%; | |
} | |
accordion-group [accordion-trigger] { | |
background: transparent; | |
border: 0; | |
cursor: pointer; | |
display: block; | |
font: inherit; | |
margin: 0; | |
padding: 0; | |
width: 100%; | |
text-align: start; | |
} | |
accordion-group [accordion-trigger][aria-expanded="true"]::after { | |
content: " -"; | |
} | |
accordion-group [accordion-trigger][aria-expanded="false"]::after { | |
content: " +"; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
customElements.define('accordion-group', class extends HTMLElement { | |
/** | |
* The class constructor object | |
*/ | |
constructor () { | |
// Gives element access to the parent class properties | |
super(); | |
// Get headings | |
this.headings = this.querySelectorAll(this.getAttribute('headings')); | |
if (!this.headings.length) return; | |
// Define if exclusive accordion or not | |
this.exclusive = this.hasAttribute('exclusive'); | |
// Setup the DOM | |
this.setup(); | |
// Listen for events | |
this.addEventListener('click', this); | |
} | |
/** | |
* Handle events on the Web Component | |
* @param {Event} event The event object | |
*/ | |
handleEvent (event) { | |
// Get the clicked trigger button | |
const btn = event.target.closest('[accordion-trigger]'); | |
if (!btn) return; | |
// Should accordion be hidden or expanded? | |
const isHidden = btn.getAttribute('aria-expanded') === 'true'; | |
// Toggle the accordion | |
this.toggleAccordion(btn, isHidden); | |
// If exclusive, close all other open accordions | |
if (!this.exclusive) return; | |
const triggers = this.querySelectorAll('[accordion-trigger][aria-expanded="true"]'); | |
for (const trigger of triggers) { | |
if (trigger === btn) continue; | |
this.toggleAccordion(trigger, true); | |
} | |
} | |
/** | |
* Toggle the accordion pane | |
* @param {Element} btn The accordion trigger | |
* @param {Boolean} isHidden If true, the content be hidden | |
*/ | |
toggleAccordion (btn, isHidden) { | |
// Get the associated content | |
const content = this.querySelector(`#${btn.getAttribute('aria-controls')}`); | |
// Show the content and update ARIA | |
btn.setAttribute('aria-expanded', isHidden ? 'false' : 'true'); | |
content.toggleAttribute('hidden', isHidden); | |
} | |
/** | |
* Setup the DOM on initial load | |
*/ | |
setup () { | |
for (const heading of this.headings) { | |
// Create toggle button | |
const btn = document.createElement('button'); | |
btn.setAttribute('accordion-trigger', ''); | |
btn.innerHTML = heading.innerHTML; | |
heading.innerHTML = ''; | |
heading.append(btn); | |
// Get content and hide it | |
const content = heading.nextElementSibling; | |
content.setAttribute('hidden', ''); | |
// Define an ID if one is missing | |
if (!content.id) { | |
content.id = `accordion-group_${crypto.randomUUID()}`; | |
} | |
// Add ARIA attributes | |
btn.setAttribute('aria-expanded', false); | |
btn.setAttribute('aria-controls', content.id); | |
} | |
} | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Accordions</title> | |
<style type="text/css"> | |
body { | |
margin: 1em auto; | |
max-width: 30em; | |
width: 88%; | |
} | |
</style> | |
<link rel="stylesheet" type="text/css" href="accordion-group.css"> | |
</head> | |
<body> | |
<h1>Accordions</h1> | |
<accordion-group headings="h2"> | |
<h2>Yo, ho ho!</h2> | |
<div>Yo, ho ho and a bottle of rum!</div> | |
<h2>Ahoy, there!</h2> | |
<div>Ahoy there, matey!</div> | |
</accordion-group> | |
<accordion-group headings="h2" exclusive> | |
<h2>Yo, ho ho!</h2> | |
<div>Yo, ho ho and a bottle of rum!</div> | |
<h2>Ahoy, there!</h2> | |
<div>Ahoy there, matey!</div> | |
</accordion-group> | |
<script src="accordion-group.js"></script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment