Default

Loading interactive example. Full source is available below.

View example source
Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import { TabList } from "@coreai-ds/react-components";
import { Tab } from "@coreai-ds/react-components";
import * as React from 'react';

export const Default = () => {
    return (<TabList>
        <Tab value="tab1">First Tab</Tab>
        <Tab value="tab2">Second Tab</Tab>
        <Tab value="tab3">Third Tab</Tab>
        <Tab value="tab4">Fourth Tab</Tab>
      </TabList>);
};

export default Default;

Resources

Best practices

Do

  • Use tabs for distinct but related content categories or a small set of closely related pages.
  • Ensure one tab is active on initial render.
  • Keep labels brief and grammatically and conceptually parallel.

Don't

  • Use tabs for navigation beyond closely related categories; use links.
  • Use tabs to initiate actions; use buttons.
  • Expect horizontal tabs to scroll or wrap.

Behavior and states

  • One tab, usually the first, should always be active on first render.
  • Horizontal tabs don’t scroll or wrap to the next line.
  • Use an overflow menu button when the container can’t show every tab.
  • Icon-only tabs require an aria-label and a tooltip.
  • Identify the current selection to screen readers using aria-current.
  • Vertical tablists place tabs in a column.
  • When space is limited, consider an accordion or dropdown instead.
  • Use one consistent label format for every tab in the tablist.
  • They’re are ideal for dividing content-heavy pages into distinct but related categories that are easier to process and require less scrolling.
  • Tabs can also be used for navigation between a small set of closely related, frequently accessed pages.
  • For navigation beyond closely related categories, use a link instead.
  • To initiate an action, use a button instead.
API referenceGenerated CoreAI prop and type summaries

API

Generated CoreAI prop summaries, not replacement type declarations. Most native DOM/event and ARIA props are omitted. ? means optional; JSDoc shows defaults, deprecations, and conditional requirements. Defaults assume the standard CoreAI provider.

TabList API

interface TabListProps {
  /**
   * A tab list can supports 'transparent' and 'subtle' appearance.
   * - 'subtle': Minimizes emphasis to blend into the background until hovered or focused.
   * - 'transparent': No background and border styling
   * - 'subtle-circular': Adds background and border styling
   * - 'filled-circular': Adds background styling
   * - 'elevated': Adds background around all tabs for visual grouping
   *
   * The appearance affects each of the contained tabs.
   * @default 'transparent'
   */
  appearance?: "subtle" | "transparent" | "elevated" | "subtle-circular" | "filled-circular";

  as?: "div";

  children?: any;

  className?: string;

  /**
   * The value of the tab to be selected by default.
   * Typically useful when the selectedValue is uncontrolled.
   */
  defaultSelectedValue?: unknown;

  /**
   * A tab list can be set to disable interaction.
   * @default false
   */
  disabled?: boolean;

  /**
   * Raised when a tab is selected.
   */
  onTabSelect?: SelectTabEventHandler;

  ref?: Ref<HTMLDivElement>;

  /**
   * Tab size may change between unselected and selected states.
   * The default scenario is a selected tab has bold text.
   *
   * When true, this property requests tabs be the same size whether unselected or selected.
   * @default true
   */
  reserveSelectedTabSpace?: boolean;

  /**
   * The value of the currently selected tab.
   */
  selectedValue?: unknown;

  /**
   * When true, focusing a tab will select it.
   * @default false
   */
  selectTabOnFocus?: boolean;

  /**
   * A tab list can be either 'small', 'medium', or 'large' size.
   * The size affects each of the contained tabs.
   * @default 'medium'
   */
  size?: "small" | "medium" | "large";

  style?: CSSProperties;

  /**
   * A tab list can arrange its tabs vertically.
   * @default false
   */
  vertical?: boolean;
}

Tab API

A tab provides a selectable item in a tab list.

interface TabProps {
  as?: "button";

  children?: any;

  className?: string;

  /**
   * Component children are placed in this slot
   * Avoid using the `children` property in this slot in favour of Component children whenever possible.
   */
  content?: NonNullable<WithSlotShorthandValue<{ as?: "span"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & { ref?: ((instance: HTMLSpanElement | null) => void) | RefObject<HTMLSpanElement> | null; }, "children"> & { children?: any; }> | null> | undefined;

  /**
   * A tab can be set to disable interaction.
   * @default false
   */
  disabled?: boolean;

  /**
   * Icon that renders before the content.
   */
  icon?: WithSlotShorthandValue<{ as?: "span"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & { ref?: ((instance: HTMLSpanElement | null) => void) | RefObject<HTMLSpanElement> | null; }, "children"> & { children?: any; }> | null | undefined;

  ref?: Ref<HTMLButtonElement>;

  style?: CSSProperties;

  /**
   * The value that identifies this tab when selected.
   */
  value: unknown;
}

Implementation

CoreAI 0.12.0; Fluent 9.74.9.

Setup and dependencies.

Import components from @coreai-ds/react-components. CoreAI guidance above takes precedence over API demonstration examples.

Appearance

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { Tab } from "@coreai-ds/react-components";
import { TabList } from "@coreai-ds/react-components";
import * as React from 'react';

const useStyles = makeStyles({
    root: {
        alignItems: 'flex-start',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'flex-start',
        padding: '50px 20px',
        rowGap: '20px',
    },
});

export const Appearance = (): JSXElement => {
    const styles = useStyles();
    const renderTabs = () => {
        return (<>
        <Tab value="tab1">First Tab</Tab>
        <Tab disabled value="tab2">
          Second Tab
        </Tab>
        <Tab value="tab3">Third Tab</Tab>
        <Tab value="tab4">Fourth Tab</Tab>
      </>);
    };
    return (<div className={styles.root}>
      <TabList defaultSelectedValue="tab3" appearance="transparent">
        {renderTabs()}
      </TabList>
      <TabList defaultSelectedValue="tab3" appearance="subtle">
        {renderTabs()}
      </TabList>
      <TabList defaultSelectedValue="tab3" appearance="subtle-circular">
        {renderTabs()}
      </TabList>
      <TabList defaultSelectedValue="tab3" appearance="filled-circular">
        {renderTabs()}
      </TabList>
    </div>);
};

export default Appearance;

Custom Appearance Elevated

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import * as React from 'react';
import type { TabValue } from "@coreai-ds/react-components";
import type { SelectTabEvent } from "@coreai-ds/react-components";
import type { SelectTabData } from "@coreai-ds/react-components";
import { TabList } from "@coreai-ds/react-components";
import { Tab } from "@coreai-ds/react-components";
import { bundleIcon } from "@fluentui/react-icons";
import { CalendarDayFilled } from "@fluentui/react-icons";
import { CalendarDayRegular } from "@fluentui/react-icons";
import { CalendarAgendaFilled } from "@fluentui/react-icons";
import { CalendarAgendaRegular } from "@fluentui/react-icons";
import { CalendarTodayFilled } from "@fluentui/react-icons";
import { CalendarTodayRegular } from "@fluentui/react-icons";
import { CalendarMonthFilled } from "@fluentui/react-icons";
import { CalendarMonthRegular } from "@fluentui/react-icons";
import { Overflow } from "@coreai-ds/react-components";
import { Calendar3DayFilled } from "@fluentui/react-icons";
import { Calendar3DayRegular } from "@fluentui/react-icons";
import { CalendarWorkWeekFilled } from "@fluentui/react-icons";
import { CalendarWorkWeekRegular } from "@fluentui/react-icons";
import { CalendarWeekStartFilled } from "@fluentui/react-icons";
import { CalendarWeekStartRegular } from "@fluentui/react-icons";
import { CalendarSearchFilled } from "@fluentui/react-icons";
import { CalendarSearchRegular } from "@fluentui/react-icons";
import { CalendarChatFilled } from "@fluentui/react-icons";
import { CalendarChatRegular } from "@fluentui/react-icons";
import { OverflowItem } from "@coreai-ds/react-components";
import { useOverflowMenu } from "@coreai-ds/react-components";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { MoreHorizontalFilled } from "@fluentui/react-icons";
import { MoreHorizontalRegular } from "@fluentui/react-icons";
import { MenuPopover } from "@coreai-ds/react-components";
import { MenuList } from "@coreai-ds/react-components";
import type { MenuItemProps } from "@coreai-ds/react-components";
import { useIsOverflowItemVisible } from "@coreai-ds/react-components";
import { MenuItem } from "@coreai-ds/react-components";
const CalendarDay = bundleIcon(CalendarDayFilled, CalendarDayRegular);
const CalendarAgenda = bundleIcon(CalendarAgendaFilled, CalendarAgendaRegular);
const CalendarToday = bundleIcon(CalendarTodayFilled, CalendarTodayRegular);
// ---------- Default + Panels (combined) ----------
const DefaultWithPanels = () => {
    const [selectedValue, setSelectedValue] = React.useState<TabValue>('conditions');
    const onTabSelect = (_e: SelectTabEvent, data: SelectTabData) => {
        setSelectedValue(data.value);
    };
    return (<>
      <TabList appearance="elevated" selectedValue={selectedValue} onTabSelect={onTabSelect}>
        <Tab id="components-tablist--custom-appearance-elevated-Arrivals" icon={<CalendarDay />} value="arrivals">
          Arrivals
        </Tab>
        <Tab id="components-tablist--custom-appearance-elevated-Departures" icon={<CalendarAgenda />} value="departures">
          Departures
        </Tab>
        <Tab id="components-tablist--custom-appearance-elevated-Conditions" icon={<CalendarToday />} value="conditions">
          Conditions
        </Tab>
      </TabList>
      <div className="tab-list-elevated-example__panels">
        {selectedValue === 'arrivals' && (<div role="tabpanel" aria-labelledby="components-tablist--custom-appearance-elevated-Arrivals">
            <table>
              <thead>
                <th>Origin</th>
                <th>Gate</th>
                <th>ETA</th>
              </thead>
              <tbody>
                <tr>
                  <td>DEN</td>
                  <td>C3</td>
                  <td>12:40 PM</td>
                </tr>
                <tr>
                  <td>SMF</td>
                  <td>D1</td>
                  <td>1:18 PM</td>
                </tr>
                <tr>
                  <td>SFO</td>
                  <td>E18</td>
                  <td>1:42 PM</td>
                </tr>
              </tbody>
            </table>
          </div>)}
        {selectedValue === 'departures' && (<div role="tabpanel" aria-labelledby="components-tablist--custom-appearance-elevated-Departures">
            <table>
              <thead>
                <th>Destination</th>
                <th>Gate</th>
                <th>ETD</th>
              </thead>
              <tbody>
                <tr>
                  <td>MSP</td>
                  <td>A7</td>
                  <td>8:26 AM</td>
                </tr>
                <tr>
                  <td>DCA</td>
                  <td>N2</td>
                  <td>9:03 AM</td>
                </tr>
                <tr>
                  <td>LAS</td>
                  <td>E15</td>
                  <td>2:36 PM</td>
                </tr>
              </tbody>
            </table>
          </div>)}
        {selectedValue === 'conditions' && (<div role="tabpanel" aria-labelledby="components-tablist--custom-appearance-elevated-Conditions">
            <table className="tab-list-elevated-example__props-table">
              <tbody>
                <tr>
                  <td>Time</td>
                  <td>6:45 AM</td>
                </tr>
                <tr>
                  <td>Temperature</td>
                  <td>68F / 20C</td>
                </tr>
                <tr>
                  <td>Forecast</td>
                  <td>Overcast</td>
                </tr>
                <tr>
                  <td>Visibility</td>
                  <td>0.5 miles, 1800 ft runway visual range</td>
                </tr>
              </tbody>
            </table>
          </div>)}
      </div>
    </>);
};
// ---------- Simple tab set used across sections ----------
const renderSimpleTabs = (disabledValue?: string) => (<>
    <Tab value="tab1">First Tab</Tab>
    <Tab value="tab2" disabled={disabledValue === 'tab2'}>
      Second Tab
    </Tab>
    <Tab value="tab3">Third Tab</Tab>
    <Tab value="tab4">Fourth Tab</Tab>
  </>);
// ---------- Icons ----------
const CalendarMonth = bundleIcon(CalendarMonthFilled, CalendarMonthRegular);
const renderIconTabs = (iconOnly?: boolean) => (<>
    <Tab icon={<CalendarMonth />} value="tab1" {...(iconOnly ? { 'aria-label': 'First Tab' } : {})}>
      {iconOnly ? undefined : 'First Tab'}
    </Tab>
    <Tab icon={<CalendarMonth />} value="tab2" {...(iconOnly ? { 'aria-label': 'Second Tab' } : {})}>
      {iconOnly ? undefined : 'Second Tab'}
    </Tab>
    <Tab icon={<CalendarMonth />} value="tab3" {...(iconOnly ? { 'aria-label': 'Third Tab' } : {})}>
      {iconOnly ? undefined : 'Third Tab'}
    </Tab>
    <Tab icon={<CalendarMonth />} value="tab4" {...(iconOnly ? { 'aria-label': 'Fourth Tab' } : {})}>
      {iconOnly ? undefined : 'Fourth Tab'}
    </Tab>
  </>);
// ---------- Overflow plumbing (adapted from TabListWithOverflow.stories) ----------
type ExampleTab = {
    id: string;
    name: string;
    icon: React.ReactElement;
};
const Calendar3Day = bundleIcon(Calendar3DayFilled, Calendar3DayRegular);
const CalendarWorkWeek = bundleIcon(CalendarWorkWeekFilled, CalendarWorkWeekRegular);
const CalendarWeekStart = bundleIcon(CalendarWeekStartFilled, CalendarWeekStartRegular);
const CalendarSearch = bundleIcon(CalendarSearchFilled, CalendarSearchRegular);
const CalendarChat = bundleIcon(CalendarChatFilled, CalendarChatRegular);
const overflowTabs: ExampleTab[] = [
    { id: 'today', name: 'Today', icon: <CalendarToday /> },
    { id: 'agenda', name: 'Agenda', icon: <CalendarAgenda /> },
    { id: 'day', name: 'Day', icon: <CalendarDay /> },
    { id: 'threeDay', name: 'Three Day', icon: <Calendar3Day /> },
    { id: 'workWeek', name: 'Work Week', icon: <CalendarWorkWeek /> },
    { id: 'week', name: 'Week', icon: <CalendarWeekStart /> },
    { id: 'month', name: 'Month', icon: <CalendarMonth /> },
    { id: 'search', name: 'Search', icon: <CalendarSearch /> },
    { id: 'chat', name: 'Conversations', icon: <CalendarChat /> },
];
type OverflowMenuProps = {
    onTabSelect?: (tabId: string) => void;
};
const MoreHorizontal = bundleIcon(MoreHorizontalFilled, MoreHorizontalRegular);
type OverflowMenuItemProps = {
    tab: ExampleTab;
    onClick: MenuItemProps['onClick'];
};
const OverflowMenuItem = ({ tab, onClick }: OverflowMenuItemProps) => {
    const isVisible = useIsOverflowItemVisible(tab.id);
    if (isVisible) {
        return null;
    }
    return (<MenuItem key={tab.id} icon={tab.icon} onClick={onClick}>
      <div>{tab.name}</div>
    </MenuItem>);
};
const OverflowMenu = ({ onTabSelect }: OverflowMenuProps) => {
    const { ref, isOverflowing, overflowCount } = useOverflowMenu<HTMLButtonElement>();
    if (!isOverflowing) {
        return null;
    }
    return (<Menu hasIcons>
      <MenuTrigger disableButtonEnhancement>
        <Button appearance="transparent" className="tab-list-elevated-example__menu-button" ref={ref} icon={<MoreHorizontal />} aria-label={`${overflowCount} more tabs`} role="tab"/>
      </MenuTrigger>
      <MenuPopover>
        <MenuList>
          {overflowTabs.map((tab) => (<OverflowMenuItem key={tab.id} tab={tab} onClick={() => onTabSelect?.(tab.id)}/>))}
        </MenuList>
      </MenuPopover>
    </Menu>);
};
const OverflowHorizontal = () => {
    const [selectedTabId, setSelectedTabId] = React.useState<string>('today');
    return (<div className="tab-list-elevated-example__overflow tab-list-elevated-example__overflow--horizontal">
      <Overflow minimumVisible={2}>
        <TabList appearance="elevated" selectedValue={selectedTabId} onTabSelect={(_, d) => setSelectedTabId(d.value as string)}>
          {overflowTabs.map((tab) => (<OverflowItem key={tab.id} id={tab.id} priority={tab.id === selectedTabId ? 2 : 1}>
              <Tab value={tab.id} icon={<span>{tab.icon}</span>}>
                {tab.name}
              </Tab>
            </OverflowItem>))}
          <OverflowMenu onTabSelect={setSelectedTabId}/>
        </TabList>
      </Overflow>
    </div>);
};
const OverflowVertical = () => {
    const [selectedTabId, setSelectedTabId] = React.useState<string>('today');
    return (<div className="tab-list-elevated-example__overflow tab-list-elevated-example__overflow--vertical">
      <Overflow minimumVisible={2} overflowAxis="vertical">
        <TabList appearance="elevated" vertical selectedValue={selectedTabId} onTabSelect={(_, d) => setSelectedTabId(d.value as string)}>
          {overflowTabs.map((tab) => (<OverflowItem key={tab.id} id={tab.id} priority={tab.id === selectedTabId ? 2 : 1}>
              <Tab value={tab.id} icon={<span>{tab.icon}</span>}>
                {tab.name}
              </Tab>
            </OverflowItem>))}
          <OverflowMenu onTabSelect={setSelectedTabId}/>
        </TabList>
      </Overflow>
    </div>);
};
// ---------- The story ----------
export const CustomAppearanceElevated = () => {
    const styles = /* css */ `
    .tab-list-elevated-example {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      justify-content: flex-start;
      row-gap: var(--spacingVerticalXXXL);
      padding: var(--spacingVerticalXXXL) var(--spacingHorizontalXL);
    }

    .tab-list-elevated-example__section {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      row-gap: var(--spacingVerticalS);
    }

    .tab-list-elevated-example__section-heading {
      margin: 0;
      color: var(--colorNeutralForeground1);
      font-size: var(--fontSizeBase400);
      font-weight: var(--fontWeightSemibold);
    }

    .tab-list-elevated-example__section-subheading {
      margin: 0;
      color: var(--colorNeutralForeground3);
      font-size: var(--fontSizeBase200);
    }

    .tab-list-elevated-example__row {
      display: flex;
      flex-flow: row wrap;
      align-items: flex-start;
      column-gap: var(--spacingHorizontalXXL);
    }

    .tab-list-elevated-example__panels {
      padding: var(--spacingVerticalS) 0 0;
    }

    .tab-list-elevated-example__panels th {
      padding: 0 30px 0 0;
      text-align: left;
    }

    .tab-list-elevated-example__props-table td {
      padding: 0 30px 0 0;
    }

    .tab-list-elevated-example__props-table td:first-child {
      font-weight: var(--fontWeightSemibold);
    }

    .tab-list-elevated-example__overflow {
      z-index: 0;
      overflow: hidden;
      padding: 5px;
      background-color: var(--colorNeutralBackground2);
    }

    .tab-list-elevated-example__overflow--horizontal {
      width: 600px;
      min-width: 150px;
      height: fit-content;
      resize: horizontal;
    }

    .tab-list-elevated-example__overflow--vertical {
      display: flex;
      align-content: stretch;
      align-items: stretch;
      justify-content: stretch;
      justify-items: stretch;
      width: fit-content;
      height: 250px;
      min-height: 100px;
      resize: vertical;
    }

    .tab-list-elevated-example__menu-button {
      align-self: center;
    }
  `;
    return (<>
      <style>{styles}</style>
      <div className="tab-list-elevated-example">
        {/* 1. Default — appearance + panels combined */}
        <section className="tab-list-elevated-example__section">
          <h3 className="tab-list-elevated-example__section-heading">Default (with panels)</h3>
          <p className="tab-list-elevated-example__section-subheading">
            Selectable tabs that drive a panel below the strip.
          </p>
          <DefaultWithPanels />
        </section>

        {/* 2. Vertical */}
        <section className="tab-list-elevated-example__section">
          <h3 className="tab-list-elevated-example__section-heading">Vertical</h3>
          <TabList appearance="elevated" defaultSelectedValue="tab3" vertical>
            {renderSimpleTabs()}
          </TabList>
        </section>

        {/* 3. Disabled */}
        <section className="tab-list-elevated-example__section">
          <h3 className="tab-list-elevated-example__section-heading">Disabled tab</h3>
          <TabList appearance="elevated" defaultSelectedValue="tab3">
            {renderSimpleTabs('tab2')}
          </TabList>
        </section>

        {/* 4. Sizes — horizontal: small, medium, large stacked */}
        <section className="tab-list-elevated-example__section">
          <h3 className="tab-list-elevated-example__section-heading">Sizes (horizontal)</h3>
          <TabList appearance="elevated" defaultSelectedValue="tab3" size="small">
            {renderSimpleTabs()}
          </TabList>
          <TabList appearance="elevated" defaultSelectedValue="tab3" size="medium">
            {renderSimpleTabs()}
          </TabList>
          <TabList appearance="elevated" defaultSelectedValue="tab3" size="large">
            {renderSimpleTabs()}
          </TabList>
        </section>

        {/* 5. Sizes vertical — laid out in a horizontal row: small, medium, large */}
        <section className="tab-list-elevated-example__section">
          <h3 className="tab-list-elevated-example__section-heading">
            Sizes (vertical, side-by-side)
          </h3>
          <div className="tab-list-elevated-example__row">
            <TabList appearance="elevated" defaultSelectedValue="tab3" vertical size="small">
              {renderSimpleTabs()}
            </TabList>
            <TabList appearance="elevated" defaultSelectedValue="tab3" vertical size="medium">
              {renderSimpleTabs()}
            </TabList>
            <TabList appearance="elevated" defaultSelectedValue="tab3" vertical size="large">
              {renderSimpleTabs()}
            </TabList>
          </div>
        </section>

        {/* 6. With icon */}
        <section className="tab-list-elevated-example__section">
          <h3 className="tab-list-elevated-example__section-heading">With icon</h3>
          <TabList appearance="elevated" defaultSelectedValue="tab2">
            {renderIconTabs()}
          </TabList>
          <TabList appearance="elevated" defaultSelectedValue="tab2" vertical>
            {renderIconTabs()}
          </TabList>
        </section>

        {/* 7. Icon only */}
        <section className="tab-list-elevated-example__section">
          <h3 className="tab-list-elevated-example__section-heading">Icon only</h3>
          <TabList appearance="elevated" defaultSelectedValue="tab2">
            {renderIconTabs(true)}
          </TabList>
          <TabList appearance="elevated" defaultSelectedValue="tab2" vertical>
            {renderIconTabs(true)}
          </TabList>
        </section>

        {/* 8. With overflow */}
        <section className="tab-list-elevated-example__section">
          <h3 className="tab-list-elevated-example__section-heading">With overflow</h3>
          <p className="tab-list-elevated-example__section-subheading">
            Drag the resize handles to shrink the container and trigger the overflow menu.
          </p>
          <OverflowHorizontal />
          <OverflowVertical />
        </section>
      </div>
    </>);
};

export default CustomAppearanceElevated;

Disabled

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { TabList } from "@coreai-ds/react-components";
import { Tab } from "@coreai-ds/react-components";
import { bundleIcon } from "@fluentui/react-icons";
import { CalendarMonthFilled } from "@fluentui/react-icons";
import { CalendarMonthRegular } from "@fluentui/react-icons";
import * as React from 'react';

const useStyles = makeStyles({
    root: {
        alignItems: 'flex-start',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'flex-start',
        padding: '50px 20px',
        rowGap: '20px',
    },
});

const CalendarMonth = bundleIcon(CalendarMonthFilled, CalendarMonthRegular);

export const Disabled = (): JSXElement => {
    const styles = useStyles();
    return (<div className={styles.root}>
      <TabList defaultSelectedValue="tab2" disabled>
        <Tab icon={<CalendarMonth />} value="tab1">
          First Tab
        </Tab>
        <Tab icon={<CalendarMonth />} value="tab2">
          Second Tab
        </Tab>
        <Tab icon={<CalendarMonth />} value="tab3">
          Third Tab
        </Tab>
        <Tab icon={<CalendarMonth />} value="tab4">
          Fourth Tab
        </Tab>
      </TabList>
      <TabList defaultSelectedValue="tab2">
        <Tab icon={<CalendarMonth />} value="tab1">
          First Tab
        </Tab>
        <Tab icon={<CalendarMonth />} value="tab2" disabled>
          Second Tab
        </Tab>
        <Tab icon={<CalendarMonth />} value="tab3" disabled>
          Third Tab
        </Tab>
        <Tab icon={<CalendarMonth />} value="tab4">
          Fourth Tab
        </Tab>
      </TabList>
    </div>);
};

export default Disabled;

Elevated Appearance

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import { Text } from "@coreai-ds/react-components";
import { TabList } from "@coreai-ds/react-components";
import { Tab } from "@coreai-ds/react-components";
import * as React from 'react';

export const ElevatedAppearance = () => {
    const styles = /* css */ `
      .tab-list-elevated-example {
        align-items: flex-start;
        display: flex;
        flex-direction: column;
        justify-content: flex-start;
        padding: var(--spacingVerticalXXL) var(--spacingHorizontalL);
        row-gap: var(--spacingVerticalXXL);
      }
    `;
    return (<>
        <style>{styles}</style>
        <div className="tab-list-elevated-example">
          <Text as="p" block>
            The <code>elevated</code> appearance raises the tab strip onto its own background with
            rounded corners and padding around every tab, instead of the flat underline/indicator
            styling the other appearances use.
          </Text>
          <TabList appearance="elevated" defaultSelectedValue="tab2">
            <Tab value="tab1">First Tab</Tab>
            <Tab value="tab2">Second Tab</Tab>
            <Tab value="tab3">Third Tab</Tab>
          </TabList>
        </div>
      </>);
};

export default ElevatedAppearance;

Horizontal

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { TabList } from "@coreai-ds/react-components";
import { Tab } from "@coreai-ds/react-components";
import * as React from 'react';

const useStyles = makeStyles({
    root: {
        alignItems: 'flex-start',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'flex-start',
        padding: '50px 20px',
        rowGap: '20px',
    },
});

export const Horizontal = (): JSXElement => {
    const styles = useStyles();
    return (<div className={styles.root}>
      <TabList defaultSelectedValue="tab2">
        <Tab value="tab1">First Tab</Tab>
        <Tab value="tab2">Second Tab</Tab>
        <Tab value="tab3">Third Tab</Tab>
        <Tab value="tab4">Fourth Tab</Tab>
      </TabList>
    </div>);
};

export default Horizontal;

Icon Only

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { Tab } from "@coreai-ds/react-components";
import { bundleIcon } from "@fluentui/react-icons";
import { CalendarMonthFilled } from "@fluentui/react-icons";
import { CalendarMonthRegular } from "@fluentui/react-icons";
import { TabList } from "@coreai-ds/react-components";
import * as React from 'react';

const useStyles = makeStyles({
    root: {
        alignItems: 'flex-start',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'flex-start',
        padding: '50px 20px',
        rowGap: '20px',
    },
});

const CalendarMonth = bundleIcon(CalendarMonthFilled, CalendarMonthRegular);

export const IconOnly = (): JSXElement => {
    const styles = useStyles();
    const renderTabs = () => {
        return (<>
        <Tab icon={<CalendarMonth />} value="tab1" aria-label="First Tab"/>
        <Tab icon={<CalendarMonth />} value="tab2" aria-label="Second Tab"/>
        <Tab icon={<CalendarMonth />} value="tab3" aria-label="Third Tab"/>
        <Tab icon={<CalendarMonth />} value="tab4" aria-label="Fourth Tab"/>
      </>);
    };
    return (<div className={styles.root}>
      <TabList defaultSelectedValue="tab2">{renderTabs()}</TabList>
      <TabList defaultSelectedValue="tab2" vertical>
        {renderTabs()}
      </TabList>
    </div>);
};

export default IconOnly;

Left Align Tab Text

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import * as React from 'react';
import type { TabValue } from "@coreai-ds/react-components";
import type { SelectTabEvent } from "@coreai-ds/react-components";
import type { SelectTabData } from "@coreai-ds/react-components";
import { Text } from "@coreai-ds/react-components";
import { TabList } from "@coreai-ds/react-components";
import { Tab } from "@coreai-ds/react-components";

export const LeftAlignTabText = () => {
    const tabContent: Record<string, {
        heading: string;
        body: string;
    }> = {
        overview: {
            heading: 'Overview',
            body: 'A high-level summary of the project, its goals, and current status.',
        },
        activity: {
            heading: 'Activity',
            body: 'A chronological feed of recent changes, comments, and status updates.',
        },
        settings: {
            heading: 'Settings',
            body: 'Configuration options such as notifications, access, and integrations.',
        },
    };
    const [selectedValue, setSelectedValue] = React.useState<TabValue>('overview');
    const onTabSelect = (_event: SelectTabEvent, data: SelectTabData) => {
        setSelectedValue(data.value);
    };
    const { heading, body } = tabContent[selectedValue as string];
    const styles = /* css */ `
      .tab-list-left-align-example {
        display: flex;
        flex-direction: column;
        max-width: 480px;
        row-gap: var(--spacingVerticalXXS);
      }

      .tab-list-left-align-example__title {
        margin: 0;
      }

      .tab-list-left-align-example__tab-list {
        margin-inline: calc(-1 * var(--spacingHorizontalM));
      }

      .tab-list-left-align-example__content {
        color: var(--colorNeutralForeground1);
      }
    `;
    return (<>
        <style>{styles}</style>
        <div className="tab-list-left-align-example">
          <Text as="h2" size={500} weight="semibold" block className="tab-list-left-align-example__title">
            Left-align tab content
          </Text>

          <TabList selectedValue={selectedValue} onTabSelect={onTabSelect} appearance="subtle" className="tab-list-left-align-example__tab-list">
            <Tab value="overview">Overview</Tab>
            <Tab value="activity">Activity</Tab>
            <Tab value="settings">Settings</Tab>
          </TabList>

          <div className="tab-list-left-align-example__content" role="tabpanel" aria-labelledby={selectedValue as string}>
            <Text as="h3" size={300} weight="semibold" block>
              {heading}
            </Text>
            <Text as="p" size={200} weight="regular" block>
              {body}
            </Text>
          </div>
        </div>
      </>);
};

export default LeftAlignTabText;

Select Tab On Focus

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { Tab } from "@coreai-ds/react-components";
import { TabList } from "@coreai-ds/react-components";
import * as React from 'react';

const useStyles = makeStyles({
    root: {
        alignItems: 'flex-start',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'flex-start',
        padding: '50px 20px',
        rowGap: '20px',
    },
});

export const SelectTabOnFocus = (): JSXElement => {
    const styles = useStyles();
    const renderTabs = () => {
        return (<>
        <Tab value="tab1">First Tab</Tab>
        <Tab value="tab2">Second Tab</Tab>
        <Tab value="tab3">Third Tab</Tab>
        <Tab value="tab4">Fourth Tab</Tab>
      </>);
    };
    return (<div className={styles.root}>
      <TabList defaultSelectedValue="tab2" selectTabOnFocus={true}>
        {renderTabs()}
      </TabList>
    </div>);
};

export default SelectTabOnFocus;

Size Large

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { Tab } from "@coreai-ds/react-components";
import { bundleIcon } from "@fluentui/react-icons";
import { CalendarMonthFilled } from "@fluentui/react-icons";
import { CalendarMonthRegular } from "@fluentui/react-icons";
import { TabList } from "@coreai-ds/react-components";
import * as React from 'react';

const useStyles = makeStyles({
    root: {
        alignItems: 'flex-start',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'flex-start',
        padding: '50px 20px',
        rowGap: '20px',
    },
});

const CalendarMonth = bundleIcon(CalendarMonthFilled, CalendarMonthRegular);

export const SizeLarge = (): JSXElement => {
    const styles = useStyles();
    const renderTabs = () => {
        return (<>
        <Tab value="tab1">First Tab</Tab>
        <Tab icon={<CalendarMonth />} value="tab2">
          Second Tab
        </Tab>
        <Tab value="tab3">Third Tab</Tab>
        <Tab value="tab4">Fourth Tab</Tab>
      </>);
    };
    return (<div className={styles.root}>
      <TabList defaultSelectedValue="tab2" size="large">
        {renderTabs()}
      </TabList>
      <TabList defaultSelectedValue="tab2" size="large" vertical>
        {renderTabs()}
      </TabList>
    </div>);
};

export default SizeLarge;

Size Medium

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { Tab } from "@coreai-ds/react-components";
import { bundleIcon } from "@fluentui/react-icons";
import { CalendarMonthFilled } from "@fluentui/react-icons";
import { CalendarMonthRegular } from "@fluentui/react-icons";
import { TabList } from "@coreai-ds/react-components";
import * as React from 'react';

const useStyles = makeStyles({
    root: {
        alignItems: 'flex-start',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'flex-start',
        padding: '50px 20px',
        rowGap: '20px',
    },
});

const CalendarMonth = bundleIcon(CalendarMonthFilled, CalendarMonthRegular);

export const SizeMedium = (): JSXElement => {
    const styles = useStyles();
    const renderTabs = () => {
        return (<>
        <Tab value="tab1">First Tab</Tab>
        <Tab icon={<CalendarMonth />} value="tab2">
          Second Tab
        </Tab>
        <Tab value="tab3">Third Tab</Tab>
        <Tab value="tab4">Fourth Tab</Tab>
      </>);
    };
    return (<div className={styles.root}>
      <TabList defaultSelectedValue="tab2" size="medium">
        {renderTabs()}
      </TabList>
      <TabList defaultSelectedValue="tab2" size="medium" vertical>
        {renderTabs()}
      </TabList>
    </div>);
};

export default SizeMedium;

Size Small

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { Tab } from "@coreai-ds/react-components";
import { bundleIcon } from "@fluentui/react-icons";
import { CalendarMonthFilled } from "@fluentui/react-icons";
import { CalendarMonthRegular } from "@fluentui/react-icons";
import { TabList } from "@coreai-ds/react-components";
import * as React from 'react';

const useStyles = makeStyles({
    root: {
        alignItems: 'flex-start',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'flex-start',
        padding: '50px 20px',
        rowGap: '20px',
    },
});

const CalendarMonth = bundleIcon(CalendarMonthFilled, CalendarMonthRegular);

export const SizeSmall = (): JSXElement => {
    const styles = useStyles();
    const renderTabs = () => {
        return (<>
        <Tab value="tab1">First Tab</Tab>
        <Tab icon={<CalendarMonth />} value="tab2">
          Second Tab
        </Tab>
        <Tab value="tab3">Third Tab</Tab>
        <Tab value="tab4">Fourth Tab</Tab>
      </>);
    };
    return (<div className={styles.root}>
      <TabList defaultSelectedValue="tab2" size="small">
        {renderTabs()}
      </TabList>
      <TabList defaultSelectedValue="tab2" size="small" vertical>
        {renderTabs()}
      </TabList>
    </div>);
};

export default SizeSmall;

Vertical

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { TabList } from "@coreai-ds/react-components";
import { Tab } from "@coreai-ds/react-components";
import * as React from 'react';

const useStyles = makeStyles({
    root: {
        alignItems: 'flex-start',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'flex-start',
        padding: '50px 20px',
        rowGap: '20px',
    },
});

export const Vertical = (): JSXElement => {
    const styles = useStyles();
    return (<div className={styles.root}>
      <TabList defaultSelectedValue="tab2" vertical>
        <Tab value="tab1">First Tab</Tab>
        <Tab value="tab2">Second Tab</Tab>
        <Tab value="tab3">Third Tab</Tab>
        <Tab value="tab4">Fourth Tab</Tab>
      </TabList>
    </div>);
};

export default Vertical;

With Icon

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { Tab } from "@coreai-ds/react-components";
import { bundleIcon } from "@fluentui/react-icons";
import { CalendarMonthFilled } from "@fluentui/react-icons";
import { CalendarMonthRegular } from "@fluentui/react-icons";
import { TabList } from "@coreai-ds/react-components";
import * as React from 'react';

const useStyles = makeStyles({
    root: {
        alignItems: 'flex-start',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'flex-start',
        padding: '50px 20px',
        rowGap: '20px',
    },
});

const CalendarMonth = bundleIcon(CalendarMonthFilled, CalendarMonthRegular);

export const WithIcon = (): JSXElement => {
    const styles = useStyles();
    const renderTabs = () => {
        return (<>
        <Tab icon={<CalendarMonth />} value="tab1">
          First Tab
        </Tab>
        <Tab icon={<CalendarMonth />} value="tab2">
          Second Tab
        </Tab>
        <Tab icon={<CalendarMonth />} value="tab3">
          Third Tab
        </Tab>
        <Tab icon={<CalendarMonth />} value="tab4">
          Fourth Tab
        </Tab>
      </>);
    };
    return (<div className={styles.root}>
      <TabList defaultSelectedValue="tab2">{renderTabs()}</TabList>
      <TabList defaultSelectedValue="tab2" vertical>
        {renderTabs()}
      </TabList>
    </div>);
};

export default WithIcon;

With Overflow

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import * as React from 'react';
import { mergeClasses } from "@coreai-ds/react-components";
import { Overflow } from "@coreai-ds/react-components";
import { TabList } from "@coreai-ds/react-components";
import { bundleIcon } from "@fluentui/react-icons";
import { CalendarTodayFilled } from "@fluentui/react-icons";
import { CalendarTodayRegular } from "@fluentui/react-icons";
import { CalendarAgendaFilled } from "@fluentui/react-icons";
import { CalendarAgendaRegular } from "@fluentui/react-icons";
import { CalendarDayFilled } from "@fluentui/react-icons";
import { CalendarDayRegular } from "@fluentui/react-icons";
import { Calendar3DayFilled } from "@fluentui/react-icons";
import { Calendar3DayRegular } from "@fluentui/react-icons";
import { CalendarWorkWeekFilled } from "@fluentui/react-icons";
import { CalendarWorkWeekRegular } from "@fluentui/react-icons";
import { CalendarWeekStartFilled } from "@fluentui/react-icons";
import { CalendarWeekStartRegular } from "@fluentui/react-icons";
import { CalendarMonthFilled } from "@fluentui/react-icons";
import { CalendarMonthRegular } from "@fluentui/react-icons";
import { CalendarSearchFilled } from "@fluentui/react-icons";
import { CalendarSearchRegular } from "@fluentui/react-icons";
import { CalendarChatFilled } from "@fluentui/react-icons";
import { CalendarChatRegular } from "@fluentui/react-icons";
import { OverflowItem } from "@coreai-ds/react-components";
import { Tab } from "@coreai-ds/react-components";
import { useOverflowMenu } from "@coreai-ds/react-components";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { MoreHorizontalFilled } from "@fluentui/react-icons";
import { MoreHorizontalRegular } from "@fluentui/react-icons";
import { MenuPopover } from "@coreai-ds/react-components";
import { MenuList } from "@coreai-ds/react-components";
import type { MenuItemProps } from "@coreai-ds/react-components";
import { useIsOverflowItemVisible } from "@coreai-ds/react-components";
import { MenuItem } from "@coreai-ds/react-components";

const useStyles = makeStyles({
    root: {
        alignItems: 'flex-start',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'flex-start',
        overflow: 'auto',
        padding: '50px 20px',
        rowGap: '20px',
        minHeight: '600px', //lets the page remain at a minimum height when vertical tabs are resized
    },
});

//----- Stories -----//
const useExampleStyles = makeStyles({
    example: {
        backgroundColor: tokens.colorNeutralBackground2,
        overflow: 'hidden',
        padding: '5px',
        zIndex: 0, //stop the browser resize handle from piercing the overflow menu
    },
    horizontal: {
        height: 'fit-content',
        minWidth: '150px',
        resize: 'horizontal',
        width: '600px',
    },
    vertical: {
        height: '250px',
        minHeight: '100px',
        resize: 'vertical',
        width: 'fit-content',
        display: 'flex',
        alignContent: 'stretch',
        alignItems: 'stretch',
        justifyContent: 'stretch',
        justifyItems: 'stretch',
    },
});

//----- Example Tab Data -----//
type ExampleTab = {
    id: string;
    name: string;
    icon: React.ReactElement;
};

const CalendarToday = bundleIcon(CalendarTodayFilled, CalendarTodayRegular);

const CalendarAgenda = bundleIcon(CalendarAgendaFilled, CalendarAgendaRegular);

const CalendarDay = bundleIcon(CalendarDayFilled, CalendarDayRegular);

const Calendar3Day = bundleIcon(Calendar3DayFilled, Calendar3DayRegular);

const CalendarWorkWeek = bundleIcon(CalendarWorkWeekFilled, CalendarWorkWeekRegular);

const CalendarWeekStart = bundleIcon(CalendarWeekStartFilled, CalendarWeekStartRegular);

const CalendarMonth = bundleIcon(CalendarMonthFilled, CalendarMonthRegular);

const CalendarSearch = bundleIcon(CalendarSearchFilled, CalendarSearchRegular);

const CalendarChat = bundleIcon(CalendarChatFilled, CalendarChatRegular);

const tabs: ExampleTab[] = [
    {
        id: 'today',
        name: 'Today',
        icon: <CalendarToday />,
    },
    {
        id: 'agenda',
        name: 'Agenda',
        icon: <CalendarAgenda />,
    },
    {
        id: 'day',
        name: 'Day',
        icon: <CalendarDay />,
    },
    {
        id: 'threeDay',
        name: 'Three Day',
        icon: <Calendar3Day />,
    },
    {
        id: 'workWeek',
        name: 'Work Week',
        icon: <CalendarWorkWeek />,
    },
    {
        id: 'week',
        name: 'Week',
        icon: <CalendarWeekStart />,
    },
    {
        id: 'month',
        name: 'Month',
        icon: <CalendarMonth />,
    },
    {
        id: 'search',
        name: 'Search',
        icon: <CalendarSearch />,
    },
    {
        id: 'chat',
        name: 'Conversations',
        icon: <CalendarChat />,
    },
];

type OverflowMenuProps = {
    onTabSelect?: (tabId: string) => void;
};

//----- OverflowMenu -----//
const useOverflowMenuStyles = makeStyles({
    menu: {
        backgroundColor: tokens.colorNeutralBackground1,
    },
    menuButton: {
        alignSelf: 'center',
    },
});

const MoreHorizontal = bundleIcon(MoreHorizontalFilled, MoreHorizontalRegular);

//----- OverflowMenuItem -----//
type OverflowMenuItemProps = {
    tab: ExampleTab;
    onClick: MenuItemProps['onClick'];
};

/**
 * A menu item for an overflow menu that only displays when the tab is not visible
 */
const OverflowMenuItem = (props: OverflowMenuItemProps) => {
    const { tab, onClick } = props;
    const isVisible = useIsOverflowItemVisible(tab.id);
    if (isVisible) {
        return null;
    }
    return (<MenuItem key={tab.id} icon={tab.icon} onClick={onClick}>
      <div>{tab.name}</div>
    </MenuItem>);
};

/**
 * A menu for selecting tabs that have overflowed and are not visible.
 */
const OverflowMenu = (props: OverflowMenuProps) => {
    const { onTabSelect } = props;
    const { ref, isOverflowing, overflowCount } = useOverflowMenu<HTMLButtonElement>();
    const styles = useOverflowMenuStyles();
    const onItemClick = (tabId: string) => {
        onTabSelect?.(tabId);
    };
    if (!isOverflowing) {
        return null;
    }
    return (<Menu hasIcons>
      <MenuTrigger disableButtonEnhancement>
        <Button appearance="transparent" className={styles.menuButton} ref={ref} icon={<MoreHorizontal />} aria-label={`${overflowCount} more tabs`} role="tab"/>
      </MenuTrigger>
      <MenuPopover>
        <MenuList className={styles.menu}>
          {tabs.map(tab => (<OverflowMenuItem key={tab.id} tab={tab} onClick={() => onItemClick(tab.id)}/>))}
        </MenuList>
      </MenuPopover>
    </Menu>);
};

const HorizontalExample = () => {
    const styles = useExampleStyles();
    const [selectedTabId, setSelectedTabId] = React.useState<string>('today');
    const onTabSelect = (tabId: string) => {
        setSelectedTabId(tabId);
    };
    return (<div className={mergeClasses(styles.example, styles.horizontal)}>
      <Overflow minimumVisible={2}>
        <TabList selectedValue={selectedTabId} onTabSelect={(_, d) => onTabSelect(d.value as string)}>
          {tabs.map(tab => {
            return (<OverflowItem key={tab.id} id={tab.id} priority={tab.id === selectedTabId ? 2 : 1}>
                <Tab value={tab.id} icon={<span>{tab.icon}</span>}>
                  {tab.name}
                </Tab>
              </OverflowItem>);
        })}
          <OverflowMenu onTabSelect={onTabSelect}/>
        </TabList>
      </Overflow>
    </div>);
};

const VerticalExample = () => {
    const styles = useExampleStyles();
    const [selectedTabId, setSelectedTabId] = React.useState<string>('today');
    const onTabSelect = (tabId: string) => {
        setSelectedTabId(tabId);
    };
    return (<div className={mergeClasses(styles.example, styles.vertical)}>
      <Overflow minimumVisible={2} overflowAxis="vertical">
        <TabList vertical selectedValue={selectedTabId} onTabSelect={(_, d) => onTabSelect(d.value as string)}>
          {tabs.map(tab => {
            return (<OverflowItem key={tab.id} id={tab.id} priority={tab.id === selectedTabId ? 2 : 1}>
                <Tab value={tab.id} icon={<span>{tab.icon}</span>}>
                  {tab.name}
                </Tab>
              </OverflowItem>);
        })}
          <OverflowMenu onTabSelect={onTabSelect}/>
        </TabList>
      </Overflow>
    </div>);
};

export const WithOverflow = (): JSXElement => {
    const styles = useStyles();
    return (<div className={styles.root}>
      <HorizontalExample />
      <VerticalExample />
    </div>);
};

export default WithOverflow;

With Panels

Loading interactive example. Full source is available below.

Download source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import * as React from 'react';
import type { TabValue } from "@coreai-ds/react-components";
import type { SelectTabEvent } from "@coreai-ds/react-components";
import type { SelectTabData } from "@coreai-ds/react-components";
import { TabList } from "@coreai-ds/react-components";
import { Tab } from "@coreai-ds/react-components";
import { bundleIcon } from "@fluentui/react-icons";
import { AirplaneFilled } from "@fluentui/react-icons";
import { AirplaneRegular } from "@fluentui/react-icons";
import { AirplaneTakeOffFilled } from "@fluentui/react-icons";
import { AirplaneTakeOffRegular } from "@fluentui/react-icons";
import { TimeAndWeatherFilled } from "@fluentui/react-icons";
import { TimeAndWeatherRegular } from "@fluentui/react-icons";
const useStyles = makeStyles({
    root: {
        alignItems: 'flex-start',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'flex-start',
        padding: '50px 20px',
        rowGap: '20px',
    },
    panels: {
        padding: '0 10px',
        '& th': {
            textAlign: 'left',
            padding: '0 30px 0 0',
        },
    },
    propsTable: {
        '& td:first-child': {
            fontWeight: tokens.fontWeightSemibold,
        },
        '& td': {
            padding: '0 30px 0 0',
        },
    },
});
const Airplane = bundleIcon(AirplaneFilled, AirplaneRegular);
const AirplaneTakeOff = bundleIcon(AirplaneTakeOffFilled, AirplaneTakeOffRegular);
const TimeAndWeather = bundleIcon(TimeAndWeatherFilled, TimeAndWeatherRegular);
export const WithPanels = (): JSXElement => {
    const styles = useStyles();
    const [selectedValue, setSelectedValue] = React.useState<TabValue>('conditions');
    const onTabSelect = (event: SelectTabEvent, data: SelectTabData) => {
        setSelectedValue(data.value);
    };
    const Arrivals = React.memo(() => (<div role="tabpanel" aria-labelledby="components-tablist--with-panels-Arrivals">
      <table>
        <thead>
          <th>Origin</th>
          <th>Gate</th>
          <th>ETA</th>
        </thead>
        <tbody>
          <tr>
            <td>DEN</td>
            <td>C3</td>
            <td>12:40 PM</td>
          </tr>
          <tr>
            <td>SMF</td>
            <td>D1</td>
            <td>1:18 PM</td>
          </tr>
          <tr>
            <td>SFO</td>
            <td>E18</td>
            <td>1:42 PM</td>
          </tr>
        </tbody>
      </table>
    </div>));
    const Departures = React.memo(() => (<div role="tabpanel" aria-labelledby="components-tablist--with-panels-Departures">
      <table>
        <thead>
          <th>Destination</th>
          <th>Gate</th>
          <th>ETD</th>
        </thead>
        <tbody>
          <tr>
            <td>MSP</td>
            <td>A7</td>
            <td>8:26 AM</td>
          </tr>
          <tr>
            <td>DCA</td>
            <td>N2</td>
            <td>9:03 AM</td>
          </tr>
          <tr>
            <td>LAS</td>
            <td>E15</td>
            <td>2:36 PM</td>
          </tr>
        </tbody>
      </table>
    </div>));
    const Conditions = React.memo(() => (<div role="tabpanel" aria-labelledby="components-tablist--with-panels-Conditions">
      <table className={styles.propsTable}>
        <tbody>
          <tr>
            <td>Time</td>
            <td>6:45 AM</td>
          </tr>
          <tr>
            <td>Temperature</td>
            <td>68F / 20C</td>
          </tr>
          <tr>
            <td>Forecast</td>
            <td>Overcast</td>
          </tr>
          <tr>
            <td>Visibility</td>
            <td>0.5 miles, 1800 ft runway visual range</td>
          </tr>
        </tbody>
      </table>
    </div>));
    return (<div className={styles.root}>
      <TabList selectedValue={selectedValue} onTabSelect={onTabSelect}>
        <Tab id="components-tablist--with-panels-Arrivals" icon={<Airplane />} value="arrivals">
          Arrivals
        </Tab>
        <Tab id="components-tablist--with-panels-Departures" icon={<AirplaneTakeOff />} value="departures">
          Departures
        </Tab>
        <Tab id="components-tablist--with-panels-Conditions" icon={<TimeAndWeather />} value="conditions">
          Conditions
        </Tab>
      </TabList>
      <div className={styles.panels}>
        {selectedValue === 'arrivals' && <Arrivals />}
        {selectedValue === 'departures' && <Departures />}
        {selectedValue === 'conditions' && <Conditions />}
      </div>
    </div>);
};

export default WithPanels;