1

I had a requirement to display a row of tabs. When one of them is clicked, it displays a dropdown sub-menu, allowing the user to click on one of the options.

I couldn't find any out-of-the-box capability for this, nor could I find any question on here asking how to do this.

I have since developed a solution which is presented in the answer.

1 Answer 1

2

gif of tab with dropdown

Here is the component markup:

<aura:component>
    <aura:attribute name="activeTab" type="String" default="home"/>

    <!--
        Convention when adding a new tab -
            The aura:id of the tab must follow the pattern 'tabname-tab-auraid'
            where 'tabname' is some identifier for the tab.
            The data-tab value of the tab must be tabname
            The aura:id of the tab content must follow the pattern 'tabname-content-auraid'
            Add the tabname to the allTabs array in the helper.  The order is not important.
        To remove a tab -
            Remove the tab and tab content below
            Remove tabname from the allTabs array in the helper
    -->

    <div class="slds-tabs_default">
        <ul class="slds-tabs_default__nav" role="tablist">
            <!-- Tabs -->
            <!-- Home tab -->
            <li class="slds-tabs_default__item slds-active" title="Home Tab" role="presentation" aura:id="home-tab-auraid">
                <a class="slds-tabs_default__link" href="javascript:void(0);" role="tab" tabindex="0" aria-selected="true" aria-controls="home-content" id="home-tab" onclick="{!c.switchTabs}" data-tab="home">Home</a>
            </li>
            <!-- Accounts tab -->
            <li class="slds-tabs_default__item" title="Accounts Tab" role="presentation" aura:id="company-vis-tab-auraid">
                <a class="slds-tabs_default__link" href="javascript:void(0);" role="tab" tabindex="-1" aria-selected="false" aria-controls="accounts-content" id="accounts-tab" onclick="{!c.switchTabs}" data-tab="accounts">Accounts</a>
            </li>
            <!-- Example tab with dropdown -->
            <li class="slds-tabs_default__item slds-tabs_default__overflow-button" title="Example" role="presentation" aura:id="example-tab-auraid">
                <div aura:id="menuExample" class="slds-dropdown-trigger slds-dropdown-trigger_click">
                    <button class="slds-button" aria-haspopup="true" onclick="{!c.toggleExampleMenu}" data-tab="example">Example&nbsp;
                            <lightning:buttonIcon iconName="utility:chevrondown"  size="small" variant="bare" alternativeText="Example" />
                    </button>
                    <div class="slds-dropdown slds-dropdown_right">
                        <ul class="slds-dropdown__list slds-dropdown_length-with-icon-10" role="menu">
                            <li class="slds-dropdown__item" role="presentation">
                                <a href="javascript:void(0);" role="menuitem" tabindex="-1" aria-controls="option1-content" id="option1-tab" onclick="{!c.switchTabs}" data-tab="option1">
                                    <span class="slds-truncate" title="Option 1 Tab">Option 1</span>
                                </a>
                            </li>
                            <li class="slds-dropdown__item" role="presentation">
                                <a href="javascript:void(0);" role="menuitem" tabindex="-1" aria-controls="option2-content" id="option2-tab" onclick="{!c.switchTabs}" data-tab="option2">
                                    <span class="slds-truncate" title="Option 2 Tab">Option 2</span>
                                </a>
                            </li>
                            <li class="slds-dropdown__item" role="presentation">
                                <a href="javascript:void(0);" role="menuitem" tabindex="-1" aria-controls="option3-content" id="option3-tab" onclick="{!c.switchTabs}" data-tab="option3">
                                    <span class="slds-truncate" title="Option 3 Tab">Option 3</span>
                                </a>
                            </li>
                        </ul>
                    </div>
                </div>
            </li>
        </ul>

        <!-- Tab contents -->
        <!-- Home content -->
        <aura:if isTrue="{!v.activeTab == 'home'}">
            <div aura:id="home-content-auraid" id="home-content" class="slds-tabs_default__content slds-show" role="tabpanel" aria-labelledby="home-tab">
                <p>Home tab content goes here</p>
            </div>
        </aura:if>
        <!--  Accounts content -->
        <aura:if isTrue="{!v.activeTab == 'accounts'}">
            <div aura:id="accounts-content-auraid" id="accounts-content" class="slds-tabs_default__content slds-hide" role="tabpanel" aria-labelledby="accounts-tab">
                <p>Accounts tab content goes here</p>
            </div>
        </aura:if>
        <!-- Option 1 content -->
        <aura:if isTrue="{!v.activeTab == 'option1'}">
            <div aura:id="option1-content-auraid" id="option1-content" class="slds-tabs_default__content slds-hide" role="tabpanel" aria-labelledby="option1-tab">
                <p>Option 1 content goes here</p>
            </div>
        </aura:if>
        <!-- Option 2 content -->
        <aura:if isTrue="{!v.activeTab == 'option2'}">
            <div aura:id="option2-content-auraid" id="option2-content" class="slds-tabs_default__content slds-hide" role="tabpanel" aria-labelledby="option2-tab">
                <p>Option 2 content goes here</p>
            </div>
        </aura:if>
        <!-- Option 3 content -->
        <aura:if isTrue="{!v.activeTab == 'option3'}">
            <div aura:id="option3-content-auraid" id="option3-content" class="slds-tabs_default__content slds-hide" role="tabpanel" aria-labelledby="option3-tab">
                <p>Option 3 content goes here</p>
            </div>
        </aura:if>
    </div>
</aura:component>

Here is the controller:

({
    switchTabs: function(component, event, helper) {
        /* Use html5 data attributes to pass the tab name as the
         * data-tab attribute in the onclick event in component
         */
        var tab = event.currentTarget.dataset.tab;
        component.set("v.activeTab", tab);
        helper.deactivateAllTabs(component, event, helper);
        helper.activateTab(component, event, helper, tab);
    },

    toggleExampleMenu: function(component, event, helper) {
        var exampleMenu = component.find("menuExample");
        $A.util.toggleClass(exampleMenu, 'slds-is-open');
    },
})

and here is the helper:

({
    /* For all tabs, remove Classes that make the tab visible and 
     * add Class to hide the tab
     */
    deactivateAllTabs: function(component, event, helper) {
        // When adding a new tab, the tabname must be added to the allTabs array:
        var allTabs = [
            'home',
            'accounts',
            'example',
            'option1',
            'option2',
            'option3'
        ]

        // Hide the dropdown on Example menu:
        $A.util.removeClass(component.find("menuExample"), 'slds-is-open');

        // Deactivate all tabs:
        allTabs.forEach(deactivate);

        function deactivate(item) {
            var tabToDeactivate = component.find(item + '-tab-auraid');
            var contentToHide = component.find(item + '-content-auraid');

            $A.util.removeClass(tabToDeactivate, 'slds-active');
            $A.util.removeClass(tabToDeactivate, 'slds-has-focus');
            $A.util.removeClass(tabToDeactivate, 'tabActive');
            $A.util.removeClass(contentToHide, 'slds-show');
            $A.util.addClass(contentToHide, 'slds-hide');

        }
    },

    /* For the active tab, add Classes to make the tab visible and 
     * remove Class that hides the tab
     */
    activateTab: function(component, event, helper, tab) {
        var tabToActivate = component.find(tab + '-tab-auraid');
        var contentToShow = component.find(tab + '-content-auraid');

        $A.util.addClass(tabToActivate, 'slds-active');
        $A.util.addClass(contentToShow, 'slds-show');
        $A.util.removeClass(contentToShow, 'slds-hide');

        // If it's an overflow tab we need to activate the parent:
        var overflowTabs = [
            'option1',
            'option2',
            'option3'
        ];

        if (overflowTabs.includes(tab)) {
            $A.util.addClass(component.find('example-tab-auraid'), 'slds-has-focus');
            $A.util.addClass(component.find('example-tab-auraid'), 'tabActive');
        }
    },
})

Thanks to sfdcmonkey.com whose post 'How To Custom Create Lightning Tabs In Lightning Component' was a great help when getting started: https://sfdcmonkey.com/2016/11/23/how-to-create-lightning-tabs-in-component/

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .