# Tabs (React Native)

> A scrollable tab bar with a sliding indicator, and its panels.

GramproKit for React Native · Display · Beta · Source: https://kit.gramproindia.com/native/docs/tabs

> **Beta:** React Native support is in beta. APIs may change or break between prereleases (npm tag `native`).

_Interactive demo:_ [open the live example](https://kit.gramproindia.com/native/docs/tabs). The example's source:

```tsx
import { useState } from "react";
import { Text } from "react-native";
import { useKitTheme } from "@/component-lib/shared/native";
import { Tab, TabList, TabPanel, Tabs } from "@/component-lib/tabs";
import { Section } from "./layout"; // Section and Row: page layout for the demo

function Body({ children }: { children: string }) {
  const { tokens } = useKitTheme();
  return <Text style={{ color: tokens.fg, fontSize: tokens.fontSize, paddingVertical: 8 }}>{children}</Text>;
}

export function TabsDemo() {
  const [value, setValue] = useState("invoices");
  return (
    <>
      <Section title="Tabs · line (scrolls when it does not fit)">
        <Tabs value={value} onValueChange={setValue}>
          <TabList>
            <Tab value="overview">Overview</Tab>
            <Tab value="invoices" badge={12}>
              Invoices
            </Tab>
            <Tab value="payments">Payments</Tab>
            <Tab value="reports">Reports</Tab>
            <Tab value="settings">Settings</Tab>
            <Tab value="archived" disabled>
              Archived
            </Tab>
          </TabList>
          <TabPanel value="overview">
            <Body>Overview: revenue and outstanding at a glance.</Body>
          </TabPanel>
          <TabPanel value="invoices">
            <Body>12 invoices waiting for approval.</Body>
          </TabPanel>
          <TabPanel value="payments">
            <Body>Payments received this month.</Body>
          </TabPanel>
          <TabPanel value="reports">
            <Body>Reports: GST, TDS and ledgers.</Body>
          </TabPanel>
          <TabPanel value="settings">
            <Body>Settings for this workspace.</Body>
          </TabPanel>
        </Tabs>
      </Section>

      <Section title="Tabs · pills, small">
        <Tabs variant="pills" size="sm" defaultValue="week">
          <TabList>
            <Tab value="day">Day</Tab>
            <Tab value="week">Week</Tab>
            <Tab value="month">Month</Tab>
            <Tab value="year">Year</Tab>
          </TabList>
          <TabPanel value="day">
            <Body>Today's numbers.</Body>
          </TabPanel>
          <TabPanel value="week">
            <Body>This week's numbers.</Body>
          </TabPanel>
          <TabPanel value="month">
            <Body>This month's numbers.</Body>
          </TabPanel>
          <TabPanel value="year">
            <Body>This year's numbers.</Body>
          </TabPanel>
        </Tabs>
      </Section>

      <Section title="Tabs · enclosed (segmented), keepMounted">
        <Tabs variant="enclosed" keepMounted>
          <TabList>
            <Tab value="list">List</Tab>
            <Tab value="board">Board</Tab>
            <Tab value="calendar">Calendar</Tab>
          </TabList>
          <TabPanel value="list">
            <Body>No value given: the first tab is selected.</Body>
          </TabPanel>
          <TabPanel value="board">
            <Body>Board view; the list keeps its state while hidden.</Body>
          </TabPanel>
          <TabPanel value="calendar">
            <Body>Calendar view.</Body>
          </TabPanel>
        </Tabs>
      </Section>

      <Section title="Tabs · vertical">
        <Tabs orientation="vertical" defaultValue="profile">
          <TabList>
            <Tab value="profile">Profile</Tab>
            <Tab value="security">Security</Tab>
            <Tab value="billing">Billing</Tab>
          </TabList>
          <TabPanel value="profile">
            <Body>Name, photo and contact details.</Body>
          </TabPanel>
          <TabPanel value="security">
            <Body>Password and two-factor sign-in.</Body>
          </TabPanel>
          <TabPanel value="billing">
            <Body>Plan and payment method.</Body>
          </TabPanel>
        </Tabs>
      </Section>
    </>
  );
}
```

## Install

```bash
npx @grampro/kit@native add Tabs
```

## Usage

```tsx
import { Tabs, TabList, Tab, TabPanel } from "@/component-lib/tabs";

<Tabs defaultValue="open">
  <TabList>
    <Tab value="open">Open</Tab>
    <Tab value="paid">Paid</Tab>
  </TabList>
  <TabPanel value="open">…</TabPanel>
  <TabPanel value="paid">…</TabPanel>
</Tabs>
```

## Props

### TabsProps

| Prop | Type | Description |
|---|---|---|
| `value` | `string` | Selected tab (controlled). |
| `defaultValue` | `string` | Selected tab at first. Without either, the first enabled tab is selected. |
| `onValueChange` | `(value: string) => void` | The newly selected tab. Not fired when the same tab is pressed again. |
| `orientation` | `TabsOrientation` | Default `horizontal`. |
| `activation` | `TabsActivation` | Kept for API parity with the web. Touch has no arrow-key focus to follow, so a press always selects. |
| `variant` | `TabsVariant` | Default `line`. |
| `size` | `TabsSize` | Default `md`. |
| `keepMounted` | `boolean` | Keep hidden panels mounted, preserving their state (form input, scroll) through React's `<Activity>`. Default false. |
| `children` | `ReactNode` |   |

Also accepts the props of `Omit<ViewProps, "children">`.

### TabProps

| Prop | Type | Description |
|---|---|---|
| `value` (required) | `string` | Identifies the tab and its panel. |
| `disabled` | `boolean` |   |
| `icon` | `ReactNode` | An icon before the tab's text. |
| `badge` | `ReactNode` | A small count or label after the text, e.g. unread items. |
| `children` | `ReactNode` |   |
| `style` | `StyleProp<ViewStyle> \| ((state: TabStyleState) => StyleProp<ViewStyle>)` |   |
| `styles` | `Partial<{ label: StyleProp<TextStyle>; badge: StyleProp<ViewStyle>; icon: StyleProp<Vie…` |   |

Also accepts the props of `Omit<PressableProps, "children" | "style" | "disabled">`.

### TabPanelProps

| Prop | Type | Description |
|---|---|---|
| `value` (required) | `string` |   |
| `keepMounted` | `boolean` | Overrides `keepMounted` on `Tabs` for this panel. |
| `children` | `ReactNode` |   |

Also accepts the props of `Omit<ViewProps, "children">`.

## Native and web

- `activation` is accepted for parity but a tap always selects.
- Web version: [Tabs on the web](https://kit.gramproindia.com/tabs).
