A WAI-ARIA friendly accordion component.
Note: The accordion has been refactored and is not compatible with accordion prior to version 0.9.13
An accordion component is a collection of expandable panels associated with a common outer container. Panels consist of a tab header and an associated content region or panel. The primary use of an Accordion is to present multiple sections of content on a single page without scrolling, where all of the sections are peers in the application or object hierarchy. The general look is similar to a tree where each root tree node is an expandable accordion header. The user navigates and makes the contents of each panel visible (or not) by interacting with the Accordion tab header.
1. Code a <ul>
element with class="mdlext-accordion mdlext-js-accordion mdlext-accordion--horizontal"
to hold the accordion with horizontal layout.
<ul class="mdlext-accordion mdlext-js-accordion mdlext-accordion--horizontal"> </ul>
2. Code a <li>
element with class="mdlext-accordion__panel"
to hold an individual accordion panel.
<ul class="mdlext-accordion mdlext-js-accordion mdlext-accordion--horizontal"> <li class="mdlext-accordion__panel"> </li> </ul>
3. Code a <header>
element with class="mdlext-accordion__tab"
to hold the accordion tab header.
<ul class="mdlext-accordion mdlext-js-accordion mdlext-accordion--horizontal"> <li class="mdlext-accordion__panel"> <header class="mdlext-accordion__tab"> </header> </li> </ul>
4. Code a <span>
element with class="mdlext-accordion__tab__caption"
to hold the accordion tab header caption.
<ul class="mdlext-accordion mdlext-js-accordion mdlext-accordion--horizontal"> <li class="mdlext-accordion__panel"> <header class="mdlext-accordion__tab"> <span class="mdlext-accordion__tab__caption">A tab caption</span> </header> </li> </ul>
5. Code a <section>
element with class="mdlext-accordion__tabpanel"
to hold the tab content.
<ul class="mdlext-accordion mdlext-js-accordion mdlext-accordion--horizontal"> <li class="mdlext-accordion__panel"> <header class="mdlext-accordion__tab"> <span class="mdlext-accordion__tab__caption">A tab caption</span> </header> <section class="mdlext-accordion__tabpanel"> <p>Content goes here ...</p> </section> </li> </ul>
6. Repeat steps 2..5 for each accordion panel required.
Multiselectable vertical accordion with three panels, aria attributes, ripple effect on each tab header, decorated with a glyph left and a state icon right. Tab #1 is open at page load (aria-expanded="true"). Subscribes to accordion toggle event.
<ul id="my-accordion" class="mdlext-accordion mdlext-js-accordion mdlext-accordion--vertical mdlext-js-ripple-effect" role="tablist" aria-multiselectable="true"> <li class="mdlext-accordion__panel" role="presentation"> <header class="mdlext-accordion__tab" role="tab" aria-expanded="true"> <i class="material-icons">dns</i> <span class="mdlext-accordion__tab__caption">First section. A long caption should not push the state icon</span> <i class="mdlext-aria-toggle-material-icons"></i> </header> <section class="mdlext-accordion__tabpanel" role="tabpanel" aria-hidden="false"> <h5>Content #1 goes here</h5> <p>Some content <a href="#">with an anchor</a> as a focusable element.</p> </section> </li> <li class="mdlext-accordion__panel" role="presentation"> <header class="mdlext-accordion__tab" role="tab" aria-expanded="false"> <i class="material-icons">all_inclusive</i> <span class="mdlext-accordion__tab__caption">Tab #2</span> <i class="mdlext-aria-toggle-material-icons"></i> </header> <section class="mdlext-accordion__tabpanel" role="tabpanel" aria-hidden="true" hidden> <h5>Content #2 goes here</h5> <p>Some content....</p> </section> </li> <li class="mdlext-accordion__panel" role="presentation"> <header class="mdlext-accordion__tab" role="tab" aria-expanded="false"> <i class="material-icons">build</i> <span class="mdlext-accordion__tab__caption">Tab #3</span> <i class="mdlext-aria-toggle-material-icons"></i> </header> <section class="mdlext-accordion__tabpanel" role="tabpanel" aria-hidden="true" hidden> <h5>Content #3 goes here</h5> </section> </li> </ul> <script> 'use strict'; window.addEventListener('load', function() { var accordion = document.querySelector('#my-accordion'); accordion.addEventListener('toggle', function(e) { console.log('Accordion toggled. State:', e.detail.state, 'Source:', e.detail.tab); }); }); </script>
Note: All required aria attributes will be added by the accordion component during initialization - so it is not strictly necessary to apply the attributes in markup.
The accordion interacts with the following keyboard keys.
Interaction with the component programmatically is performed receiving events from the component or by sending events to the component (or by using the public api).
A client can send a command
custom event to the accordion. The command event holds a detail object defining the action to perform and a target for the action.
The detail object has the following structure:
detail: { action, // "open", "close", "toggle" or "upgrade" target // Target, panel or tab, of action, "undefined" if all panels should be targeted. // Note: If you send a null target, the action is cancelled }
Possible actions are:
Open a targeted tab and it's corresponding tabpanel.
myAccrdion = document.querySelector('#my-accordion'); target = myAccordion.querySelector('#my-accordion .mdlext-accordion__panel:nth-child(3)'); ce = new CustomEvent('command', { detail: { action : 'open', target: target } });
If target
is undefined, the action will open all panels. Note: Opening all panels only makes sense if the accordion has the aria attribute aria-multiselectable
set to true
, and will be cancelled otherwise.
Close a targeted tab and its corresponding tabpanel.
myAccrdion = document.querySelector('#my-accordion'); target = myAccordion.querySelector('#my-accordion .mdlext-accordion__panel:nth-child(3)'); ce = new CustomEvent('command', { detail: { action : 'close', target: target } });
If target
is undefined, the action will close all panels. Note: Closing all panels only makes sense if the accordion has the aria attribute aria-multiselectable
set to true
, and will be cancelled otherwise.
Toggle a targeted tab. Open or close a targeted tab and it's corresponding tabpanel.
myAccrdion = document.querySelector('#my-accordion'); target = myAccordion.querySelector('#my-accordion .mdlext-accordion__panel:nth-child(3)'); ce = new CustomEvent('command', { detail: { action : 'toggle', target: target } });
If target
is undefined, the action will be cancelled.
Upgrade a targeted panel. If you add a panel to the accordion after the page has loaded, you must call upgrade
to notify the accordion component about the new panel.
myAccrdion = document.querySelector('#my-accordion'); addedPanel = myAccordion.querySelector('#my-accordion .mdlext-accordion__panel:nth-child(4)'); ce = new CustomEvent('command', { detail: { action : 'upgrade', target: addedPanel } });
If target
is undefined, the action will be cancelled.
var ce = new CustomEvent( 'command', { detail: { action: 'open' } }); document.querySelector('#my-accordion').dispatchEvent(ce);
var panel3 = document.querySelector('#my-accordion .mdlext-accordion__panel:nth-child(3) .mdlext-accordion__tab'); var ce = new CustomEvent('command', { detail: { action: 'toggle', target: panel3 } }); document.querySelector('#my-accordion').dispatchEvent(ce);
var panel = '<li class="mdlext-accordion__panel">' + '<header class="mdlext-accordion__tab" aria-expanded="true">' + '<span class="mdlext-accordion__tab__caption">New Tab</span>' + '<i class="mdlext-aria-toggle-material-icons"></i>' + '</header>' + '<section class="mdlext-accordion__tabpanel">' + '<h5>New tab content</h5>' + '<p>Some content</p>' + '</section>' +'</li>'; var accordion = document.querySelector('#my-accordion'); accordion.insertAdjacentHTML('beforeend', panel); var theNewPanel = document.querySelector('#my-accordion .mdlext-accordion__panel:last-child'); var ce = new CustomEvent('command', { detail: { action : 'upgrade', target: theNewPanel } }); document.querySelector('#my-accordion').dispatchEvent(ce);
Refer to snippets/accordion.html or the tests for detailed usage.
The accordion emits a custom toggle
event when a panel opens or closes. The event has a detail object with the following structure:
detail: { state, // "open" or "close" tab, // the haeder tab element instance that caused the event tabpanel // the cooresponding tabpanel element instance }
Set up an event listener to receive the toggle event.
document.querySelector('#my-accordion').addEventListener('toggle', function(e) { console.log('Accordion toggled. State:', e.detail.state, 'Source:', e.detail.source); });
Refer to snippets/accordion.html or the tests for detailed usage.
Upgrade a targeted panel with aria attributes and ripple effects. If you add a panel to the accordion after the page has loaded, you must call upgrade
to notify the accordion component about the newly added panel.
var accordion = document.querySelector('#my-accordion'); var panel3 = document.querySelector('#my-accordion .mdlext-accordion__panel:nth-child(3)'); accordion.MaterialExtAccordion.upgradeTab( panel3 );
Executes an action, targeting a specific tab. The actions corresponds to the custom events defined for this component.
The detail object parameter has the following structure:
detail: { action, // "open", "close", "toggle" or "upgrade" target // Target, panel or tab, of action, "undefined" if all panels should be targeted. // Note: If you send a null target, the action is cancelled }
Open a targeted tab and it's corresponding tabpanel.
Close a targeted tab and it's corresponding tabpanel.
Toggle a targeted tab. Open or close a targeted tab and it's corresponding tabpanel.
Upgrade a targeted panel with aria attributes and ripple effects. If you add a panel to the accordion after the page has loaded, you must call upgrade
to notify the accordion component about the newly added panel.
var accordion = document.querySelector('#my-accordion'); accordion.MaterialExtAccordion.command( {action: 'open'} );
var accordion = document.querySelector('#my-accordion'); var panel3 = document.querySelector('#my-accordion .mdlext-accordion__panel:nth-child(3) .mdlext-accordion__tab'); accordion.MaterialExtAccordion.command( {action: 'toggle', target: panel3} );
Refer to snippets/accordion.html or the tests for detailed usage.
The MDLEXT CSS classes apply various predefined visual and behavioral enhancements to the accordion. The table below lists the available classes and their effects.
MDLEXT class | Effect | Remarks |
---|---|---|
mdlext-accordion | Defines container as an MDL component | Required on "outer" <div> or <ul> element |
mdlext-js-accordion | Assigns basic MDL behavior to accordion | Required on "outer" <div> or <ul> element |
mdlext-accordion--horizontal | Horizontal layot of an accordion | Required. The accordion must have one of mdlext-accordion--horizontal or mdlext-accordion--vertical defined |
mdlext-accordion--vertical | Vertical layot of an accordion | Required. The accordion must have one of mdlext-accordion--horizontal or mdlext-accordion--vertical defined |
mdlext-js-ripple-effect | Applies ripple click effect to accordion tab header | Optional. Goes on "outer" <ul> or <div> element |
mdlext-js-animation-effect | Applies animation effect to accordion tab panel | Optional. Goes on "outer" <ul> or <div> element |
mdlext-accordion__panel | Defines a container for each section of the accordion - the tab and tabpanel element | Required on first inner <div> element or <li> element |
mdlext-accordion__tab | Defines a tab header for a corresponding tabpanel | Required on <header> or <div> element |
mdlext-accordion__tabpanel | The content | Required on <section> or <div> element |
The table below lists available attributes and their effects.
Attribute | Description | Remarks |
---|---|---|
aria-multiselectable | If true, multiple panels may be open simultaneously | Required. Add aria-multiselectable="true" to the mdlext-accordion element to keep multiple panels open at the same time. If not present, the component will set aria-multiselectable="false" during initialization. |
role=tablist | Component role | Required. Added by component during initialization if not present. |
role=presentation | Accordion panel role | Required. Added by component during initialization if not present. |
role=tab | Accordion tab header role | Required. Added by component during initialization if not present. |
aria-expanded | Accordion tab header attribute. An accordion should manage the expanded/collapsed state of each tab by maintain its aria-expanded state. | Required. Defaults to aria-expanded="false" . Set aria-expanded="true" if you want a tab to open during page load. |
aria-selected | Accordion tab header attribute. An accordion should manage the selected state of each tab by maintaining its aria-selected state | Optional. Added by component. |
disabled | Accordion tab header attribute. Indicates a disabled tab and tabpanel | Optional. If this attribute is present, the tabpanel will not open or close. |
role=tabpanel | Accordion tabpanel role. | Required. Added by component during initialization if not present. |
aria-hidden | Accordion tabpanel attribute. An accordion should convey the visibility of each tabpanel by maintaining its aria-hidden state | Required. Added by component. |
hidden | Accordion tabpanel attribute. | Required. Added by component if aria-hidden="true" . |