Skip to content

Tabs

The Tabs component is a responsive horizontal navigation bar that allows the user to easily switch between content. Tab panelsare a set of individual content sections, where only one content panel can be displayed at a time. Each tab panel has an associated tab element that, when activated, displays the panel. The list of tab elements is arranged along one edge of the currently displayed panel, the top edge. The component implements the W3C ARIA APG Tabs Pattern.

Examples

Base

Each item component can have a value prop. The active tab is represented by the value of the item as the modelValue prop of the tabs component.

html
<section>
    <o-field grouped>
        <o-switch v-model="showBooks" label="Show Books item" />

        <o-button label="Set Music" @click="activeTab = 'music'" />
    </o-field>

    <o-tabs v-model="activeTab">
        <o-tab-item value="pictures" label="Pictures" icon="image">
            what light is light, if Silvia be not seen? <br />
            What joy is joy.
        </o-tab-item>

        <o-tab-item value="articles" label="Articles" icon="pen">
            Lorem ipsum dolor sit amet.
        </o-tab-item>

        <o-tab-item value="music" label="Music" icon="music">
            Lorem <br />
            ipsum <br />
            dolor <br />
            sit <br />
            amet.
        </o-tab-item>

        <o-tab-item
            value="books"
            :visible="showBooks"
            label="Books"
            icon="book">
            What light is light, if Silvia be not seen? <br />
            What joy is joy, if Silvia be not by— <br />
            Unless it be to think that she is by <br />
            And feed upon the shadow of perfection? <br />
            Except I be by Silvia in the night, <br />
            There is no music in the nightingale.
        </o-tab-item>

        <o-tab-item value="words" label="Words">
            This text is much longer than the other examples. The most
            merciful thing in the world, I think, is the inability of the
            human mind to correlate all its contents. We live on a placid
            island of ignorance in the midst of black seas of infinity, and
            it was not meant that we should voyage far. The sciences, each
            straining in its own direction, have hitherto harmed us little;
            but some day the piecing together of dissociated knowledge will
            open up such terrifying vistas of reality, and of our frightful
            position therein, that we shall either go mad from the
            revelation or flee from the deadly light into the peace and
            safety of a new dark age.
        </o-tab-item>

        <o-tab-item value="videos" label="Videos" icon="video" disabled>
            Nunc nec velit nec libero vestibulum eleifend. Curabitur
            pulvinar congue luctus. Nullam hendrerit iaculis augue vitae
            ornare. Maecenas vehicula pulvinar tellus, id sodales felis
            lobortis eget.
        </o-tab-item>
    </o-tabs>
</section>
javascript
import { ref } from "vue";

const activeTab = ref<string>();
const showBooks = ref(false);

Types

The tabs header can be displayed in different styles using the type prop.

html
<section>
    <o-field label="Boxed/Tabs">
        <o-tabs type="boxed">
            <o-tab-item label="Pictures" icon="images" />
            <o-tab-item label="Music" icon="music" />
            <o-tab-item label="Words" />
            <o-tab-item label="Videos" icon="video" />
        </o-tabs>
    </o-field>

    <o-field label="Toggle">
        <o-tabs type="toggle">
            <o-tab-item label="Pictures" icon="images" />
            <o-tab-item label="Music" icon="music" />
            <o-tab-item label="Words" />
            <o-tab-item label="Videos" icon="video" />
        </o-tabs>
    </o-field>

    <o-field label="Pills">
        <o-tabs type="pills">
            <o-tab-item label="Pictures" icon="images" />
            <o-tab-item label="Music" icon="music" />
            <o-tab-item label="Words" />
            <o-tab-item label="Videos" icon="video" />
        </o-tabs>
    </o-field>
</section>

Positions

The tabs header can be positioned by the position prop.

html
<section>
    <o-tabs type="boxed" position="left">
        <o-tab-item label="Pictures" icon="images" />
        <o-tab-item label="Music" icon="music" />
        <o-tab-item label="Words" />
        <o-tab-item label="Videos" icon="video" />
    </o-tabs>

    <o-tabs type="boxed" position="centered">
        <o-tab-item label="Pictures" icon="images" />
        <o-tab-item label="Music" icon="music" />
        <o-tab-item label="Words" />
        <o-tab-item label="Videos" icon="video" />
    </o-tabs>

    <o-tabs type="boxed" position="right">
        <o-tab-item label="Pictures" icon="images" />
        <o-tab-item label="Music" icon="music" />
        <o-tab-item label="Words" />
        <o-tab-item label="Videos" icon="video" />
    </o-tabs>
</section>

Expanded

When the expanded prop is set, the tabs header will be occupy the full with it can have.

html
<section>
    <o-tabs expanded>
        <o-tab-item label="Pictures" icon="images" />
        <o-tab-item label="Music" icon="music" />
        <o-tab-item label="Words" />
        <o-tab-item label="Videos" icon="video" />
    </o-tabs>
</section>

Variants

Different styles can be achieved with the variant prop. The variant prop can be set for the whole Tabs component as well as for each TabItem.

html
<section>
    <o-tabs>
        <o-tab-item label="Pictures" icon="images" variant="success" />
        <o-tab-item label="Music" icon="music" variant="info" />
        <o-tab-item label="Words" variant="warning" />
        <o-tab-item label="Videos" icon="video" variant="danger" />
    </o-tabs>
</section>

Sizes

The component can be displayed in different sizes using the size prop.

html
<section>
    <o-tabs size="small" type="boxed" :options="options" />

    <o-tabs size="medium" type="boxed" :options="options" />

    <o-tabs size="large" type="boxed" :options="options" />
</section>
javascript
import type { OptionsProp } from "@oruga-ui/oruga-next";

const options: OptionsProp = [
    {
        label: "Pictures",
        value: 0,
        attrs: {
            icon: "image",
        },
    },
    {
        label: "Music",
        value: 1,
        attrs: {
            icon: "music",
        },
    },
    {
        label: "Articles",
        value: 2,
        attrs: {
            icon: "pen",
        },
    },
    {
        label: "Words",
        value: 3,
    },
    {
        label: "Videos",
        value: 4,
        attrs: {
            icon: "video",
            disabled: true,
        },
    },
];

Vertical

Adding the vertical prop displays the component vertically instead of horizontally.

html
<section>
    <o-field grouped multiline>
        <o-field label="Position">
            <o-select v-model="position" placeholder="Position">
                <option :value="undefined">Default</option>
                <option value="left">Left</option>
                <option value="right">Right</option>
            </o-select>
        </o-field>
        <o-field label="Size">
            <o-select v-model="size" placeholder="Size">
                <option :value="undefined">Default</option>
                <option value="small">Small</option>
                <option value="medium">Medium</option>
                <option value="large">Large</option>
            </o-select>
        </o-field>
        <o-field label="Type">
            <o-select v-model="type" placeholder="Type">
                <option value="default">Default</option>
                <option value="boxed">Boxed</option>
                <option value="toggle">Toggle</option>
            </o-select>
        </o-field>
        <o-field>
            <o-switch v-model="expanded" label="Expanded" />
        </o-field>
    </o-field>

    <o-tabs
        :position="position"
        :size="size"
        :type="type"
        vertical
        :expanded="expanded">
        <o-tab-item label="Pictures" icon="images">
            Lorem ipsum dolor sit amet. <br />
            Lorem ipsum dolor sit amet. <br />
            Lorem ipsum dolor sit amet. <br />
            Lorem ipsum dolor sit amet. <br />
            Lorem ipsum dolor sit amet. <br />
            Lorem ipsum dolor sit amet.
        </o-tab-item>

        <o-tab-item label="Music" icon="music">
            What light is light, if Silvia be not seen? <br />
            What joy is joy, if Silvia be not by— <br />
            Unless it be to think that she is by <br />
            And feed upon the shadow of perfection? <br />
            Except I be by Silvia in the night, <br />
            There is no music in the nightingale.
        </o-tab-item>

        <o-tab-item label="Words">
            <p>
                This text is much longer than the other examples. The most
                merciful thing in the world, I think, is the inability of
                the human mind to correlate all its contents. We live on a
                placid island of ignorance in the midst of black seas of
                infinity, and it was not meant that we should voyage far.
                The sciences, each straining in its own direction, have
                hitherto harmed us little; but some day the piecing together
                of dissociated knowledge will open up such terrifying vistas
                of reality, and of our frightful position therein, that we
                shall either go mad from the revelation or flee from the
                deadly light into the peace and safety of a new dark age.
            </p>
        </o-tab-item>

        <o-tab-item label="Videos" icon="video" disabled>
            Nunc nec velit nec libero vestibulum eleifend. Curabitur
            pulvinar congue luctus. Nullam hendrerit iaculis augue vitae
            ornare. Maecenas vehicula pulvinar tellus, id sodales felis
            lobortis eget.
        </o-tab-item>
    </o-tabs>
</section>
javascript
import { ref } from "vue";

const position = ref<"left" | "right">("left");
const expanded = ref(false);
const size = ref(undefined);
const type = ref("default");

Custom header

The individual tab label can be customised using the header slot.

html
<section>
    <o-tabs type="boxed">
        <o-tab-item>
            <template #header>
                <o-icon icon="info-circle" root-class="custom-icon" />
                <span> Issues 3 </span>
            </template>
        </o-tab-item>

        <o-tab-item>
            <template #header>
                <o-icon icon="retweet" root-class="custom-icon" />
                <span> Pull Requests {{ count }} </span>
            </template>
        </o-tab-item>
    </o-tabs>
</section>
javascript
import { ref, onMounted } from "vue";

const count = ref(1);

onMounted(() => {
    setTimeout(() => {
        count.value++;
    }, 3000);
});
scss
.custom-icon {
    margin-right: 5px;
}

Long header

The multiple prop allows to break the tab header to be broken into multiple lines if there are too many tabs for one line.

html
<section>
    <o-tabs type="boxed" multiline>
        <o-tab-item
            v-for="(item, index) in new Array(45)"
            :key="`longitem-${index}`"
            :label="`Head ${index}`"
            :icon="index % 2 === 0 ? 'book' : ''" />
    </o-tabs>
</section>

Tabs Component

Responsive horizontal navigation tabs, switch between contents with ease.

html
<o-tabs></o-tabs>

Props

Prop nameDescriptionTypeValuesDefault
activateOnFocusSet the tab active on navigation focusboolean-false
animateInitiallyApply animation on the initial renderboolean-
From config:
tabs: {
  animateInitially: false
}
animatedTab will have an animationboolean-
From config:
tabs: {
  animated: true
}
animationTransition animation name[string, string, string, string] | [string, string][next, prev], [right, left, down, up]
From config:
tabs: {
  animation: [ "slide-next", "slide-prev", "slide-down", "slide-up",]
}
ariaLabelAccessibility aria-label to be passed to the tablist wrapper elementstring-
From config:
tabs: {
  ariaLabel: undefined
}
expandedTabs will be expanded (full-width)boolean-false
v-modelThe selected item value, use v-model to make it two-way bindingstring|number|object-
multilineShow tab items multiline when there is no spaceboolean-false
optionsTabs options, unnecessary when default slot is usedTabsOptions<unknown>-
overrideOverride existing theme classes completelyboolean-
positionPosition of the tabs"centered" | "left" | "right"left, centered, right
sizeTab sizestringsmall, medium, large
From config:
tabs: {
  size: undefined
}
tagTablist tag nameDynamicComponent-
From config:
tabs: {
  tag: "div"
}
typeTab typestringdefault, boxed, toggle, pills
From config:
tabs: {
  type: "default"
}
variantColor variant of the controlstringprimary, info, success, warning, danger, and any other custom color
From config:
tabs: {
  variant: undefined
}
verticalShow tab in vertical layoutboolean-
From config:
tabs: {
  vertical: false
}

Events

Event namePropertiesDescription
update:model-valuevalue unknown - updated modelValue propmodelValue prop two-way binding
changevalue unknown - new tab value
value unknown - old tab value
on tab change event

Slots

NameDescriptionBindings
beforeAdditional slot before the tabs
afterAdditional slot after the tabs
defaultDefine the tag items here

TabItem Component

An tab item used by the tabs component.

html
<o-tab-item></o-tab-item>

Props

Prop nameDescriptionTypeValuesDefault
componentComponent to be injectedC-
contentText content, unnecessary when default slot is usedstring-
disabledItem will be disabledboolean-false
eventsEvents to be binded to the injected componentEmitsToProps<ComponentEmit<C>>-
iconIcon shown to the left of the labelstring-
From config:
tabs: {
  icon: undefined
}
iconPackIcon packstring-
From config:
tabs: {
  iconPack: undefined
}
labelItem labelstring-
overrideOverride existing theme classes completelyboolean-
propsProps to be binded to the injected componentComponentProps<C>-
tagTabs item tag nameDynamicComponent-
From config:
tabs: {
  itemTag: PlainButton
}
valueItem value (it will be used as the v-model of the wrapper component) - default is an uuidstring|number|object-useId()
variantColor variant of the control
This will override parent variant.
stringprimary, info, success, warning, danger, and any other custom color
visibleShow/hide itemboolean-true

Events

Event namePropertiesDescription
activateon tab item activate event
deactivateon tab item deactivate event

Slots

NameDescriptionBindings
defaultDefine the tab item content hereactive boolean - if item is shown
headerOverride tab header labelactive boolean - if item is shown

Class Inspector

Classes applied to the element:
Want to know how does the Class Inspector work?
Class propDescriptionPropsSuffixes
rootClass
Class of the root element.
positionClass
Class of the root element with position.
positionbottom
left
right
sizeClass
Class of the root element with size.
sizesmall
medium
large
typeClass
Class of the root element with type.
typedefault
boxed
toggle
pills
expandedClass
Class of the root element when expanded.
expanded
verticalClass
Class of the root element when vertical.
vertical
multilineClass
Class of the root element when multilined.
multiline
listClass
Class of the list container element.
animatedClass
Class of the item element when animated.
contentClass
Class of the panel container element.
transitioningClass
Class of the panel container element when transitioning.
tabClass
Class of the tab item element.
tabVariantClass
Class of the step item element with variant (default value by parent steps component).
variantprimary
info
warning
danger
tabActiveClass
Class of the tab item element when active.
tabDisabledClass
Class of the tab item element when disabled.
disabled
tabPreviousClass
Class of the tab item element before the active one.
tabNextClass
Class of the tab item element after the active one.
tabIconClass
Class of the tab item icon element.
icon
tabLabelClass
Class of the tab item label element.
label
tabPanelClass
Class of the tab panel element.

Sass Variables

Current theme ➜ Oruga

SASS VariableDefault
$tabs-sapcerh.useVar("control-spacer")
$tabs-disabled-opacityh.useVar("control-disabled-opacity")
$tabs-tab-paddingh.useVar("control-spacer") calc(2 * h.useVar("control-spacer"))
$tabs-tab-icon-margin0 h.useVar("control-spacer") 0 0
$tabs-tab-colorh.useVar("font-color")
$tabs-tab-font-sizeh.useVar("font-size")
$tabs-tab-font-weighth.useVar("font-weight")
$tabs-tab-line-heighth.useVar("line-height")
$tabs-tab-border-widthh.useVar("control-border-width")
$tabs-tab-border-stylesolid
$tabs-tab-border-colorh.useVar("control-border-color")
$tabs-tab-border-radiush.useVar("border-radius")
$tabs-tab-background-colortransparent
$tabs-tab-hover-color$tabs-tab-color
$tabs-tab-hover-background-colorhsl(0, 0%, 96%)
$tabs-tab-hover-border-colorhsl(0, 0%, 86%)
$tabs-tab-hover-border-radius$tabs-tab-border-radius
$tabs-tab-active-colorh.useVar("primary")
$tabs-tab-active-background-colorh.useVar("primary-invert")
$tabs-tab-active-border-colorh.useVar("primary")
$tabs-tab-active-border-radius$tabs-tab-border-radius
$tabs-content-paddingcalc(2 * h.useVar("control-spacer"))

See ➜ 📄 SCSS file

Current theme ➜ Bulma

SASS VariableDefault
$tabs-focused-outlinenone
$tabs-link-focus-border-bottom-colorcss.getVar( "tabs-link-hover-border-bottom-color")
$tabs-link-focus-active-border-bottom-colorcss.getVar( "tabs-link-active-border-bottom-color")
$tabs-boxed-link-focus-active-background-colorcss.getVar( "tabs-boxed-link-active-background-color")
$tabs-boxed-link-focus-background-colorcss.getVar( "tabs-boxed-link-hover-background-color")
$tabs-boxed-link-focus-active-border-bottom-colorcss.getVar( "tabs-boxed-link-active-border-bottom-color")
$tabs-boxed-link-focus-border-bottom-colorcss.getVar( "tabs-boxed-link-hover-border-bottom-color")
$tabs-toggle-link-focus-active-background-colorcss.getVar( "tabs-toggle-link-active-background-color")
$tabs-toggle-link-focus-background-colorcss.getVar( "tabs-toggle-link-hover-background-color")
$tabs-toggle-link-focus-active-border-colorcss.getVar( "tabs-toggle-link-active-border-color")
$tabs-toggle-link-focus-border-colorcss.getVar( "tabs-toggle-link-hover-border-color")

See ➜ 📄 SCSS file

Current theme ➜ Bootstrap

SASS VariableDefault
$nav-tabs-colorvar(--#{$prefix}body-color)
$nav-tabs-spacer$spacer
$nav-tabs-disabled-opacity0.5
$nav-underline-link-active-bg$nav-tabs-link-active-bg
$nav-underline-link-active-border-colorcurrentcolor

See ➜ 📄 SCSS file

Released under the MIT License.