# Tabs

## Introduction

The Tabs component provides a way to organize content into separate views where only one view is visible at a time. Built on Joy UI's Tabs, TabList, Tab, and TabPanel components, it enables users to switch between different sections of related content without leaving the current page. Tabs are ideal for organizing related information that doesn't need to be viewed simultaneously.

```
<Canvas of={Tabs.Playground} />
```

| Field   | Description | Default   |
| ------- | ----------- | --------- |
| color   | —           | "primary" |
| size    | —           | "md"      |
| variant | —           | "plain"   |

## Usage

```tsx
import { Tabs, TabList, Tab, TabPanel } from '@ceed/cds';

function MyComponent() {
  return (
    <Tabs defaultValue={0}>
      <TabList>
        <Tab>First Tab</Tab>
        <Tab>Second Tab</Tab>
        <Tab>Third Tab</Tab>
      </TabList>
      <TabPanel value={0}>Content for the first tab</TabPanel>
      <TabPanel value={1}>Content for the second tab</TabPanel>
      <TabPanel value={2}>Content for the third tab</TabPanel>
    </Tabs>
  );
}
```

## Examples

### Basic Tabs

Default tab navigation with horizontal layout.

```tsx
<Tabs {...args}>
  <TabList>
    <Tab color={color} variant={variant}>
      Tab1
    </Tab>
    <Tab color={color} variant={variant}>
      Tab2
    </Tab>
    <Tab color={color} variant={variant}>
      Tab3
    </Tab>
  </TabList>
  <TabPanel value={0}>Tab list1</TabPanel>
  <TabPanel value={1}>Tab list2</TabPanel>
  <TabPanel value={2}>Tab list3</TabPanel>
</Tabs>
```

### Variants

Tabs support different visual styles through variants.

```
<Canvas of={Tabs.Variants} />
```

### Sizes

Tabs come in different sizes to fit various use cases.

```
<Canvas of={Tabs.Sizes} />
```

### Colors

Apply semantic colors to tabs.

```
<Canvas of={Tabs.Colors} />
```

### With Decorators

Add icons or other elements to tab labels.

```tsx
<Tabs {...args}>
  <TabList>
    <Tab startDecorator={<Call />} color={color} variant={variant}>
      Tab1
    </Tab>
    <Tab endDecorator={<Sms />} color={color} variant={variant}>
      Tab2
    </Tab>
    <Tab startDecorator={<Email />} endDecorator={<MoreVert />} color={color} variant={variant}>
      Tab3
    </Tab>
  </TabList>
  <TabPanel value={0}>Tab list1</TabPanel>
  <TabPanel value={1}>Tab list2</TabPanel>
  <TabPanel value={2}>Tab list3</TabPanel>
</Tabs>
```

### Vertical Orientation

Tabs can be arranged vertically for sidebar-style navigation.

```
<Canvas of={Tabs.Vertical} />
```

### Disabled Tabs

Individual tabs can be disabled while keeping others active.

```
<Canvas of={Tabs.Disabled} />
```

### Controlled Tabs

Programmatically control the active tab.

```
<Canvas of={Tabs.Controlled} />
```

## When to Use

### ✅ Good Use Cases

- **Related content sections**: When content can be logically grouped and users don't need to see all sections at once
- **Settings pages**: Organizing different categories of settings (Profile, Security, Notifications)
- **Dashboard views**: Switching between different data views or time periods
- **Product details**: Showing Description, Specifications, Reviews as separate tabs
- **Form sections**: Breaking long forms into logical steps (not for strict wizard flows)
- **Code examples**: Showing code in different languages or frameworks

### ❌ When Not to Use

- **Primary navigation**: Use a navigation menu or sidebar for main app navigation
- **Sequential workflows**: Use Stepper for multi-step processes that must be completed in order
- **Comparing content**: If users need to see multiple sections simultaneously, use accordions or show all content
- **Very few items**: If there are only 2 options, consider using a toggle or radio buttons
- **Many items**: More than 5-6 tabs become hard to navigate; consider a dropdown or nested navigation
- **Mobile layouts**: Consider alternative patterns like accordions or stacked sections on small screens

## Common Use Cases

### Settings Page

```tsx
function SettingsPage() {
  return (
    <Tabs defaultValue={0}>
      <TabList>
        <Tab startDecorator={<PersonIcon />}>Profile</Tab>
        <Tab startDecorator={<SecurityIcon />}>Security</Tab>
        <Tab startDecorator={<NotificationsIcon />}>Notifications</Tab>
        <Tab startDecorator={<PaletteIcon />}>Appearance</Tab>
      </TabList>
      <TabPanel value={0}>
        <ProfileSettings />
      </TabPanel>
      <TabPanel value={1}>
        <SecuritySettings />
      </TabPanel>
      <TabPanel value={2}>
        <NotificationSettings />
      </TabPanel>
      <TabPanel value={3}>
        <AppearanceSettings />
      </TabPanel>
    </Tabs>
  );
}
```

### Product Detail Page

```tsx
function ProductDetails({ product }) {
  return (
    <Tabs defaultValue={0}>
      <TabList>
        <Tab>Description</Tab>
        <Tab>Specifications</Tab>
        <Tab>Reviews ({product.reviewCount})</Tab>
        <Tab>Q&A</Tab>
      </TabList>
      <TabPanel value={0}>
        <Typography>{product.description}</Typography>
      </TabPanel>
      <TabPanel value={1}>
        <SpecificationTable specs={product.specifications} />
      </TabPanel>
      <TabPanel value={2}>
        <ReviewList reviews={product.reviews} />
      </TabPanel>
      <TabPanel value={3}>
        <QASection productId={product.id} />
      </TabPanel>
    </Tabs>
  );
}
```

### Dashboard with Time Filters

```tsx
function DashboardTabs() {
  const [timeRange, setTimeRange] = useState('week');

  return (
    <Tabs value={timeRange} onChange={(e, val) => setTimeRange(val as string)}>
      <TabList>
        <Tab value="day">Today</Tab>
        <Tab value="week">This Week</Tab>
        <Tab value="month">This Month</Tab>
        <Tab value="year">This Year</Tab>
      </TabList>
      <TabPanel value="day">
        <DailyStats />
      </TabPanel>
      <TabPanel value="week">
        <WeeklyStats />
      </TabPanel>
      <TabPanel value="month">
        <MonthlyStats />
      </TabPanel>
      <TabPanel value="year">
        <YearlyStats />
      </TabPanel>
    </Tabs>
  );
}
```

### Code Examples

```tsx
function CodeExamples() {
  return (
    <Tabs defaultValue="react">
      <TabList>
        <Tab value="react">React</Tab>
        <Tab value="vue">Vue</Tab>
        <Tab value="angular">Angular</Tab>
      </TabList>
      <TabPanel value="react">
        <CodeBlock language="jsx">{reactCode}</CodeBlock>
      </TabPanel>
      <TabPanel value="vue">
        <CodeBlock language="vue">{vueCode}</CodeBlock>
      </TabPanel>
      <TabPanel value="angular">
        <CodeBlock language="typescript">{angularCode}</CodeBlock>
      </TabPanel>
    </Tabs>
  );
}
```

### Vertical Sidebar Navigation

```tsx
function SidebarTabs() {
  return (
    <Box sx={{ display: 'flex' }}>
      <Tabs orientation="vertical" defaultValue={0} sx={{ minWidth: 200 }}>
        <TabList>
          <Tab startDecorator={<DashboardIcon />}>Dashboard</Tab>
          <Tab startDecorator={<AnalyticsIcon />}>Analytics</Tab>
          <Tab startDecorator={<ReportsIcon />}>Reports</Tab>
          <Tab startDecorator={<SettingsIcon />}>Settings</Tab>
        </TabList>
      </Tabs>
      <Box sx={{ flex: 1, p: 2 }}>
        <TabPanel value={0}>Dashboard content</TabPanel>
        <TabPanel value={1}>Analytics content</TabPanel>
        <TabPanel value={2}>Reports content</TabPanel>
        <TabPanel value={3}>Settings content</TabPanel>
      </Box>
    </Box>
  );
}
```

## Component Structure

Tabs uses a composition pattern with multiple sub-components:

```tsx
<Tabs>                    {/* Container - manages state */}
  <TabList>               {/* Tab button container */}
    <Tab>Tab 1</Tab>      {/* Individual tab buttons */}
    <Tab>Tab 2</Tab>
  </TabList>
  <TabPanel value={0}>    {/* Content panels */}
    Content 1
  </TabPanel>
  <TabPanel value={1}>
    Content 2
  </TabPanel>
</Tabs>
```

## Props and Customization

### Tabs Props

| Prop           | Type                         | Default        | Description                         |
| -------------- | ---------------------------- | -------------- | ----------------------------------- |
| `defaultValue` | `string \| number`           | -              | Default selected tab (uncontrolled) |
| `value`        | `string \| number`           | -              | Selected tab (controlled)           |
| `onChange`     | `function`                   | -              | Callback when tab changes           |
| `orientation`  | `'horizontal' \| 'vertical'` | `'horizontal'` | Tab layout direction                |
| `size`         | `'sm' \| 'md' \| 'lg'`       | `'md'`         | Size of all child components        |

### Tab Props

| Prop             | Type                                                           | Default   | Description                        |
| ---------------- | -------------------------------------------------------------- | --------- | ---------------------------------- |
| `value`          | `string \| number`                                             | -         | Tab identifier (defaults to index) |
| `variant`        | `'plain' \| 'outlined' \| 'soft' \| 'solid'`                   | `'plain'` | Visual style                       |
| `color`          | `'primary' \| 'neutral' \| 'danger' \| 'success' \| 'warning'` | -         | Color scheme                       |
| `disabled`       | `boolean`                                                      | `false`   | Disable the tab                    |
| `startDecorator` | `ReactNode`                                                    | -         | Element before tab label           |
| `endDecorator`   | `ReactNode`                                                    | -         | Element after tab label            |

### TabPanel Props

| Prop          | Type               | Default | Description                   |
| ------------- | ------------------ | ------- | ----------------------------- |
| `value`       | `string \| number` | -       | Matching tab value            |
| `keepMounted` | `boolean`          | `false` | Keep panel in DOM when hidden |

### Custom Styling

```tsx
<Tabs
  sx={{
    '--Tabs-gap': '8px',
  }}
>
  <TabList
    sx={{
      borderBottom: '1px solid',
      borderColor: 'divider',
    }}
  >
    <Tab
      sx={{
        '&.Mui-selected': {
          borderBottom: '2px solid',
          borderColor: 'primary.500',
        },
      }}
    >
      Custom Tab
    </Tab>
  </TabList>
</Tabs>
```

## Accessibility

Tabs components follow WAI-ARIA Tabs pattern for comprehensive accessibility:

### ARIA Attributes

- `role="tablist"` on TabList
- `role="tab"` on each Tab
- `role="tabpanel"` on each TabPanel
- `aria-selected` indicates the active tab
- `aria-controls` links tabs to their panels
- `aria-labelledby` links panels to their tabs

### Keyboard Navigation

- **Tab**: Move focus to the tab list, then to the active panel
- **Arrow Left/Right**: Move between tabs (horizontal orientation)
- **Arrow Up/Down**: Move between tabs (vertical orientation)
- **Home**: Move to first tab
- **End**: Move to last tab
- **Enter/Space**: Activate the focused tab

### Screen Reader Support

```tsx
<Tabs aria-label="Account settings tabs">
  <TabList>
    <Tab>Profile</Tab>
    <Tab>Security</Tab>
  </TabList>
  <TabPanel value={0}>
    <h2 id="profile-heading">Profile Settings</h2>
    {/* Content */}
  </TabPanel>
</Tabs>
```

## Best Practices

### ✅ Do

1. **Use clear, concise labels**: Tab labels should clearly describe the content

```tsx
// ✅ Good: Clear labels
<Tab>Account Settings</Tab>
<Tab>Notifications</Tab>

// ❌ Bad: Vague labels
<Tab>Tab 1</Tab>
<Tab>Other</Tab>
```

2. **Keep tab count manageable**: Limit to 5-6 tabs maximum

3. **Order tabs logically**: Place most important or frequently used tabs first

4. **Use consistent styling**: All tabs should have the same visual weight

5. **Show active state clearly**: Users should always know which tab is selected

### ❌ Don't

1. **Don't hide critical information**: Important content shouldn't be buried in secondary tabs

2. **Don't use for sequential processes**: Use Stepper for ordered workflows

```tsx
// ❌ Bad: Sequential steps as tabs
<Tab>Step 1: Personal Info</Tab>
<Tab>Step 2: Payment</Tab>
<Tab>Step 3: Confirm</Tab>

// ✅ Good: Use Stepper instead
<Stepper activeStep={activeStep}>
  <Step>Personal Info</Step>
  <Step>Payment</Step>
  <Step>Confirm</Step>
</Stepper>
```

3. **Don't nest tabs within tabs**: Creates confusing navigation

4. **Don't use inconsistent tab counts**: If tabs are dynamic, consider alternative UI patterns

## Performance Considerations

### Lazy Loading Tab Content

By default, inactive tab panels are not rendered. For complex content, this provides automatic lazy loading:

```tsx
<TabPanel value={0}>
  {/* Only rendered when this tab is active */}
  <HeavyComponent />
</TabPanel>
```

### Keep Mounted

Use `keepMounted` when tab content needs to maintain state:

```tsx
<TabPanel value={0} keepMounted>
  {/* Stays in DOM, maintains form state */}
  <FormWithState />
</TabPanel>
```

### Avoid Heavy Re-renders

Memoize tab content when it depends on complex calculations:

```tsx
const tabContent = useMemo(() => (
  <ExpensiveComponent data={data} />
), [data]);

<TabPanel value={0}>{tabContent}</TabPanel>
```

Tabs provide an intuitive way to organize related content while keeping the interface clean and navigable. Use them thoughtfully to enhance content discoverability without overwhelming users.
