Tabcordion¶
A responsive and accessible solution for tabs for a tab / accordion hybrid implementation.
Some notable features supported by the extension:
- Keyboard support
- Accordion-like display that can be explicitly set or auto detected based on screen width
- Automatic scroll to panel behavior
- Automatic window history state replacement when activating panels
- Robust API including the ability to programmatically show / hide panels, set the initial active panel, customize the scroll to panel behavior, and much more!
Installation¶
Note: This class is pre-installed and loaded asynchronously with Genesis out of the box in the PROD.js file. The extension styling is loaded in when the Tabcordion class is imported.
Import the Tabcordion extension class in your desired JavaScript file.
import {Tabcordion} from 'extensions/tabs';
Example Usage¶
Product Page Setup¶
A tabcordion set includes:
- A tab control for the associated panel
- An accordion control for the associated panel
- The associated panel containing the main content
By default, the product page tabcordions include the product description as the first tabcordion set if the description value is not empty. Additional tabcordion sets are loaded from the tabs custom field group. This custom field group will need to be created if it is not already present and all product custom fields to be utilized as tabs assigned to the group.
The tab and accordion control titles will correlate to the custom field Name, however, this can be adjusted if needed in the template code. Additional template adjustments can be made to load in and customize the desired tabcordion sets by configuring the l.settings:product:tabs variable to suit your needs. The l.settings:product:tabs variable is an array of structures that support the following members:
:code- Used for generate the HTMLidattributes for the elements in each tabcordion set.:name- Used for the tab and accordion control titles.:value- Used for the panel content.
.mvt¶
Add the tabcordion pattern markup resembling the HTML structure shown below. See the notes below the example HTML that correlate to the comments for more details on the structure.
<!-- [1] -->
<article class="g-tabcordion">
<!-- [2] -->
<div class="g-tabcordion__tabs">
<!-- [3] -->
<button type="button" id="tab-list-descrip" class="g-tabcordion__tab is-active" aria-expanded="true" aria-controls="panel-descrip">
<h2 class="g-tabcordion__tab-title">Description</h2>
</button>
<button type="button" id="tab-list-prod_tab1" class="g-tabcordion__tab" aria-expanded="false" aria-controls="panel-prod_tab1">
<h2 class="g-tabcordion__tab-title">Product Tab 1</h2>
</button>
</div>
<!-- [4] -->
<div id="tab-list-descrip-accordion-control" class="g-tabcordion__accordion-control is-active" aria-expanded="true" aria-controls="panel-descrip">
<h2 class="g-tabcordion__tab-title">Description</h2>
<span class="g-tabcordion__accordion-control-icon" aria-hidden="true"></span>
</div>
<!-- [5] -->
<div id="panel-descrip" class="g-tabcordion__panel is-active" role="region" aria-labelledby="tab-list-descrip tab-list-descrip-accordion-control">
<!-- [6] -->
<div class="g-tabcordion__panel-content">I come from a land down under</div>
</div>
<div id="tab-list-prod_tab1-accordion-control" class="g-tabcordion__accordion-control" aria-expanded="false" aria-controls="panel-prod_tab1">
<h2 class="g-tabcordion__tab-title">Product Tab 1</h2>
<span class="g-tabcordion__accordion-control-icon" aria-hidden="true"></span>
</div>
<div id="panel-prod_tab1" class="g-tabcordion__panel" role="region" aria-labelledby="tab-list-prod_tab1 tab-list-prod_tab1-accordion-control">
<div class="g-tabcordion__panel-content">
Product Tab 1 content...
</div>
</div>
</article>
- This is the root container for the tab content and is targeted by the extension styling. This is also the container element that must be passed in as the first parameter for the
Tabcordionclass. - The
g-tabcordion__tabsclass indicates that the element serves as the container for the set of tabs (tab list). This element's width is also targeted when theaccordionModesetting is set toauto. Each element with the
g-tabcordion__tabclass within the tab list indicates the element serves as a tab control. The associated panel is linked by its ownidattribute that matches thearia-controlsattribute value on the tab control element.The default active tab control must contain the
is-activeclass or set to the class specified by thetabActiveClassconfiguration setting. Additionally, the active tab control must have itsaria-expandedattribute set totrue. All other tab control elements must have aaria-expandedattribute set tofalse.Each element with the
g-tabcordion__accordion-controlclass indicates the elements serves as an accordion control. The associated panel is linked by its ownidattribute that matches thearia-controlsattribute value on the accordion control element.The default active accordion control must contain the
is-activeclass or set to the class specified by thetabActiveClassconfiguration setting. Additionally, the active accordion control must have itsaria-expandedattribute set totrue. All other accordion control elements must have aaria-expandedattribute set tofalse.- Each tab panel element must have an
idattribute and arole="region"attribute in conjunction with thearia-labelledbyattribute to indicate the element serves as a container for the panel content and is associated properly to its control elements. Thearia-labelledbyvalue is a space separated value containing theidattributes for each of the panel's control elements. - The panel content is placed within an element with the
g-tabcordion__panel-contentclass.
.js¶
After loading in the Tabcordion class, initialize the class by passing the root container element as the first parameter.
Preferred asynchronous initialization:
(async () => {
const productTabs = document.getElementsByClassName('g-tabcordion');
if (!productTabs.length) {
return;
}
const {Tabcordion} = await import('extensions/tabs');
for (const tab of productTabs) {
new Tabcordion(tab);
}
})();
Alternatively:
import {Tabcordion} from 'extensions/tabs';
for (const tab of document.getElementsByClassName('g-tabcordion')) {
new Tabcordion(tab);
}
Options¶
The Tabcordion class can take an optional configuration object for the second parameter to override any of the default configuration settings.
The following table defines the available configuration options:
| Name | Type | Description | Default Value |
|---|---|---|---|
| accordionActiveClass | String | Accordion mode class name. | 'is-accordion' |
| accordionMode | String|Integer | Accordion mode setting that controls when the tabs display like an accordion. This can be set to 'auto' to automatically detect and switch to the accordion view when the width of the tabs exceeds the container width. An integer value can also be provided to explicitly set the width to switch to the accordion view. |
'auto' |
| hashOptions | Object | Configuration object for URL hash features. If overriding the default object, you MUST provide all properties listed below. | See following properties below for default values. |
| hashOptions.enabled | Boolean | Flag to determine if URL hash features are enabled or disabled. Enabling this option will override the tabActiveIndex setting for the initial tab panel activation if a URL location hash is present and matches the id attribute of a tab panel element. |
true |
| hashOptions.scrollIntoView | Object | Scroll into view options object. Reference article here for more information on available options https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView. | {behavior: 'smooth', block: 'center'} |
| hashOptions.updateLocation | Boolean | Flag to determine if window location state is updated with hash value corresponding to the active tab panel. |
true |
| tabActiveClass | String | Active tab class name. | 'is-active' |
| tabActiveIndex | Integer | Sets the index of the initial active panel. | 0 |
| tabControlSelector | String | The selector for the tab conrol elements. | '.g-tabcordion__tab' |
| tabListSelector | String | The selector for the tab list element. | '.g-tabcordion__tabs' |
| tabPanelSelector | String | The selector for the tab panel elements. | '.g-tabcordion__panel' |
| tabPanelContentSelector | String | The selector for the tab panel content elements. | '.g-tabcordion__panel-content' |
Features¶
The following section describes common use-case features supported by the Tabcordion class.
Show Panel¶
The showPanel method may be utilized to programmatically show a panel element. Simply pass in the panel element to the showPanel method to display the panel. Alternatively, a tabcordion element object can be passed in as well as the first parameter. More details for the tabcordion element object can be found below.
const tabcordion = new Tabcordion(container);
const panelElement = container.querySelector('#target-panel');
tabcordion.showPanel(panelElement);
The showPanel method takes an optional object for a second parameter if you wish to override the default method behavior. The object supports the following properties:
| Name | Type | Description | Default Value |
|---|---|---|---|
| disableLocationUpdate | Boolean | If true, disables the hash window location state update functionality if the configuration setting is enabled. |
false |
| focus | Boolean | Boolean to determine if focus should be set on the panel. | true |
| scrollIntoView | Null|Object | Scroll in to view behavior. If null, scroll behavior is disabled. The object utilizes a scrollIntoView object https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView. |
null |
A common use case to apply the second parameter is to display and scroll to the panel after interacting with a control or target element.
For example, clicking a Reviews link to activate and scroll to a Reviews panel.
HTML
<a id="js-reviews" class="g-display-link" href="https://www.example.com#panel-reviews">See Reviews</a>
JavaScript
const reviewsTriggerElement = document.getElementById('js-reviews');
reviewsTriggerElement.addEventListener('click', (event) => {
event.preventDefault();
const hashElements = tabcordion.getElementsByHash(reviewsTriggerElement.hash);
if (hashElements) {
tabcordion.showPanel(hashElements, {
scrollIntoView: tabcordion.hashOptions.scrollIntoView
});
}
});
Tabcordion Element Object¶
NOTE the use of the getElementsByHash(hashVal) method in the example above. This method receives a hash value argument corresponding to an id attribute of a panel element. If a matching panel element is found, it will return a tabcordion element object with the following properties:
accordionControl- The accordion control elementpanel- The tab panel elementtabControl- The tab control element
Other helper methods for retrieving a tabcordion element object include:
getActiveElement()- Returns the activetabcordion elementobjectgetElementsByControlElement(controlElement)- Returns atabcordion elementobject associated to the providedcontrolElementgetElementsByPanelElement(panelElement)- Returns atabcordion elementobject associated to the providedpanelElement
Auto Tab Activate And Scroll¶
Alternative to the above use case example, automatic panel display and scroll to functionality is available when the hashOptions.enabled flag is set to true. When this option is enabled, window.location hash changes will be observed and trigger this functionality when the hash value matches the id attribute of a panel element. Essentially, the HTML example above can be output and will automatically apply similar behavior as the JavaScript example when the hash options are enabled. The scroll to behavior in this case is driven by the hashOptions.scrollIntoView configuration option value.
On Page Load¶
When the hashOptions.enabled flag is true and the window location contains a hash value that matches the id attribute of a panel element, the associated tab and accordion control elements will be activated and the panel element will be scrolled into view.
Tab View¶
When the tab view is enabled, only the active panel will be shown and all other panels will be hidden.
Accordion View¶
The accordion view is activated when meeting the criteria for the value provided in the accordionMode setting. When the accordion view is active, panels are shown and hidden individually when interacting with the accordion control elements.
Window Location State¶
When the hashOptions.enabled and hashOptions.updateLocationsettings are enabled, the window.history state will continually be replaced with a location value containing the id attribute of the most recently shown panel element as the location's hash value.
Keyboard Support¶
The sections below outline the keyboard support for the tab and accordion views.
Tab View¶
| Key | Function |
|---|---|
| Tab |
|
| → |
|
| ← |
|
| Home |
|
| End |
|
| Space or Enter |
|
| Shift + Tab |
|
Accordion View¶
| Key | Function |
|---|---|
| Tab |
|
| ↓ |
|
| ↑ |
|
| Home |
|
| End |
|
| Space or Enter |
|