import { ArgTypes, Canvas, Story, Meta } from '@storybook/addon-docs/blocks';
import { Tabs, TabList, Tab, TabPanels, TabPanel } from './Tabs';
import * as TabsStories from './Tabs.stories';
import { Grid, Column } from '../Grid';
import { stackblitzPrefillConfig } from '../../../previewer/codePreviewer';

<Meta isTemplate />

# Tabs

[Source code](https://github.com/carbon-design-system/carbon/tree/main/packages/react/src/components/Tabs)
&nbsp;|&nbsp;
[Usage guidelines](https://www.carbondesignsystem.com/components/tabs/usage)
&nbsp;|&nbsp;
[Accessibility](https://www.carbondesignsystem.com/components/tabs/accessibility)

{/* <!-- START doctoc generated TOC please keep comment here to allow auto update --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> */}

## Table of Contents

- [Overview](#overview)
  - [Line Tabs](#line-tabs)
  - [Contained Tabs](#contained-tabs)
  - [Contained Full Width](#contained-full-width)
  - [Contained With Icons](#contained-with-icons)
  - [Contained With Second Labels](#contained-with-second-labels)
  - [Contained With Second Labels and Icons](#contained-with-second-labels-and-icons)
  - [Icon Tabs Only](#icon-tabs-only)
  - [Dismissable Tabs](#dismissable-tabs)
  - [Manual](#manual)
  - [Skeleton](#skeleton)
  - [With Icons](#with-icons)
  - [Vertical tabs](#vertical-tabs)
  - [Tab - tab activation modes](#tab---tab-activation-modes)
  - [Tabs and the Grid - fullWidth prop](#tabs-and-the-grid---fullwidth-prop)
- [V11](#v11)
  - [Tabs composition](#tabs-composition)
  - [Various updates](#various-updates)
  - [Max width](#max-width)
- [Component API](#component-api)
- [Feedback](#feedback)

{/* <!-- END doctoc generated TOC please keep comment here to allow auto update --> */}

## Overview

Use tabs to allow users to navigate easily between views within the same
context. Tabs are now more composable, meaning that you have more flexibility in
what is in rendered inside of `Tab` and `TabPanel`.

### Line Tabs

<Canvas
  of={TabsStories.Default}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(TabsStories.Default),
    },
  ]}
/>

### Contained Tabs

<Canvas
  of={TabsStories.Contained}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(TabsStories.Contained),
    },
  ]}
/>

### Contained Full Width

<Canvas
  of={TabsStories.ContainedFullWidth}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(TabsStories.ContainedFullWidth),
    },
  ]}
/>

### Contained With Icons

<Canvas
  of={TabsStories.ContainedWithIcons}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(TabsStories.ContainedWithIcons),
    },
  ]}
/>

### Contained With Second Labels

<Canvas
  of={TabsStories.ContainedWithSecondaryLabels}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(TabsStories.ContainedWithSecondaryLabels),
    },
  ]}
/>

### Contained With Second Labels and Icons

<Canvas
  of={TabsStories.ContainedWithSecondaryLabelsAndIcons}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(TabsStories.ContainedWithSecondaryLabelsAndIcons),
    },
  ]}
/>

### Icon Tabs Only

<Canvas
  of={TabsStories.IconOnly}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(TabsStories.IconOnly),
    },
  ]}
/>

<Canvas
  of={TabsStories.Icon20Only}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(TabsStories.Icon20Only),
    },
  ]}
/>

### Dismissable Tabs

You can implement dismissable tabs in your project using Carbon's `Tabs`
components. In order to put this in place, there are some events and props we'll
need to forward through the component's API that have been outlined here.

First, we'll want to import the components from the react package.

```js
import { Tabs, TabList, Tab, TabPanels, TabPanel } from '@carbon/react';
```

In order to be able to "close" or "remove" tabs, we'll need to access and render
your tabs programmatically. For such purposes we'll need to store your tabs in
an array variable and put them in the state

```js
const tabs = [
  {
    label: 'Tab label 1',
    panel: <TabPanel>Tab Panel 1</TabPanel>,
  },
  {
    label: 'Tab label 2',
    panel: <TabPanel>Tab Panel 2</TabPanel>,
  },
  {
    label: 'Tab label 3',
    panel: <TabPanel>Tab Panel 3</TabPanel>,
    disabled: true,
  },
  {
    label: 'Tab label 4',
    panel: <TabPanel>Tab Panel 4</TabPanel>,
  },
];
const [renderedTabs, setRenderedTabs] = useState(tabs);
```

The `Tabs` component accepts an `onTabCloseRequest` prop function that will
forward us the index of the requested tab to be closed. You may use this
function to open up a confirmation modal previous to deleting the tab; in our
case, we'll just go ahead and remove that tab directly from the `renderedTab`s
array and cover for some `selectedIndex` edge cases (i.e., when a tab is removed
from the array, the selectedIndex might need to be updated to point to a new tab
or index).

In order to be able to modify the `selectedIndex` on our end we'll need to use
the `Tabs` component in a controlled state, which means we'll also have to
implement the `Tabs`' `onChange` function, which we are calling
`handleTabChange`.

```js
const [selectedIndex, setSelectedIndex] = useState(0);

const handleTabChange = (evt) => {
  setSelectedIndex(evt.selectedIndex);
};

const handleCloseTabRequest = (tabIndex) => {
  // ignore close requests on disabled tabs
  if (renderedTabs[tabIndex].disabled) {
    return;
  }

  const selectedTab = renderedTabs[selectedIndex];

  const filteredTabs = renderedTabs.filter((_, index) => index !== tabIndex);
  // if the tab being deleted is the currently selected tab, we're re-setting the selectedIndex
  // to the first tab available that isn't disabled
  if (tabIndex === selectedIndex) {
    const defaultTabIndex = filteredTabs.findIndex((tab) => !tab.disabled);
    setSelectedIndex(defaultTabIndex);
  } else {
    // we're re-calculating the selectedIndex since the selected tab's index might have shifted
    // due to a tab element being removed from the array
    setSelectedIndex(filteredTabs.indexOf(selectedTab));
  }
  setRenderedTabs(filteredTabs);
};
```

Finally, we'll use a `resetTabs` function to demonstrate how you can re-render
tabs after they've been removed

```js
const resetTabs = () => {
  setRenderedTabs(tabs);
};
```

Now we're ready to render our `Tabs`, remember to pass the `dismissable` prop in
as well as your `handleCloseTabRequest` function

```jsx
return (
  <>
    <Button style={{ marginBottom: '3rem' }} onClick={resetTabs}>
      Reset
    </Button>
    <Tabs
      selectedIndex={selectedIndex}
      onChange={handleTabChange}
      dismissable
      onTabCloseRequest={handleCloseTabRequest}>
      <TabList aria-label="List of tabs">
        {renderedTabs.map((tab, index) => (
          <Tab key={index} disabled={tab.disabled}>
            {tab.label}
          </Tab>
        ))}
      </TabList>
      <TabPanels>{renderedTabs.map((tab) => tab.panel)}</TabPanels>
    </Tabs>
  </>
);
```

And there you have it! Working dismissable tabs.

<Canvas
  of={TabsStories.Dismissable}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(TabsStories.Dismissable),
    },
  ]}
/>

Dismissable With Icons: 

<Canvas
  of={TabsStories.DismissableWithIcons}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(TabsStories.DismissableWithIcons),
    },
  ]}
/>
### Manual

<Canvas
  of={TabsStories.Manual}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(TabsStories.Manual),
    },
  ]}
/>

### Skeleton

<Canvas
  of={TabsStories.Skeleton}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(TabsStories.Skeleton),
    },
  ]}
/>

### With Icons

<Canvas
  of={TabsStories.WithIcons}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(TabsStories.WithIcons),
    },
  ]}
/>

### Vertical tabs

<Canvas
  of={TabsStories.Vertical}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(TabsStories.Vertical),
    },
  ]}
/>
### Tab - tab activation modes

**Tabs With Automatic Activation**: A tabs widget where tabs are automatically
activated and their panel is displayed when they receive focus.

**Tabs With Manual Activation**: A tabs widget where users activate a tab and
display its panel by pressing Space or Enter.

In v11, to do this, you can this by setting `activation` to `manual`:

```jsx
<Tabs>
  <TabList aria-label="List of tabs" activation="manual">
    <Tab>Tab Label 1</Tab>
    <Tab>Tab Label 2</Tab>
    <Tab>Tab Label 3</Tab>
  </TabList>
  <TabPanels>
    <TabPanel>Tab Panel 1</TabPanel>
    <TabPanel>Tab Panel 2</TabPanel>
    <TabPanel>Tab Panel 3</TabPanel>
  </TabPanels>
</Tabs>
```

### Tabs and the Grid - fullWidth prop

By default, a `Tab` component is only as wide as it's content. This posses
difficulties when trying to align tabs to the grid. Alternatively, you may
choose to use the `fullWidth` prop to allow `Tab` elements to grow as wide as
their container allows.

Note that this feature is _only available_ for `contained` tabs in large and
extra large screen sizes. The prop is a no-op for smaller screens and will also
be ignored for `TabList`s with more than 8 tabs. `fullWidth` paired up with a
wrapping `Grid` component will allow for "grid-aware" tabs:

<Canvas>
  <Grid condensed>
    <Column lg={16} md={8} sm={4}>
      <Tabs>
        <TabList aria-label="List of tabs" contained fullWidth>
          <Tab>Tab Label 1</Tab>
          <Tab>Tab Label 2</Tab>
          <Tab disabled>Tab Label 3</Tab>
        </TabList>
        <TabPanels>
          <TabPanel>Tab Panel 1</TabPanel>
          <TabPanel>Tab Panel 2</TabPanel>
          <TabPanel>Tab Panel 3</TabPanel>
        </TabPanels>
      </Tabs>
    </Column>
  </Grid>
</Canvas>

```jsx
<Grid condensed>
  <Column lg={16} md={8} sm={4}>
    <Tabs>
      <TabList aria-label="List of tabs" contained fullWidth>
        <Tab>Tab Label 1</Tab>
        <Tab>Tab Label 2</Tab>
        <Tab disabled>Tab Label 3</Tab>
      </TabList>
      <TabPanels>
        <TabPanel>Tab Panel 1</TabPanel>
        <TabPanel>Tab Panel 2</TabPanel>
        <TabPanel>Tab Panel 3</TabPanel>
      </TabPanels>
    </Tabs>
  </Column>
</Grid>
```

Using the `fullWidth` prop alone within a `Grid` makes it so that the `Tabs`
container aligns to the `Grid`, but not the individual `Tab` items; to have each
individual `Tab` take up exactly one or many columns within the `Grid`, you must
specify the number of columns as a multiple of the number of `Tab` items within
the `TabList`.

For example, to have 5 tabs and each tab span exactly two columns:

<Canvas>
  <Grid condensed>
    <Column lg={10}>
      <Tabs>
        <TabList aria-label="List of tabs" contained fullWidth>
          <Tab>Tab Label 1</Tab>
          <Tab>Tab Label 2</Tab>
          <Tab disabled>Tab Label 3</Tab>
          <Tab>Tab Label 4</Tab>
          <Tab>Tab Label 5</Tab>
        </TabList>
        <TabPanels>
          <TabPanel>Tab Panel 1</TabPanel>
          <TabPanel>Tab Panel 2</TabPanel>
          <TabPanel>Tab Panel 3</TabPanel>
          <TabPanel>Tab Panel 4</TabPanel>
          <TabPanel>Tab Panel 5</TabPanel>
        </TabPanels>
      </Tabs>
    </Column>
  </Grid>
</Canvas>

```jsx
<Grid condensed>
  <Column lg={10}>
    <Tabs>
      <TabList aria-label="List of tabs" contained fullWidth>
        <Tab>Tab Label 1</Tab>
        <Tab>Tab Label 2</Tab>
        <Tab disabled>Tab Label 3</Tab>
        <Tab>Tab Label 4</Tab>
        <Tab>Tab Label 5</Tab>
      </TabList>
      <TabPanels>
        <TabPanel>Tab Panel 1</TabPanel>
        <TabPanel>Tab Panel 2</TabPanel>
        <TabPanel>Tab Panel 3</TabPanel>
        <TabPanel>Tab Panel 4</TabPanel>
        <TabPanel>Tab Panel 5</TabPanel>
      </TabPanels>
    </Tabs>
  </Column>
</Grid>
```

Or, to have 5 tabs and each tab span exactly three columns:

<Canvas>
  <Grid condensed>
    <Column lg={15}>
      <Tabs>
        <TabList aria-label="List of tabs" contained fullWidth>
          <Tab>Tab Label 1</Tab>
          <Tab>Tab Label 2</Tab>
          <Tab disabled>Tab Label 3</Tab>
          <Tab>Tab Label 4</Tab>
          <Tab>Tab Label 5</Tab>
        </TabList>
        <TabPanels>
          <TabPanel>Tab Panel 1</TabPanel>
          <TabPanel>Tab Panel 2</TabPanel>
          <TabPanel>Tab Panel 3</TabPanel>
          <TabPanel>Tab Panel 4</TabPanel>
          <TabPanel>Tab Panel 5</TabPanel>
        </TabPanels>
      </Tabs>
    </Column>
  </Grid>
</Canvas>

```jsx
<Grid condensed>
  <Column lg={15}>
    <Tabs>
      <TabList aria-label="List of tabs" contained fullWidth>
        <Tab>Tab Label 1</Tab>
        <Tab>Tab Label 2</Tab>
        <Tab disabled>Tab Label 3</Tab>
        <Tab>Tab Label 4</Tab>
        <Tab>Tab Label 5</Tab>
      </TabList>
      <TabPanels>
        <TabPanel>Tab Panel 1</TabPanel>
        <TabPanel>Tab Panel 2</TabPanel>
        <TabPanel>Tab Panel 3</TabPanel>
        <TabPanel>Tab Panel 4</TabPanel>
        <TabPanel>Tab Panel 5</TabPanel>
      </TabPanels>
    </Tabs>
  </Column>
</Grid>
```

## V11

### Tabs composition

Tabs got a big revamp in v11! Tabs are now more composable than ever before,
meaning that you have the flexibility and control on your end to make them look
and act how you want. The biggest difference is that the Tab label and the Tab
content are now separate components.

Example of Tabs in v10:

```js
<Tabs>
  <Tab label="Tab label 1">
    <p>Content for first tab goes here.</p>
  </Tab>
  <Tab label="Tab label 2">
    <p>Content for second tab goes here.</p>
  </Tab>
  <Tab label="Tab label 3" disabled>
    <p>Content for third tab goes here.</p>
  </Tab>
  <Tab
    label="Tab label 4 shows truncation"
    title="Tab label 4 shows truncation">
    <p>Content for fourth tab goes here.</p>
  </Tab>
</Tabs>
```

Those same Tabs, now in v11:

```js
<Tabs>
  <TabList>
    <Tab>Tab Label 1</Tab>
    <Tab>Tab Label 2</Tab>
    <Tab disabled>Tab Label 3</Tab>
    <Tab title="Tab Label 4 shows truncation">Tab Label 4 shows truncation</Tab>
  </TabList>
  <TabPanels>
    <TabPanel>Content for first tab goes here.</TabPanel>
    <TabPanel>Content for second tab goes here.</TabPanel>
    <TabPanel>Content for third tab goes here.</TabPanel>
    <TabPanel>Content for fourth tab goes here.</TabPanel>
  </TabPanels>
</Tabs>
```

### Various updates

All the same functionality for Tabs is available in v11 and more! Below are the
minor tweaks in naming or implementation.

- the `type` prop is deprecated. Both "container" and "default" tabs still exist
  but now can be called by adding the prop `contained` to the `TabList`. See the
  above "Contained Tabs" for an example.
- Default tabs are now referred to as line tabs in our documentation here and on
  our website.
- `hidden` prop is no longer needed with the new composable Tabs. You have full
  control over tab content and when it's hidden through the `TabPanel` and
  `TabPanels` components.
- `selected` prop is now named `selectedIndex`.
- `tabContentClassName` is no longer needed. `TabPanel` (equivalent to tab
  content) takes in a className prop on its outermost node.
- For `Tab`, `label` is no longer needed. `children` of `Tab` are now the label.
- Due to its composability, `renderAnchor`, `renderButton`, `renderContent` are
  no longer needed on `Tab`.
- `selected` on `Tab` is deprecated in favor or `selectedIndex`, now placed on
  `Tabs` instead.
- Because `renderButton` is no longer needed, the associated `tabIndex` prop has
  also been deprecated.

### Max width

In V11, tabs no longer have a max-width property set. Which means a tab title
can span as wide as its title is long. To override this behavior, you may use
some style rules:

```css
.cds--tabs__nav-link {
  max-width: 10rem;
}
```

## Component API

<ArgTypes />

## Feedback

Help us improve this component by providing feedback, asking questions on Slack,
or updating this file on
[GitHub](https://github.com/carbon-design-system/carbon/edit/main/packages/react/src/components/Tabs/Tabs.mdx).
