Vue/Nuxt + ChakraUI: Tabs
Tags: vue, javascript, nuxt, chakra
Published: 2020-12-07 04:08:08

![Chakra UI logo](https://dev-to-uploads.s3.amazonaws.com/i/mgvh8h79eq3kk6wxr1d3.png)

I have been working with Chakra UI Vue for several months. I am using Chakra in a side project to learn more about JAMStack and Vue/Nuxt. I am drawn to Chakra UI because of its practical set of components, and its focus on accessibility. This is the first article in a series I will be publishing about Vue and Chakra. I hope you enjoy!

One of the components I have been working with a lot is the tabs component. Tabs works well when presenting content. I have also been using it to driver high-level option selection for specific processes and user flows. Let's jump right in...

*This post assumes you already have a Nuxt project setup with Chakra installed, as well as auto-imports enabled.* 

The standard way of setting up tabs using Chakra is using a parent `c-tabs` element, containing a single `c-tab-list` and single `c-tab-panels` element.

```html
<c-box>
    <c-tabs>
        <c-tab-list>
        <c-tab>One</c-tab>
        <c-tab>Two</c-tab>
        <c-tab>Three</c-tab>
        </c-tab-list>
        <c-tab-panels>
        <c-tab-panel>
            <p>one!</p>
        </c-tab-panel>
        <c-tab-panel>
            <p>two!</p>
        </c-tab-panel>
        <c-tab-panel>
            <p>three!</p>
        </c-tab-panel>
        </c-tab-panels>
    </c-tabs>
</c-box>
```

It is important to ensure you have the same number of `c-tab-panel` elements as you do `c-tab` elements. Not doing so may mean your content is not accessible to the user. The order is also critical to this working, as the first `c-tab` button will correspond to the first `c-tab-panel` element. This is quick to get up and running. Note, each `c-tab` becomes a button when it renders.

In addition to the separation of content, I also want to know which tab a user has selected. To do this I recommend moving to a different pattern. This pattern involves moving the tab options to an array and then using Vues `v-for` directive look to generate the `c-tab-list` elements. 

```html
<c-box>
    <c-tabs>
        <c-tab-list>
        <c-tab v-for="tab in tabs" :key="tab">{{
            tab
          }}</c-tab>
        </c-tab-list>
...
    </c-tabs>
</c-box>
```

We have now introduced a new data object here.. `tabs`. Lets set it up so the above code works:

```jsx
data() {
    return {
      tabs: ['One', 'Two', 'Three'],
      tabIndex: 0,
    }
  },
```

We then call a method on the `@change` event, to change the tabIndex value:

```jsx
 <c-tabs @change="setTabIndex">
	 <c-tab-list>...

...
methods: {
	setTabIndex(index) {
      this.tabIndex = index
    },
}
```

As things are now, `tabIndex` will change as the user selects a different tab, but we don't yet know which option the user has selected, just its index value. To may the index value, back to the array, we then use a computed property to give us the selected tab text:

```jsx
computed: {
    selectedTab() {
      return this.tabs[this.tabIndex]
    },
}
```

We now have the `selectedTab`, and `tabIndex` values in the parent component, which we can used to drive other behaviour.

For one final feature, we can then drive the default index, property in the c-tabs element using the tabIndex field:

```html
<c-tabs :default-index="tabIndex" @change="setTabIndex" >
```

By doing this, you can set the initial tab selection. 

# Limitations of this approach

Your c-tab styling needs to be simple. Adding images or icons to your tab may over-complicate things. When using library components like this, keep it simple.

Another limitation may present itself if you want to enable/disable a tab. In this case, the following pattern works better.
## Alternative

To enable a  single tab to be disabled, the following approach can be applied.

```jsx
 <c-tab-list>
    <c-tab>{{ tabs[0] }}</c-tab>
    <c-tab :is-disabled="tabTwoDisabled">{{ tabs[1] }}</c-tab>
    <c-tab>{{ tabs[2] }}</c-tab>
 </c-tab-list>

data() {
    return {
      tabs: ['One', 'Two', 'Three'],
      tabIndex: 0,
      tabTwoDisabled: false,
    }
  },
```
This maintains the array of options, but gives the programmer the ability to enable/disable a single tab.

# Summary

Chakra's tabs are a joy to work with, as long as you keep it simple. If you also want to know the current active tab, then the above pattern works well. 

## Links

- [Chakra ui - tabs](https://vue.chakra-ui.com/tabs)
- [Chakra ui - auto imports] (https://vue.chakra-ui.com/auto-import-components)