BpTabs is a tabs component that encapsulates all the logic and accessibility operations needed. Styling classes are all customizable adherent to ABEM standard.

Vue Component

BpTabs

Props

  • block - the block class (defaults to ‘accordion’)
  • navElement - the nav element (defaults to ‘nav’)
  • navListElement - the nav list element (defaults to ‘navList’)
  • tabElement - the tab element (defaults to ‘tab’)
  • panelElement - the panel element (defaults to ‘panel’)
  • activeClass - the modifier class for the active tab (defaults to ‘-active’)
  • tabs - Object containing key values identifiying each tab/panel, ex: { tab1: 'Tab One' }
  • initialTab - Key of tab to be open by default
  • setHash - A Boolean as to whether changing tabs updates location.hash

Sass Mixin

@mixin tabs()

Parameters

None.

<bp-tabs class="-vertical" :tabs="{ tab1: 'Tab One', tab2: 'Tab Two', tab3: 'Tab Three' }" :vertical="true">
    <template #tab-panel-tab1>
        <p>
            The New England Patriots are a professional American football team based in the Greater Boston area. The Patriots play their home games at Gillette Stadium in the town of Foxborough, Massachusetts. The team is part of the East division of the American Football Conference (AFC) in the National Football League (NFL). An original member of the American Football League (AFL), the Patriots joined the NFL in the 1970 merger of the two leagues.
        </p>
        <p>
            Since the arrival of head coach Bill Belichick in 2000, the Patriots have become one of the most successful teams in NFL history. They are tied with the Pittsburgh Steelers and Dallas Cowboys as the teams with the most Super Bowl appearances overall (eight each), and have the most appearances in the last 25 years. They have twelve AFC East titles in fourteen seasons since 2001, and have not had a losing season since 2000.
        </p>
    </template>
    <template #tab-panel-tab2>
        <p>
            The Boston Bruins are an American professional ice hockey team based in Boston, Massachusetts. They are members of the Atlantic Division of the Eastern Conference of the National Hockey League (NHL). The team has been in existence since 1924, and is the League's third-oldest team and is the oldest in the United States.
        </p>
        <p>
            The Bruins have won six Stanley Cup championships, tied for fifth most of all-time with the Blackhawks and tied second-most of any American NHL team also with the Blackhawks (behind the Red Wings, who have 11). Their home arena is the TD Garden, where they have played since 1995.
        </p>
    </template>
    <template #tab-panel-tab3>
        <p>
            The Boston Celtics are an American professional basketball team based in Boston, Massachusetts. They play in the Atlantic Division of the Eastern Conference in the National Basketball Association (NBA). Founded in 1946 and one of eight NBA teams (out of 23 total teams) to survive the league's first decade, the team is currently owned by Boston Basketball Partners LLC.
        </p>
        <p>
            The Celtics have met the Lakers a record twelve times in the Finals, including their most recent appearances in 2008 and 2010, where the Celtics have won nine meetings (but only two since 1980). Four Celtics (Bob Cousy, Bill Russell, Dave Cowens and Larry Bird) have won the NBA Most Valuable Player Award for an NBA record total of ten MVP awards.
        </p>
    </template>
</bp-tabs>
  • Content:
    <template>
        <section
            ref="tabSection"
            :class="`${block}`"
        >
            <nav :class="`${block}__${navElement}`">
                <ul :class="`${block}__${navListElement}`">
                    <li
                        v-for="(tabTitle, tab) in tabs"
                        :key="tab"
                        :class="[`${block}__${tabElement}`, isActive(tab)]"
                    >
                        <button
                            :id="tab"
                            :tabindex="isActive(tab) ? '0' : '-1'"
                            :class="`${block}__${buttonElement}`"
                            role="button"
                            :aria-selected="`${isActive(tab)}`"
                            :aria-controls="`${tab}-panel`"
                            v-text="tabTitle"
                        />
                    </li>
                </ul>
            </nav>
            <div
                v-for="(tabTitle, tab) in tabs"
                :id="`${tab}-panel`"
                :key="tab"
                tabindex="0"
                :class="`${block}__${panelElement}`"
                :hidden="!isActive(tab)"
                :aria-labelledby="tab"
            >
                <div v-if="isActiveItem(tab)">
                    <slot :name="`tab-panel-${tab}`" />
                </div>
            </div>
        </section>
    </template>
    
    <script setup>
    
    import { ref } from 'vue'
    
    import useExpandable from '@resources/js/components/UseExpandable.js'
    
    const tabSection = ref(null)
    
    const props = defineProps({
        block: {
            type: String,
            default: 'tabs',
        },
        navElement: {
            type: String,
            default: 'header',
        },
        navListElement: {
            type: String,
            default: 'list',
        },
        tabElement: {
            type: String,
            default: 'tab',
        },
        buttonElement: {
            type: String,
            default: 'button',
        },
        panelElement: {
            type: String,
            default: 'panel',
        },
        activeClass: {
            type: String,
            default: '-active',
        },
        tabs: {
            type: Object,
            required: true,
        },
        initialTab: {
            type: String,
            default (props) {
                const [firstTab] = Object.keys(props.tabs)
                return firstTab
            },
        },
        setHash: {
            type: Boolean,
            default: true,
        },
        vertical: {
            type: Boolean,
            default: false,
        },
        wrap: {
            type: Boolean,
            default (props) {
                return !props.vertical
            },
        },
    })
    
    function isActive (tab) {
        return tab === activeItem.value ? props.activeClass : ''
    }
    function isActiveItem (tab) {
        return activeItem.value === tab
    }
    
    const { activeItem } = useExpandable(tabSection,
        props.tabs,
        {
            initialItem: props.initialTab,
            setHash: props.setHash,
            wrap: props.wrap,
            vertical: props.vertical,
        }
    )
    
    </script>
    
  • URL: /components/raw/tabs/BpTabs.vue
  • Filesystem Path: resources/styles/molecules/tabs/BpTabs.vue
  • Size: 2.8 KB
  • Content:
    ///
    /// TABS allows for the showing and hiding of panels via an associated tab
    /// navigation. By adding an optional data element (data-hash="#myHash") to
    /// the li tags the javascript plugin will add the hash to the URL so users
    /// may bookmark the page and the page can reload open to that tab when the
    /// the url with the hash is loaded in the browser.
    ///
    
    @use "/resources/styles/common" as common;
    @use "/resources/styles/config" as config;
    
    .tabs {
        $b: &;
    
        &__list {
            @include common.no-bullets;
            display: flex;
            overflow: hidden;
    
            &::before,
            &::after {
                content: '';
                border-bottom: 1px solid config.$gray-300;
                box-shadow: 0 -0.5px 1.1px -1.1px rgba(0, 0, 0, 0.057), 0 -1.8px 3.6px -3.6px rgba(0, 0, 0, 0.083), 0 -8px 16px -16px rgba(0, 0, 0, 0.14);
                flex-grow: 1;
            }
        }
    
        &__tab {
            margin: 0;
            border: 1px solid config.$gray-100;
            border-bottom-color: config.$gray-300;
            border-radius: 4px 4px 0 0;
    
            & + & {
                margin-left: -1px;
            }
        }
    
        &__button {
            border: none;
            background: none;
            cursor: pointer;
            padding: config.$thin-v-space config.$h-space;
        }
    
        &__tab.-active {
            background-color: transparent;
            border-color: config.$gray-300;
            border-bottom: none;
            box-shadow: 0 0 1.1px rgba(0, 0, 0, 0.57), 0 0 3.6px rgba(0, 0, 0, 0.083), 0 0 16px rgba(0, 0, 0, 0.14);
            z-index: 1;
        }
    
        &__panel {
            padding-top: .5rem;
        }
    
        &.-vertical {
            #{$b}__tab {
                border-radius: 0;
                border: 0;
                box-shadow: 0 -.125rem 0 inset;
    
                &.-active {
                    box-shadow: 0 -.25rem 0 config.$primary inset;
    
                    #{$b}__button {
                        color: config.$primary;
                    }
                }
            }
    
            @include common.at(md) {
                display: flex;
                justify-content: space-between;
    
                #{$b}__header {
                    width: span(1, 3);
                }
    
                #{$b}__list {
                    flex-direction: column;
    
                    &::before,
                    &::after {
                        content: none;
                    }
                }
    
                #{$b}__tab {
                    box-shadow: .25rem 0 0 inset;
                    margin: 0 0 .5rem;
    
                    &.-active {
                        box-shadow: .5rem 0 0 config.$primary inset;
                    }
                }
    
                #{$b}__button {
                    text-align: left;
                    width: 100%;
                }
    
                #{$b}__panel {
                    padding-top: 0;
                    width: span(2, 3);
                }
            }
        }
    }
  • URL: /components/raw/tabs/_index.scss
  • Filesystem Path: resources/styles/molecules/tabs/_index.scss
  • Size: 2.8 KB