---
title: Tabs
description: Tabbed interface for switching between panels of content.
icon: window-restore
---

import { ComponentPreview } from '/snippets/component-preview.mdx'

Tabs organize content into panels that users switch between by clicking triggers. Each `Tab` child defines a trigger label and the content shown when that tab is active.

## Basic Usage

<ComponentPreview json={{"view":{"name":"tabs_1","value":"account","type":"Tabs","variant":"default","orientation":"horizontal","children":[{"type":"Tab","title":"Account","value":"account","disabled":false,"children":[{"type":"Card","children":[{"type":"CardHeader","children":[{"type":"CardTitle","content":"Account"},{"type":"CardDescription","content":"Make changes to your account here."}]},{"type":"CardContent","children":[{"cssClass":"gap-3","type":"Column","children":[{"type":"Label","text":"Name"},{"name":"input_18","type":"Input","inputType":"text","placeholder":"Your name","disabled":false,"readOnly":false,"required":false}]}]}]}]},{"type":"Tab","title":"Password","value":"password","disabled":false,"children":[{"type":"Card","children":[{"type":"CardHeader","children":[{"type":"CardTitle","content":"Password"},{"type":"CardDescription","content":"Change your password here."}]},{"type":"CardContent","children":[{"cssClass":"gap-3","type":"Column","children":[{"type":"Label","text":"Current Password"},{"name":"input_19","type":"Input","inputType":"password","disabled":false,"readOnly":false,"required":false},{"type":"Label","text":"New Password"},{"name":"input_20","type":"Input","inputType":"password","disabled":false,"readOnly":false,"required":false}]}]}]}]}]},"state":{"tabs_1":"account"}}} playground=" ">
<CodeGroup>
```python Python icon="python"
from prefab_ui.components import (
    Card,
    CardContent,
    CardDescription,
    CardHeader,
    CardTitle,
    Column,
    Input,
    Label,
    Tab,
    Tabs,
)

with Tabs(value="account"):
    with Tab("Account", value="account"):
        with Card():
            with CardHeader():
                CardTitle("Account")
                CardDescription("Make changes to your account here.")
            with CardContent():
                with Column(gap=3):
                    Label("Name")
                    Input(placeholder="Your name")
    with Tab("Password", value="password"):
        with Card():
            with CardHeader():
                CardTitle("Password")
                CardDescription("Change your password here.")
            with CardContent():
                with Column(gap=3):
                    Label("Current Password")
                    Input(input_type="password")
                    Label("New Password")
                    Input(input_type="password")
```
```json Protocol icon="brackets-curly"
{
  "view": {
    "name": "tabs_1",
    "value": "account",
    "type": "Tabs",
    "variant": "default",
    "orientation": "horizontal",
    "children": [
      {
        "type": "Tab",
        "title": "Account",
        "value": "account",
        "disabled": false,
        "children": [
          {
            "type": "Card",
            "children": [
              {
                "type": "CardHeader",
                "children": [
                  {"type": "CardTitle", "content": "Account"},
                  {"type": "CardDescription", "content": "Make changes to your account here."}
                ]
              },
              {
                "type": "CardContent",
                "children": [
                  {
                    "cssClass": "gap-3",
                    "type": "Column",
                    "children": [
                      {"type": "Label", "text": "Name"},
                      {
                        "name": "input_18",
                        "type": "Input",
                        "inputType": "text",
                        "placeholder": "Your name",
                        "disabled": false,
                        "readOnly": false,
                        "required": false
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "Tab",
        "title": "Password",
        "value": "password",
        "disabled": false,
        "children": [
          {
            "type": "Card",
            "children": [
              {
                "type": "CardHeader",
                "children": [
                  {"type": "CardTitle", "content": "Password"},
                  {"type": "CardDescription", "content": "Change your password here."}
                ]
              },
              {
                "type": "CardContent",
                "children": [
                  {
                    "cssClass": "gap-3",
                    "type": "Column",
                    "children": [
                      {"type": "Label", "text": "Current Password"},
                      {
                        "name": "input_19",
                        "type": "Input",
                        "inputType": "password",
                        "disabled": false,
                        "readOnly": false,
                        "required": false
                      },
                      {"type": "Label", "text": "New Password"},
                      {
                        "name": "input_20",
                        "type": "Input",
                        "inputType": "password",
                        "disabled": false,
                        "readOnly": false,
                        "required": false
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  },
  "state": {"tabs_1": "account"}
}
```
</CodeGroup>
</ComponentPreview>

## Variants

The `variant` prop controls the visual style of the tab triggers. The default uses a pill-style background, while `"line"` uses an underline indicator.

<ComponentPreview json={{"view":{"cssClass":"gap-16 w-fit mx-auto","type":"Column","children":[{"name":"tabs_2","value":"one","type":"Tabs","variant":"default","orientation":"horizontal","children":[{"type":"Tab","title":"Mostly","value":"one","disabled":false,"children":[{"content":"Don't panic.","type":"Text"}]},{"type":"Tab","title":"Harmless","value":"two","disabled":false,"children":[{"content":"It's a wholly remarkable book.","type":"Text"}]},{"type":"Tab","title":"Guide","value":"three","disabled":false,"children":[{"content":"A towel is the most massively useful thing.","type":"Text"}]}]},{"name":"tabs_3","value":"one","type":"Tabs","variant":"line","orientation":"horizontal","children":[{"type":"Tab","title":"Mostly","value":"one","disabled":false,"children":[{"content":"Don't panic.","type":"Text"}]},{"type":"Tab","title":"Harmless","value":"two","disabled":false,"children":[{"content":"It's a wholly remarkable book.","type":"Text"}]},{"type":"Tab","title":"Guide","value":"three","disabled":false,"children":[{"content":"A towel is the most massively useful thing.","type":"Text"}]}]}]},"state":{"tabs_2":"one","tabs_3":"one"}}} playground=" ">
<CodeGroup>
```python Python icon="python"
from prefab_ui.components import Column, Tab, Tabs, Text

with Column(gap=16, css_class="w-fit mx-auto"):
    with Tabs(value="one"):
        with Tab("Mostly", value="one"):
            Text("Don't panic.")
        with Tab("Harmless", value="two"):
            Text("It's a wholly remarkable book.")
        with Tab("Guide", value="three"):
            Text("A towel is the most massively useful thing.")

    with Tabs(variant="line", value="one"):
        with Tab("Mostly", value="one"):
            Text("Don't panic.")
        with Tab("Harmless", value="two"):
            Text("It's a wholly remarkable book.")
        with Tab("Guide", value="three"):
            Text("A towel is the most massively useful thing.")
```
```json Protocol icon="brackets-curly"
{
  "view": {
    "cssClass": "gap-16 w-fit mx-auto",
    "type": "Column",
    "children": [
      {
        "name": "tabs_2",
        "value": "one",
        "type": "Tabs",
        "variant": "default",
        "orientation": "horizontal",
        "children": [
          {
            "type": "Tab",
            "title": "Mostly",
            "value": "one",
            "disabled": false,
            "children": [{"content": "Don't panic.", "type": "Text"}]
          },
          {
            "type": "Tab",
            "title": "Harmless",
            "value": "two",
            "disabled": false,
            "children": [{"content": "It's a wholly remarkable book.", "type": "Text"}]
          },
          {
            "type": "Tab",
            "title": "Guide",
            "value": "three",
            "disabled": false,
            "children": [{"content": "A towel is the most massively useful thing.", "type": "Text"}]
          }
        ]
      },
      {
        "name": "tabs_3",
        "value": "one",
        "type": "Tabs",
        "variant": "line",
        "orientation": "horizontal",
        "children": [
          {
            "type": "Tab",
            "title": "Mostly",
            "value": "one",
            "disabled": false,
            "children": [{"content": "Don't panic.", "type": "Text"}]
          },
          {
            "type": "Tab",
            "title": "Harmless",
            "value": "two",
            "disabled": false,
            "children": [{"content": "It's a wholly remarkable book.", "type": "Text"}]
          },
          {
            "type": "Tab",
            "title": "Guide",
            "value": "three",
            "disabled": false,
            "children": [{"content": "A towel is the most massively useful thing.", "type": "Text"}]
          }
        ]
      }
    ]
  },
  "state": {"tabs_2": "one", "tabs_3": "one"}
}
```
</CodeGroup>
</ComponentPreview>

## Orientation

Set `orientation="vertical"` to stack the tab triggers in a column alongside the content.

<ComponentPreview json={{"view":{"cssClass":"gap-16 w-48 mx-auto","type":"Column","children":[{"name":"tabs_4","value":"one","type":"Tabs","variant":"default","orientation":"vertical","children":[{"type":"Tab","title":"Mostly","value":"one","disabled":false,"children":[{"content":"Don't panic.","type":"Text"}]},{"type":"Tab","title":"Harmless","value":"two","disabled":false,"children":[{"content":"It's a wholly remarkable book.","type":"Text"}]},{"type":"Tab","title":"Guide","value":"three","disabled":false,"children":[{"content":"A towel is the most massively useful thing.","type":"Text"}]}]},{"name":"tabs_5","value":"one","type":"Tabs","variant":"line","orientation":"vertical","children":[{"type":"Tab","title":"Mostly","value":"one","disabled":false,"children":[{"content":"Don't panic.","type":"Text"}]},{"type":"Tab","title":"Harmless","value":"two","disabled":false,"children":[{"content":"It's a wholly remarkable book.","type":"Text"}]},{"type":"Tab","title":"Guide","value":"three","disabled":false,"children":[{"content":"A towel is the most massively useful thing.","type":"Text"}]}]}]},"state":{"tabs_4":"one","tabs_5":"one"}}} playground=" ">
<CodeGroup>
```python Python icon="python"
from prefab_ui.components import Column, Tab, Tabs, Text

with Column(gap=16, css_class="w-48 mx-auto"):
    with Tabs(orientation="vertical", value="one"):
        with Tab("Mostly", value="one"):
            Text("Don't panic.")
        with Tab("Harmless", value="two"):
            Text("It's a wholly remarkable book.")
        with Tab("Guide", value="three"):
            Text("A towel is the most massively useful thing.")

    with Tabs(variant="line", orientation="vertical", value="one"):
        with Tab("Mostly", value="one"):
            Text("Don't panic.")
        with Tab("Harmless", value="two"):
            Text("It's a wholly remarkable book.")
        with Tab("Guide", value="three"):
            Text("A towel is the most massively useful thing.")
```
```json Protocol icon="brackets-curly"
{
  "view": {
    "cssClass": "gap-16 w-48 mx-auto",
    "type": "Column",
    "children": [
      {
        "name": "tabs_4",
        "value": "one",
        "type": "Tabs",
        "variant": "default",
        "orientation": "vertical",
        "children": [
          {
            "type": "Tab",
            "title": "Mostly",
            "value": "one",
            "disabled": false,
            "children": [{"content": "Don't panic.", "type": "Text"}]
          },
          {
            "type": "Tab",
            "title": "Harmless",
            "value": "two",
            "disabled": false,
            "children": [{"content": "It's a wholly remarkable book.", "type": "Text"}]
          },
          {
            "type": "Tab",
            "title": "Guide",
            "value": "three",
            "disabled": false,
            "children": [{"content": "A towel is the most massively useful thing.", "type": "Text"}]
          }
        ]
      },
      {
        "name": "tabs_5",
        "value": "one",
        "type": "Tabs",
        "variant": "line",
        "orientation": "vertical",
        "children": [
          {
            "type": "Tab",
            "title": "Mostly",
            "value": "one",
            "disabled": false,
            "children": [{"content": "Don't panic.", "type": "Text"}]
          },
          {
            "type": "Tab",
            "title": "Harmless",
            "value": "two",
            "disabled": false,
            "children": [{"content": "It's a wholly remarkable book.", "type": "Text"}]
          },
          {
            "type": "Tab",
            "title": "Guide",
            "value": "three",
            "disabled": false,
            "children": [{"content": "A towel is the most massively useful thing.", "type": "Text"}]
          }
        ]
      }
    ]
  },
  "state": {"tabs_4": "one", "tabs_5": "one"}
}
```
</CodeGroup>
</ComponentPreview>

## State Tracking

Give Tabs a `name` to sync the active tab with client state. Other components can then read or change which tab is active — useful for building wizard flows or linking navigation between different parts of the UI.

```python Tabs with State
from prefab_ui.components import Button, Column, Row, Tab, Tabs, Text
from prefab_ui.actions import SetState

with Column(gap=4):
    with Tabs(name="activeTab", value="general"):
        with Tab("General", value="general"):
            Text("General settings here.")
        with Tab("Advanced", value="advanced"):
            Text("Advanced settings here.")

    with Row(gap=2):
        Button("Go to General", on_click=SetState("activeTab", "general"))
        Button("Go to Advanced", on_click=SetState("activeTab", "advanced"))
```

## API Reference

<Card icon="code" title="Tabs Parameters">
<ParamField body="variant" type="str" default="default">
  Visual style: `"default"` (pill background) or `"line"` (underline indicator).
</ParamField>

<ParamField body="orientation" type="str" default="horizontal">
  Layout direction: `"horizontal"` (triggers above content) or `"vertical"` (triggers beside content).
</ParamField>

<ParamField body="value" type="str | None" default="None">
  Value of the initially active tab. If omitted, the first tab is active.
</ParamField>

<ParamField body="name" type="str | None" default="None">
  State key for tracking the active tab. Enables reading/writing the active tab from other components.
</ParamField>

<ParamField body="on_change" type="Action | list[Action] | None" default="None">
  Action(s) triggered when the active tab changes.
</ParamField>

<ParamField body="css_class" type="str | None" default="None">
  Additional Tailwind CSS classes.
</ParamField>
</Card>

<Card icon="code" title="Tab Parameters">
<ParamField body="title" type="str" required>
  Tab trigger label. Can be passed as a positional argument.
</ParamField>

<ParamField body="value" type="str | None" default="None">
  Unique value identifying this tab. Defaults to the title.
</ParamField>

<ParamField body="disabled" type="bool" default="False">
  Whether this tab is disabled.
</ParamField>
</Card>

## Protocol Reference

```json Tabs
{
  "type": "Tabs",
  "children?": "[Component]",
  "let?": "object",
  "name?": "string",
  "variant?": "default | line",
  "value?": "string",
  "orientation?": "horizontal | vertical",
  "onChange?": "Action | Action[]",
  "cssClass?": "string"
}
```

```json Tab
{
  "type": "Tab",
  "children?": "[Component]",
  "let?": "object",
  "title": "string (required)",
  "value?": "string",
  "disabled?": false,
  "cssClass?": "string"
}
```

For the complete protocol schema, see [Tabs](/protocol/tabs), [Tab](/protocol/tab).
