Skip to content

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 HTML id attributes 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>
  1. 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 Tabcordion class.
  2. The g-tabcordion__tabs class indicates that the element serves as the container for the set of tabs (tab list). This element's width is also targeted when the accordionMode setting is set to auto.
  3. Each element with the g-tabcordion__tab class within the tab list indicates the element serves as a tab control. The associated panel is linked by its own id attribute that matches the aria-controls attribute value on the tab control element.

    The default active tab control must contain the is-active class or set to the class specified by the tabActiveClass configuration setting. Additionally, the active tab control must have its aria-expanded attribute set to true. All other tab control elements must have a aria-expanded attribute set to false.

  4. Each element with the g-tabcordion__accordion-control class indicates the elements serves as an accordion control. The associated panel is linked by its own id attribute that matches the aria-controls attribute value on the accordion control element.

    The default active accordion control must contain the is-active class or set to the class specified by the tabActiveClass configuration setting. Additionally, the active accordion control must have its aria-expanded attribute set to true. All other accordion control elements must have a aria-expanded attribute set to false.

  5. Each tab panel element must have an id attribute and a role="region" attribute in conjunction with the aria-labelledby attribute to indicate the element serves as a container for the panel content and is associated properly to its control elements. The aria-labelledby value is a space separated value containing the id attributes for each of the panel's control elements.
  6. The panel content is placed within an element with the g-tabcordion__panel-content class.

.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 element
  • panel - The tab panel element
  • tabControl - The tab control element

Other helper methods for retrieving a tabcordion element object include:

  • getActiveElement() - Returns the active tabcordion element object
  • getElementsByControlElement(controlElement) - Returns a tabcordion element object associated to the provided controlElement
  • getElementsByPanelElement(panelElement) - Returns a tabcordion element object associated to the provided panelElement

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
  • Moves focus to the next tab control element.
  • Moves focus to the next tab control element.
  • If focus is on the last tab control, moves focus to the first tab control.
  • Moves focus to the previous tab control element.
  • If focus is on the first tab control, moves focus to the last tab control.
Home
  • Moves focus to the first tab control element.
End
  • Moves focus to the last tab control element.
Space or Enter
  • Shows the associated panel of the tab control element and places focus on the panel element's content container.
Shift + Tab
  • Moves focus to the associated tab control element when the panel element's content container is focused.

Accordion View

Key Function
Tab
  • Moves focus to the next focusable element.
  • Moves focus to the next accordion control element.
  • If focus is on the last accordion control, moves focus to the first accordion control.
  • Moves focus to the previous accordion control element.
  • If focus is on the first accordion control, moves focus to the last accordion control.
Home
  • Moves focus to the first accordion control element.
End
  • Moves focus to the last accordion control element.
Space or Enter
  • Shows or hides the associated panel of the accordion control element.
  • Places focus on the panel element's content container if the panel is shown.