---
title: "MazTabs"
description: "MazTabs is a standalone component to display content in tabs with animations"
package: "maz-ui"
url: "https://maz-ui.com/components/maz-tabs"
---

# MazTabs

> MazTabs is a standalone component to display content in tabs with animations

- Package: `maz-ui`
- Import: `import MazTabs from 'maz-ui/components/MazTabs'` or `import MazTabsBar from 'maz-ui/components/MazTabsBar'` or `import MazTabsContent from 'maz-ui/components/MazTabsContent'` or `import MazTabsContentItem from 'maz-ui/components/MazTabsContentItem'`
- Nuxt: auto-imported by `@maz-ui/nuxt`, no import needed in a Nuxt app
- Web: https://maz-ui.com/components/maz-tabs

## Basic usage

```vue
<script lang="ts" setup>
import { MazTabs, MazTabsBar, type MazTabsBarItem, MazTabsContent, MazTabsContentItem } from 'maz-ui/components'

const tabs: MazTabsBarItem[] = [
  { label: 'First Tab', disabled: false },
  { label: 'Second Tab', disabled: false, badge: { color: 'destructive', content: 1, roundedSize: 'full' } },
  { label: 'Third Tab', disabled: true },
]
</script>

<template>
  <MazTabs>
    <MazTabsBar :items="tabs" />

    <MazTabsContent>
      <MazTabsContentItem :tab="1" class="py-4">
        Tab 1
      </MazTabsContentItem>
      <MazTabsContentItem :tab="2" class="py-4">
        Tab 2
      </MazTabsContentItem>
      <MazTabsContentItem :tab="3" class="py-4">
        Tab 3
      </MazTabsContentItem>
    </MazTabsContent>
  </MazTabs>
</template>
```

## With model-value

**Details: View code**

```vue
<script lang="ts" setup>
import { ref } from 'vue'

const currentTab = ref(2)

const tabs: MazTabsBarItem[] = ['First Tab', 'Second Tab', 'Third Tab']
</script>

<template>
  <MazTabs v-model="currentTab">
    <MazTabsBar :items="tabs" />

    <MazTabsContent>
      <MazTabsContentItem :tab="1" class="py-4">
        Tab 1
      </MazTabsContentItem>
      <MazTabsContentItem :tab="2" class="py-4">
        Tab 2
      </MazTabsContentItem>
      <MazTabsContentItem :tab="3" class="py-4">
        Tab 3
      </MazTabsContentItem>
    </MazTabsContent>
  </MazTabs>

  <br>

  <MazBtn @click="currentTab = currentTab === 1 ? 2 : 1">
    Set model-value to {{ currentTab === 1 ? 2 : 1 }}
  </MazBtn>
</template>
```

## Persistent tab

To keep the tab current when the page reloads, you can use the `persistent` props on the component `<MazTabsBar />`.

The component will save the current table index in the URL of the page via a query parameter.

You can choose the name of this query parameter with the props `query-param` `@default 'tab'`

## Custom tabs with slot

```html
<MazTabs>
  <MazTabsBar :items="tabs">
    <template #item="{ item, index, active }">
      {{ item.label }}

      <MazBadge size="mini" rounded-size="full" :color="active ? 'primary' : 'transparent'"> {{ index }} </MazBadge>
    </template>
  </MazTabsBar>
</MazTabs>
```

## Size and rounded size

Each tab is rendered with a [`MazBtn`](./maz-btn.md), so you can control its `size` (`MazSize`) and `rounded-size` (`MazRoundedSize`, applied to the bar, the indicator and each tab).

These props can be set on `MazTabsBar` directly, or on `MazTabs` which forwards them to its `MazTabsBar`. They are also globalizable through the [global defaults](../guide/global-defaults.md) (`MazTabsBar` or `global` entry).

```vue
<template>
  <!-- size & rounded-size forwarded from MazTabs to MazTabsBar -->
  <MazTabs size="sm" rounded-size="lg">
    <MazTabsBar :items="tabs" />
    <!-- ... -->
  </MazTabs>

  <!-- or directly on MazTabsBar -->
  <MazTabsBar :items="tabs" size="lg" rounded-size="full" />
</template>
```

Each item can also override the `size` and `rounded-size` (and accepts every other [`MazBtn`](./maz-btn.md) prop, except `active`, `block`, `type`, `loading` and `fab`).

## Active color

The active tab is highlighted by the indicator. Use the `color` prop (`MazColor`) on `MazTabsBar` (or on `MazTabs`, which forwards it) to color it. When omitted, the default neutral indicator is used.

```vue
<template>
  <MazTabsBar :items="tabs" color="primary" />
</template>
```

## Standalone usage

`MazTabsBar` can be used on its own, without `MazTabs`, as an independent switcher with its own `v-model`.

**Tip: Nested inside a `MazTabs`**

If your page is already wrapped by a `MazTabs`, a nested `MazTabsBar` would otherwise be linked to that parent (clicking a tab would change the page). Add the `standalone` prop to make it fully independent (it then ignores the parent's selection, size, rounded-size and color):

```vue
<MazTabsBar v-model="selected" :items="items" standalone />
```

The model returns the `1`-based index of the selected tab, unless the items provide a `value` (`string | number`), in which case that value is returned. The model type is inferred from the items passed: declare the items `as const` (or with literal `value`s) to get a strict union type for the model and the `@update:model-value` event.

```vue
<script lang="ts" setup>
import { MazTabsBar, type MazTabsBarItem } from 'maz-ui/components'
import { ref } from 'vue'

const selected = ref('weekly')

const items = [
  { label: 'Daily', value: 'daily' },
  { label: 'Weekly', value: 'weekly' },
  { label: 'Monthly', value: 'monthly' },
] as const satisfies readonly MazTabsBarItem[]
</script>

<template>
  <MazTabsBar v-model="selected" :items="items" color="secondary" rounded-size="full" />
  <!-- selected & @update:model-value === 'daily' | 'weekly' | 'monthly' -->
</template>
```

When no `value` is set on the items, the model is a number (the `1`-based index):

```vue
<script lang="ts" setup>
const selected = ref(1)
const items = ['First', 'Second', 'Third']
</script>

<template>
  <MazTabsBar v-model="selected" :items="items" />
  <!-- selected === 1 | 2 | 3 -->
</template>
```

## Types

```ts
type MazTabsBarItem<Value extends string | number = string | number>
  // Inherits all MazBtn props except 'active' | 'block' | 'type' | 'loading' | 'fab'
  = | (Omit<MazBtnProps, 'active' | 'block' | 'type' | 'loading' | 'fab'> & {
    /**
     * Label of the tab
     */
    label: string
    /**
     * Value returned by the model when the tab is selected (standalone usage).
     * When omitted, the model returns the 1-based index of the tab.
     */
    value?: Value
    /**
     * Will disable the tab
     * @default false
     */
    disabled?: boolean
    /**
     * Badge to display in the tab
     * Inherit all props of MazBadge component
     */
    badge?: MazBadgeProps & {
      /**
       * Content of the badge
       */
      content: string | number | boolean
    }
  })
  | string
```

## Accessibility

The tabs follow the [WAI-ARIA tabs pattern](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/):

- `MazTabsBar` is a `tablist` (pass an `aria-label` to name it), each item is a `tab` with `aria-selected`, linked to its `MazTabsContentItem` (`tabpanel`) through `aria-controls` / `aria-labelledby`.
- **Keyboard**: only the selected tab is in the tab sequence, ← / → select the previous / next tab (reversed in RTL), Home / End the first / last one. Disabled tabs are skipped.

## Props & Events emitted

## MazTabs

## MazTabs API

`import MazTabs from 'maz-ui/components/MazTabs'`

### Props

- `model-value` (`number`, `v-model`): The the selected tab number.
- `size` (`"xs" | "sm" | "md" | "lg" | "xl" | "mini"`): Size of the tabs, forwarded to MazTabsBar (and each tab button).
- `rounded-size` (`MazRoundedSize`): Size of the rounded, forwarded to MazTabsBar. Values: `'none'`, `'sm'`, `'md'`, `'lg'`, `'xl'`, `'full'` (non exhaustive).
- `color` (`"primary" | "secondary" | "accent" | "info" | "success" | "warning" | "destructive" | "contrast" | "transparent"`): Color of the active tab indicator, forwarded to MazTabsBar.

### Events

- `@update:model-value` (payload: `value: number`): Emitted when the selected tab change

### Slots

- `#default`

## MazTabsBar

## MazTabsBar API

`import MazTabsBar from 'maz-ui/components/MazTabsBar'`

### Props

- `items` (`readonly Item[]`, required): The items to display in the tabs bar.
- `model-value` (`MazTabsBarItemValue<Item>`, `v-model`): Selected tab (standalone usage, without MazTabs). Holds the item `value` when provided, otherwise the 1-based index. Pass items `as const` (or with literal `value`) to infer a union type.
- `size` (`"xs" | "sm" | "md" | "lg" | "xl" | "mini"`, default: `'md'`): Size of the tabs (forwarded to each MazBtn).
- `rounded-size` (`MazRoundedSize`, default: `'md'`): Size of the rounded applied to the bar, the indicator and each tab. Values: `'none'`, `'sm'`, `'md'`, `'lg'`, `'xl'`, `'full'` (non exhaustive).
- `color` (`"primary" | "secondary" | "accent" | "info" | "success" | "warning" | "destructive" | "contrast" | "transparent"`): Color of the active tab indicator. When omitted, the default neutral indicator is used.
- `standalone` (`boolean`, default: `false`): Force the standalone mode: the tabs bar ignores any surrounding `MazTabs` (selection, size, rounded-size and color are no longer inherited) and is driven only by its own `v-model`. Useful for a nested switcher inside a page already wrapped by `MazTabs`.
- `persistent` (`boolean`, default: `false`): Will add a query param to the url to keep the selected tab on page refresh.
- `query-param` (`string`, default: `"tab"`): The name of the query param to add to the url.
- `block` (`boolean`, default: `false`): Will make the tabs bar full width.
- `elevation` (`boolean`, default: `false`): Will remove the elevation.
- `auto-scroll` (`boolean`, default: `true`): Will add a scroll on the tabs bar to show selected element.
- `bordered` (`boolean`, default: `true`): Will add a border to the tabs bar.

### Events

- `@update:model-value` (payload: `value: MazTabsBarItemValue<Item>`): Emitted when the selected tab changes (standalone usage).

### Slots

- `#item`: Content of item to display in the tabs bar Bindings: `item: { label: Item & string; value: string | number | undefined; disabled: boolean; size: "xs" | "sm" | "md" | "lg" | "xl" | "mini" | undefined; roundedSize: MazRoundedSize | undefined; color: NonNullable<"primary" | "secondary" | "accent" | ...` (all data of the item), `active: boolean` (`true` if the tab is active), `index: number` (index of the item).
- `#badge-content`: Content in the badge Bindings: `content: string | number | boolean` (content of the badge provided in item).

## MazTabsContent

## MazTabsContent API

`import MazTabsContent from 'maz-ui/components/MazTabsContent'`

### Props

No props.

### Slots

- `#default`

## MazTabsContentItem

## MazTabsContentItem API

`import MazTabsContentItem from 'maz-ui/components/MazTabsContentItem'`

### Props

- `tab` (`number`, required)

### Slots

- `#default`
