Skip to content
On this page

Tabs

Add quick, dynamic tab functionality to transition through panes of local content, even via dropdown menus. Nested tabs are not supported.

Example

vue
<template>
  <Tabs>
    <Tab title="Home">
      <p>
        Raw denim you probably haven't heard of them jean shorts Austin.
        Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache
        cliche tempor, williamsburg carles vegan helvetica. Reprehenderit
        butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui
        irure terry richardson ex squid. Aliquip placeat salvia cillum iphone.
        Seitan aliquip quis cardigan american apparel, butcher voluptate nisi
        qui.
      </p>
    </Tab>
    <Tab title="Profile">
      <p>
        Food truck fixie locavore, accusamus mcsweeney's marfa nulla
        single-origin coffee squid. Exercitation +1 labore velit, blog sartorial
        PBR leggings next level wes anderson artisan four loko farm-to-table
        craft beer twee. Qui photo booth letterpress, commodo enim craft beer
        mlkshk aliquip jean shorts ullamco ad vinyl cillum PBR. Homo nostrud
        organic, assumenda labore aesthetic magna delectus mollit. Keytar
        helvetica VHS salvia yr, vero magna velit sapiente labore stumptown.
        Vegan fanny pack odio cillum wes anderson 8-bit, sustainable jean shorts
        beard ut DIY ethical culpa terry richardson biodiesel. Art party
        scenester stumptown, tumblr butcher vero sint qui sapiente accusamus
        tattooed echo park.
      </p>
    </Tab>
    <Tab title="@vue" group="Dropdown">
      <p>
        Etsy mixtape wayfarers, ethical wes anderson tofu before they sold out
        mcsweeney's organic lomo retro fanny pack lo-fi farm-to-table readymade.
        Messenger bag gentrify pitchfork tattooed craft beer, iphone skateboard
        locavore carles etsy salvia banksy hoodie helvetica. DIY synth PBR
        banksy irony. Leggings gentrify squid 8-bit cred pitchfork. Williamsburg
        banh mi whatever gluten-free, carles pitchfork biodiesel fixie etsy
        retro mlkshk vice blog. Scenester cred you probably haven't heard of
        them, vinyl craft beer blog stumptown. Pitchfork sustainable tofu synth
        chambray yr.
      </p>
    </Tab>
    <Tab title="@bootstrap" group="Dropdown">
      <p>
        Trust fund seitan letterpress, keytar raw denim keffiyeh etsy art party
        before they sold out master cleanse gluten-free squid scenester freegan
        cosby sweater. Fanny pack portland seitan DIY, art party locavore wolf
        cliche high life echo park Austin. Cred vinyl keffiyeh DIY salvia PBR,
        banh mi before they sold out farm-to-table VHS viral locavore cosby
        sweater. Lomo wolf viral, mustache readymade thundercats keffiyeh craft
        beer marfa ethical. Wolf salvia freegan, sartorial keffiyeh echo park
        vegan.
      </p>
    </Tab>
  </Tabs>
</template>

<script setup>
import { Tab, Tabs } from 'uiv';
</script>

Disable tabs

Add disabled to <tab> to disable it.

vue
<template>
  <Tabs>
    <Tab title="Home">
      <p>Home tab.</p>
    </Tab>
    <Tab title="Profile" disabled>
      <p>Profile tab.</p>
    </Tab>
    <Tab title="@vue" group="Dropdown">
      <p>@vue tab.</p>
    </Tab>
    <Tab title="@bootstrap" group="Dropdown" disabled>
      <p>@bootstrap tab.</p>
    </Tab>
  </Tabs>
</template>

<script setup>
import { Tab, Tabs } from 'uiv';
</script>

Pull right

Add pull-right to <tab> to pull it right. A grouped tab will be pulled to right if one of its sub-tabs has this prop set to true.

vue
<template>
  <Tabs>
    <Tab title="Home">
      <p>Home tab.</p>
    </Tab>
    <Tab title="Profile">
      <p>Profile tab.</p>
    </Tab>
    <Tab title="@vue" group="Dropdown" pull-right>
      <p>@vue tab.</p>
    </Tab>
    <Tab title="@bootstrap" group="Dropdown">
      <p>@bootstrap tab.</p>
    </Tab>
  </Tabs>
</template>

<script setup>
import { Tab, Tabs } from 'uiv';
</script>

Justified style

Add justified to <tabs> to apply justified style.

vue
<template>
  <Tabs justified>
    <Tab title="Home">
      <p>Home tab.</p>
    </Tab>
    <Tab title="Profile">
      <p>Profile tab.</p>
    </Tab>
    <Tab title="Others">
      <p>Others tab.</p>
    </Tab>
  </Tabs>
</template>

<script setup>
import { Tab, Tabs } from 'uiv';
</script>

Pills style

Add pills to <tabs> to apply pills style.

Pills are also vertically stackable by adding stacked, but if you want the nav and content parts to have layout such as 2 column, you may need some custom CSS apply to them.

vue
<template>
  <Tabs pills>
    <Tab title="Home">
      <p>Home tab.</p>
    </Tab>
    <Tab title="Profile">
      <p>Profile tab.</p>
    </Tab>
    <Tab title="Others">
      <p>Others tab.</p>
    </Tab>
  </Tabs>
</template>

<script setup>
import { Tab, Tabs } from 'uiv';
</script>

Custom titles

With title slot you can place any content inside nav tabs.

vue
<template>
  <Tabs>
    <Tab>
      <template #title>
        <div><i class="glyphicon glyphicon-user"></i> Profile</div>
      </template>
      <p>This tab has a <code>title</code> slot.</p>
    </Tab>
    <Tab title="Title">
      <p>This tab has a normal title.</p>
    </Tab>
  </Tabs>
</template>

<script setup>
import { Tab, Tabs } from 'uiv';
</script>

With callbacks

vue
<template>
  <Tabs @change="onChange">
    <Tab title="Home">
      <p>Home tab.</p>
    </Tab>
    <Tab title="Profile">
      <p>Profile tab.</p>
    </Tab>
    <Tab>
      <template #title>
        <div><i class="glyphicon glyphicon-bell"></i> Alert!</div>
      </template>
      <p>This tab has HTML title and callback function!</p>
    </Tab>
  </Tabs>
</template>

<script setup>
import { Tab, Tabs, Notification } from 'uiv';

function onChange(index) {
  if (index === 2) {
    Notification.notify('You clicked on a tab that has callback function!');
  }
}
</script>

With nav-right slot

vue
<template>
  <Tabs>
    <Tab title="Home">
      <p>Home tab.</p>
    </Tab>
    <Tab title="Profile">
      <p>Profile tab.</p>
    </Tab>
    <template #nav-right>
      <form>
        <select class="form-control" style="display: inline-block; width: auto">
          <option>option1</option>
          <option>option2</option>
          <option>option3</option>
          <option>option4</option>
        </select>
        <Btn type="success">Button</Btn>
      </form>
    </template>
  </Tabs>
</template>

<script setup>
import { Tab, Tabs, Btn } from 'uiv';
</script>

Dynamic tabs

An example that generate closable tabs using v-for:

vue
<template>
  <Tabs v-model="index">
    <Tab v-for="tab in tabs" :key="tab" :title="tab">
      <p>Dynamic {{ tab }}</p>
      <btn @click="close">Close this tab</btn>
    </Tab>
    <template #nav-right>
      <Btn size="sm" @click="push">
        <i class="glyphicon glyphicon-plus"></i> Add
      </Btn>
    </template>
  </Tabs>
</template>
<script setup>
import { Tab, Tabs, Btn } from 'uiv';
import { ref, nextTick } from 'vue';

const tabs = ref(['Tab 1']);
const count = ref(1);
const index = ref(0);

function push() {
  tabs.value.push(`Tab ${++count.value}`);
  // open the new tab after created
  nextTick(() => {
    index.value = tabs.value.length - 1;
  });
}

function close() {
  tabs.value.splice(index.value, 1);
  // select prev tab if the closed tab is the last one
  if (index.value > 0) {
    --index.value;
  }
}
</script>

Validate before change

In case you need to validate something inside a tab before it being switch, a sample implementation using before-change prop:

vue
<template>
  <Tabs v-model="index" :before-change="onBeforeChange">
    <Tab title="Home">
      <div>
        <br />
        <form class="form-inline">
          <div class="form-group">
            <label for="exampleInputName">Name</label>
            <input
              id="exampleInputName"
              v-model="input"
              type="text"
              class="form-control"
              placeholder="Please fill this section"
            />
          </div>
        </form>
      </div>
    </Tab>
    <Tab title="Profile">
      <p>Profile tab.</p>
    </Tab>
    <Tab title="Others">
      <p>Others tab.</p>
    </Tab>
  </Tabs>
</template>

<script setup>
import { Tab, Tabs, Notification } from 'uiv';
import { ref } from 'vue';

const index = ref(0);
const input = ref('');

function onBeforeChange(indexFrom, indexTo, done) {
  if (indexFrom === 0 && input.value === '') {
    Notification.notify('Please fill your name first.');
    done(1);
  } else {
    done();
  }
}
</script>

API Reference

Tabs

Props

NameTypeDefaultRequiredDescription
v-modelNumberThe current tab index, use this to manual change tab index.
justifiedBooleanfalseUse justified style.
pillsBooleanfalseUse pills style.
stackedBooleanfalseUse stacked style, note that this have to work with pills.
transitionNumber150The tabs show / hide transition time in ms. Use 0 to disable transitions.
custom-nav-classApply custom classes to the tab nav, could be Object or String.
custom-content-classApply custom classes to the tab content, could be Object or String.
before-changefunction(indexFrom, indexTo, done)Trigger before active tab change. Calling done() will allow the change. Calling done(err), where err is any value, will prevent it. Note that this callback will only trigger on tab clicking.

Slots

NameDescription
defaultThe tabs content.
nav-rightThe snip at right side of tab nav. Note: it won't display if using justified style.

Events

NameParamsDescription
changeindexTrigger after active tab changed, with the active index.
changedindexTrigger after tab changed and transition finished, with the active index.

Tab

Props

NameTypeDefaultRequiredDescription
titleStringThe tab title.
tab-classesObject{}Object where keys represent class and value is interpreted as a boolean to indicate whether the class should be shown
disabledBooleanfalseDisable the tab.
groupStringTabs nav with same group will in a dropdown list.
pull-rightBooleanfalseAdd pull-right class to the tab nav. A grouped tab will be pull to right if one of its sub-tabs has this prop set to true.
hiddenBooleanfalseHide the tab, use this prop because v-show doesn't work on Tab component.

Slots

NameDescription
titleTitle slot. This will override title or html-title prop if exist.

Released under the MIT License.