# Tabs

> Panels switched by tabs.

## Examples

### Basic

```vue
<script setup lang="ts">
const tab = ref("overview");
const tabs = [
  { label: "Overview", value: "overview" },
  { label: "Activity", value: "activity" },
  { label: "Settings", value: "settings" },
  { label: "Billing", value: "billing", disabled: true },
];
</script>

<template>
  <UiTabs v-model="tab" :items="tabs" label="Project" class="demo-wide" v-slot="{ value }">
    <p v-if="value === 'overview'">A summary of the project.</p>
    <p v-else-if="value === 'activity'">Recent commits and comments.</p>
    <p v-else>Name, visibility and danger zone.</p>
  </UiTabs>
</template>
```

### Counts

The `tab` slot replaces each tab's text, e.g. to add a count.

```vue
<script setup lang="ts">
const tab = ref("open");
const tabs = [
  { label: "Open", value: "open", count: 12 },
  { label: "In review", value: "review", count: 3 },
  { label: "Closed", value: "closed", count: 148 },
];
const countOf = (value?: string) => tabs.find((t) => t.value === value)?.count;
</script>

<template>
  <UiTabs v-model="tab" :items="tabs" label="Issues" class="demo-wide">
    <template #tab="{ item, selected }">
      {{ item.label }}
      <span class="tab-count" :data-selected="selected || undefined">{{
        countOf(item.value)
      }}</span>
    </template>
    <template #default="{ value }">
      <p>{{ countOf(value) }} issues.</p>
    </template>
  </UiTabs>
</template>
```

## API

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `items` | `SelectOption<T>[]` | `[]` | Tabs to render, in order. |
| `label` | `string` | — | Accessible name for the tablist. |
| `disabled` | `boolean` | `false` | Disables every tab. |
| `modelValue` | `T` | — | The selected tab's value. |

| Event | Payload | Description |
| --- | --- | --- |
| `update:modelValue` | `[value: T \| undefined]` | `v-model:modelValue` update. |

| Slot | Props | Description |
| --- | --- | --- |
| `default` | `{ value: T \| undefined; }` | Panel content for the selected tab. |
| `tab` | `{ item: SelectOption<T>; selected: boolean; }` | Tab content. |

Types:

```ts
export interface SelectOption<T extends SelectValue = SelectValue> {
  label: string;
  value: T;
  disabled?: boolean;
}

export type SelectValue = string | number;
```

## Styling

`--ui-indicator-x`, `--ui-indicator-width`, `--ui-indicator-top` and `--ui-indicator-height` place the indicator on the selected item.

- Parts (`[data-part="…"]`): `tabs`, `tablist`, `tab-indicator`, `tab`, `tabpanel`
- State attributes: `data-tabs-sliding`, `data-tabs-animate`, `data-tab-selected`

## Keyboard

| Keys           | Action                                 |
| -------------- | -------------------------------------- |
| `Tab`          | Focus the selected tab, then the panel |
| `←` / `→`      | Select the previous / next tab         |
| `Home` / `End` | Select the first / last tab            |

## Accessibility

- In right-to-left layouts, `←` / `→` follow the visual direction.
