# Tabs

**A component for toggling between related panels on the same page.**

**Reference:** [View Source](https://github.com/jramke/fluid-primitives/tree/main/Resources/Private/Primitives/Tabs) · [Zag.js Docs](https://zagjs.com/components/react/tabs)

**Tabs.html**

```html
<ui:tabs.root defaultValue="tab1">
    <ui:tabs.list class="mb-3">
        <ui:tabs.trigger value="tab1">Account</ui:tabs.trigger>
        <ui:tabs.trigger value="tab2">Password</ui:tabs.trigger>
        <ui:tabs.trigger value="tab3">Settings</ui:tabs.trigger>
    </ui:tabs.list>
    <ui:tabs.content value="tab1">
        <div class="aspect-video w-84 rounded-md border-dashed border p-4 text-sm grid place-items-center text-center">
            Manage your account settings and preferences.
        </div>
    </ui:tabs.content>
    <ui:tabs.content value="tab2">
        <div class="aspect-video w-84 rounded-md border-dashed border p-4 text-sm grid place-items-center text-center">
            Change your password and other security options.
        </div>
    </ui:tabs.content>
    <ui:tabs.content value="tab3">
        <div class="aspect-video w-84 rounded-md border-dashed border p-4 text-sm grid place-items-center text-center">
            Configure your application settings and preferences.
        </div>
    </ui:tabs.content>
</ui:tabs.root>
```

**Tabs.ts**

```ts
import { mountAll } from 'fluid-primitives';
import { Tabs } from 'fluid-primitives/tabs';

mountAll('tabs', ({ props }) => {
    const tabs = new Tabs(props);
    tabs.init();
    return tabs;
});

```

## Features

- Full keyboard navigation support with arrow keys
- Supports horizontal and vertical orientations
- Supports automatic and manual tab activation modes
- Content is lazy mounted by default
- Supports disabled tabs

## Installation

```bash
typo3 ui:add tabs
```

Or copy the files manually from GitHub (https://github.com/jramke/fluid-primitives.com/tree/main/packages/docs/Resources/Private/Registry/Tabs) into your project.

Read more about installing [Components and Primitives](/docs/core-concepts/primitives.md).

## Examples

### Vertical Orientation

Display tabs in a vertical layout.

**Tabs.html**

```html
<ui:tabs.root defaultValue="tab1" orientation="{f:constant(name: 'Jramke\FluidPrimitives\Enum\Orientation::Vertical')}" class="flex gap-4">
    <ui:tabs.list class="flex-col h-auto items-end">
        <ui:tabs.trigger value="tab1">Account</ui:tabs.trigger>
        <ui:tabs.trigger value="tab2">Password</ui:tabs.trigger>
        <ui:tabs.trigger value="tab3">Settings</ui:tabs.trigger>
    </ui:tabs.list>
    <div class="flex-1">
        <ui:tabs.content value="tab1">
            <div class="aspect-video w-84 rounded-md border-dashed border p-4 text-sm grid place-items-center text-center">
                Manage your account settings and preferences.
            </div>
        </ui:tabs.content>
        <ui:tabs.content value="tab2">
            <div class="aspect-video w-84 rounded-md border-dashed border p-4 text-sm grid place-items-center text-center">
                Change your password and other security options.
            </div>
        </ui:tabs.content>
        <ui:tabs.content value="tab3">
            <div class="aspect-video w-84 rounded-md border-dashed border p-4 text-sm grid place-items-center text-center">
                Configure your application settings and preferences.
            </div>
        </ui:tabs.content>
    </div>
</ui:tabs.root>

```

### Disabled Tabs

Disable specific tabs to prevent interaction.

**Tabs.html**

```html
<ui:tabs.root defaultValue="tab1">
    <ui:tabs.list class="mb-3">
        <ui:tabs.trigger value="tab1">Enabled 1</ui:tabs.trigger>
        <ui:tabs.trigger value="tab2" disabled="{true}">Disabled</ui:tabs.trigger>
        <ui:tabs.trigger value="tab3">Enabled 2</ui:tabs.trigger>
    </ui:tabs.list>
    <ui:tabs.content value="tab1">First tab content.</ui:tabs.content>
    <ui:tabs.content value="tab2">This tab is disabled.</ui:tabs.content>
    <ui:tabs.content value="tab3">Third tab content.</ui:tabs.content>
</ui:tabs.root>
```

### Manual Activation

Require pressing Enter or Space to activate tabs instead of activating on focus.

**Tabs.html**

```html
<ui:tabs.root defaultValue="tab1" activationMode="{f:constant(name: 'Jramke\FluidPrimitives\Enum\TabsActivationMode::Manual')}">
    <ui:tabs.list class="mb-3">
        <ui:tabs.trigger value="tab1">Tab 1</ui:tabs.trigger>
        <ui:tabs.trigger value="tab2">Tab 2</ui:tabs.trigger>
        <ui:tabs.trigger value="tab3">Tab 3</ui:tabs.trigger>
    </ui:tabs.list>
    <ui:tabs.content value="tab1">Press Enter to switch tabs.</ui:tabs.content>
    <ui:tabs.content value="tab2">Content for tab 2.</ui:tabs.content>
    <ui:tabs.content value="tab3">Content for tab 3.</ui:tabs.content>
</ui:tabs.root>

```

## API Reference

### tabs.root

Provides shared tabs state and wraps the tab list and panels. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `loopFocus` | `boolean` | No | `true` | Whether the keyboard navigation will loop from last tab to first, and vice versa. |
| `defaultValue` | `string` | No | `-` | The initial selected tab value when rendered. Use when you don't need to control the selected tab value. |
| `orientation` | `Enum\Orientation` | No | `Horizontal` | The orientation of the tabs. |
| `activationMode` | `Enum\TabsActivationMode` | No | `Automatic` | The activation mode of the tabs. |
| `composite` | `boolean` | No | `true` | Whether the tab is composite. |
| `deselectable` | `boolean` | No | `-` | Whether the active tab can be deselected when clicking on it. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `rootId` | `string` | No | `-` | The root ID of the component, used for hydration and identification. |
| `ids` | `array` | No | `[]` | The IDs of of the component parts for composition. |
| `controlled` | `boolean` | No | `false` | If true, the component is meant to be initialized manually inside another component |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | tabs |
| `data-part` | root |
| `data-orientation` | The orientation of the tabs |
| `data-focus` | Present when focused |

### tabs.list

Groups the tab triggers. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | tabs |
| `data-part` | list |
| `data-focus` | Present when focused |
| `data-orientation` | The orientation of the list |

### tabs.trigger

Activates a tab and focuses its panel. Renders a `<button>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `value` | `string` | Yes | `-` | The value of the tab. |
| `disabled` | `boolean` | No | `-` | Whether the tab is disabled. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | tabs |
| `data-part` | trigger |
| `data-orientation` | The orientation of the trigger |
| `data-disabled` | Present when disabled |
| `data-value` | The value of the item |
| `data-selected` | Present when selected |
| `data-focus` | Present when focused |
| `data-ssr` | Present when not rendered in the browser. Useful for ssr styling |

### tabs.indicator

Displays the active tab indicator. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | tabs |
| `data-part` | indicator |
| `data-orientation` | The orientation of the indicator |

### tabs.content

Displays the panel content for a tab. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `value` | `string` | Yes | `-` | The value of the tab. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-scope` | tabs |
| `data-part` | content |
| `data-selected` | Present when selected |
| `data-orientation` | The orientation of the content |

### Machine JavaScript API

| Name | Type | Description |
| --- | --- | --- |
| `value` | `string \| null` | The current value of the tabs. |
| `focusedValue` | `string \| null` | The value of the tab that is currently focused. |
| `setValue` | `(value: string) => void` | Sets the value of the tabs. |
| `clearValue` | `VoidFunction` | Clears the value of the tabs. |
| `setIndicatorRect` | `(value: string) => void` | Sets the indicator rect to the tab with the given value |
| `syncTabIndex` | `VoidFunction` | Synchronizes the tab index of the content element. Useful when rendering tabs within a select or combobox |
| `focus` | `VoidFunction` | Set focus on the selected tab trigger |
| `selectNext` | `(fromValue?: string) => void` | Selects the next tab |
| `selectPrev` | `(fromValue?: string) => void` | Selects the previous tab |
| `getTriggerState` | `(props: TriggerProps) => TriggerState` | Returns the state of the trigger with the given props |

### Accessibility

| Key | Description |
| --- | --- |
| `Tab`  | When focus moves onto the tabs, focuses the active trigger. When a trigger is focused, moves focus to the active content. |
| `ArrowDown`  | Moves focus to the next trigger in vertical orientation and activates its associated content. |
| `ArrowRight`  | Moves focus to the next trigger in horizontal orientation and activates its associated content. |
| `ArrowUp`  | Moves focus to the previous trigger in vertical orientation and activates its associated content. |
| `ArrowLeft`  | Moves focus to the previous trigger in horizontal orientation and activates its associated content. |
| `Home`  | Moves focus to the first trigger and activates its associated content. |
| `End`  | Moves focus to the last trigger and activates its associated content. |
| `Enter` `Space`  | In manual mode, when a trigger is focused, moves focus to its associated content. |

## Anatomy

```html
<primitives:tabs.root>
    <primitives:tabs.list>
        <primitives:tabs.trigger />
        <primitives:tabs.indicator />
    </primitives:tabs.list>
    <primitives:tabs.content />
</primitives:tabs.root>
```
