Skip to Content

Tabs

Tabs make it easy to explore and switch between different views or functional aspects of an app, or to browse categorized data sets.

import * as React from 'react';
import { Tabs } from '@itwin/itwinui-react';

export default () => {
  return (
    <Tabs.Wrapper className='demo-container'>
      <Tabs.TabList>
        <Tabs.Tab value='apple' label='Apple' key='apple' />
        <Tabs.Tab value='orange' label='Orange' key='orange' />
        <Tabs.Tab value='pear' label='Pear' key='pear' />
      </Tabs.TabList>

      <Tabs.Panel value='apple' key='apple'>
        An apple is a round, edible fruit produced by an apple tree (Malus
        domestica). Apple trees are cultivated worldwide and are the most widely
        grown species in the genus Malus.
      </Tabs.Panel>
      <Tabs.Panel value='orange' key='orange'>
        An orange is a fruit of various citrus species in the family Rutaceae
        (see list of plants known as orange); it primarily refers to Citrus x
        sinensis, which is also called sweet orange, to distinguish it from the
        related Citrus x aurantium, referred to as bitter orange.
      </Tabs.Panel>
      <Tabs.Panel value='pear' key='pear'>
        Pears are fruits produced and consumed around the world, growing on a
        tree and harvested in late summer into mid-autumn.
      </Tabs.Panel>
    </Tabs.Wrapper>
  );
};

Usage

Composition API

You can build Tabs with subcomponents that are fully customizable.

<Tabs.Wrapper>
<Tabs.TabList>
<Tabs.Tab value='apple' label='Apple' key='apple' />
<Tabs.Tab value='orange' label='Orange' key='orange' />
<Tabs.Tab value='pear' label='Pear' key='pear' />
</Tabs.TabList>
<Tabs.Panel value='apple' key='apple'>
{/*...Content for apple*/}
</Tabs.Panel>
<Tabs.Panel value='orange' key='orange'>
{/*...Content for orange*/}
</Tabs.Panel>
<Tabs.Panel value='pear' key='pear'>
{/*...Content for pear*/}
</Tabs.Panel>
</Tabs.Wrapper>

Tabs.Tab and Tabs.Panel can be associated with each other by passing them the same value. Tabs.Panel will be shown when its value matches the value of the currently active Tabs.Tab.

Tabs.Tab has a label prop for ease of use. You can also build Tabs.Tab with subcomponents and add a sublabel or an icon to your tab.

<Tabs.Tab value='apple' key='apple' label='Apple' />
<Tabs.Tab value='apple' key='apple'>
<Tabs.TabIcon>
<SvgAppleIcon />
</Tabs.TabIcon>
<Tabs.TabLabel>Apple</Tabs.TabLabel>
<Tabs.TabDescription>A red fruit</Tabs.TabDescription>
</Tabs.Tab>

Legacy API

Alternatively, you can use Tabs directly with labels, actions, and children as panels. Although this pattern can suffice for simple cases, we strongly recommend using composition API for the best experience.

The following code is (mostly) equivalent to the composition example above:

<Tabs
labels={[
<Tab key='apple' label='Apple' />,
<Tab key='orange' label='Orange' />,
<Tab key='pear' label='Pear' />,
]}
>
{/* … content for active tab */}
</Tabs>

One difference is that the legacy API requires the panel content to be conditionally rendered only for the currently active tab. This can be problematic if the content is expensive to render, or if you need to preserve some state when switching tabs.

Controlled state

By default, the tabs maintain their own state. You can specify the initially active tab using the defaultValue prop in Tabs.Wrapper; the tabs will continue to maintain their own state after the initial render.

If you need to manually maintain the active state, you can use value and onValueChange props in Tabs.Wrapper.

import * as React from 'react';
import { Tabs } from '@itwin/itwinui-react';

export default () => {
  const [currentTabValue, setCurrentTabValue] = React.useState();

  return (
    <Tabs.Wrapper
      value={currentTabValue}
      onValueChange={(value) => setCurrentTabValue(value)}
      defaultValue='pear'
      className='demo-container'
    >
      <Tabs.TabList>
        <Tabs.Tab value='apple' label='Apple' key='apple' />
        <Tabs.Tab value='orange' label='Orange' key='orange' />
        <Tabs.Tab value='pear' label='Pear' key='pear' />
      </Tabs.TabList>

      <Tabs.Panel value='apple' key='apple'>
        An apple is a round, edible fruit produced by an apple tree (Malus
        domestica). Apple trees are cultivated worldwide and are the most widely
        grown species in the genus Malus.
      </Tabs.Panel>
      <Tabs.Panel value='orange' key='orange'>
        An orange is a fruit of various citrus species in the family Rutaceae
        (see list of plants known as orange); it primarily refers to Citrus x
        sinensis, which is also called sweet orange, to distinguish it from the
        related Citrus x aurantium, referred to as bitter orange.
      </Tabs.Panel>
      <Tabs.Panel value='pear' key='pear'>
        Pears are fruits produced and consumed around the world, growing on a
        tree and harvested in late summer into mid-autumn.
      </Tabs.Panel>
    </Tabs.Wrapper>
  );
};

Resetting panel state

When using the composition API, inactive panels will be hidden but will not be unmounted. This approach is more performant and preserves state.

If you need to reset the state of the inactive panels, you can pass a key to Tabs.Panel. For example, you can set the key to the currently active tab’s value (following the controlled state example from above).

<Tabs.Panel value='apple' key={currentTabValue}>
</Tabs.Panel>

Keyboard activation mode

By default, tabs are activated automatically when focused (e.g. with keyboard). In other words, when a tab has keyboard focus, pressing the arrow keys to focus a different tab will automatically activate that tab.

While the default behavior should work fine in many cases, it can hurt the user experience for keyboard users if the panel content is expensive to render or lazily loaded. In such cases, you can set focusActivationMode to "manual" to disable automatic activation. This will allow the user to navigate between tabs with the arrow keys without activating them. The user can then activate a tab by pressing the Enter or Space key.

Variants

Vertical

The orientation prop can be used to show vertical tabs.

import * as React from 'react';
import { Tabs } from '@itwin/itwinui-react';
import {
  SvgDocument,
  SvgFilter,
  SvgAirplane,
} from '@itwin/itwinui-icons-react';

export default () => {
  return (
    <Tabs.Wrapper orientation='vertical'>
      <Tabs.TabList>
        <Tabs.Tab value='apple' key='apple'>
          <Tabs.TabIcon>
            <SvgDocument />
          </Tabs.TabIcon>
          <Tabs.TabLabel>Apple</Tabs.TabLabel>
          <Tabs.TabDescription>A red fruit</Tabs.TabDescription>
        </Tabs.Tab>
        <Tabs.Tab value='orange' key='orange' disabled>
          <Tabs.TabIcon>
            <SvgFilter />
          </Tabs.TabIcon>
          <Tabs.TabLabel>Orange</Tabs.TabLabel>
          <Tabs.TabDescription>A disabled fruit</Tabs.TabDescription>
        </Tabs.Tab>
        <Tabs.Tab value='pear' key='pear'>
          <Tabs.TabIcon>
            <SvgAirplane />
          </Tabs.TabIcon>
          <Tabs.TabLabel>Pear</Tabs.TabLabel>
          <Tabs.TabDescription>A green fruit</Tabs.TabDescription>
        </Tabs.Tab>
      </Tabs.TabList>

      <Tabs.Panel value='apple' key='apple'>
        An apple is a round, edible fruit produced by an apple tree (Malus
        domestica). Apple trees are cultivated worldwide and are the most widely
        grown species in the genus Malus.
      </Tabs.Panel>
      <Tabs.Panel value='orange' key='orange'>
        An orange is a fruit of various citrus species in the family Rutaceae
        (see list of plants known as orange); it primarily refers to Citrus x
        sinensis, which is also called sweet orange, to distinguish it from the
        related Citrus x aurantium, referred to as bitter orange.
      </Tabs.Panel>
      <Tabs.Panel value='pear' key='pear'>
        Pears are fruits produced and consumed around the world, growing on a
        tree and harvested in late summer into mid-autumn.
      </Tabs.Panel>
    </Tabs.Wrapper>
  );
};

Borderless

The type prop can be set to "borderless" to show borderless tabs.

As their name implies, borderless tabs have no frame or stroke surrounding them.

Use borderless tabs when the tabbed content can be easily told apart from its surroundings (or lack thereof).

import * as React from 'react';
import { Tabs } from '@itwin/itwinui-react';

export default () => {
  return (
    <Tabs.Wrapper type='borderless' className='demo-container'>
      <Tabs.TabList>
        <Tabs.Tab value='apple' label='Apple' key='apple' />
        <Tabs.Tab value='orange' label='Orange' key='orange' />
        <Tabs.Tab value='pear' label='Pear' key='pear' />
      </Tabs.TabList>

      <Tabs.Panel value='apple' key='apple'>
        An apple is a round, edible fruit produced by an apple tree (Malus
        domestica). Apple trees are cultivated worldwide and are the most widely
        grown species in the genus Malus.
      </Tabs.Panel>
      <Tabs.Panel value='orange' key='orange'>
        An orange is a fruit of various citrus species in the family Rutaceae
        (see list of plants known as orange); it primarily refers to Citrus x
        sinensis, which is also called sweet orange, to distinguish it from the
        related Citrus x aurantium, referred to as bitter orange.
      </Tabs.Panel>
      <Tabs.Panel value='pear' key='pear'>
        Pears are fruits produced and consumed around the world, growing on a
        tree and harvested in late summer into mid-autumn.
      </Tabs.Panel>
    </Tabs.Wrapper>
  );
};

Pill

The type prop can be set to "pill" to show pill tabs.

Pill tabs are meant to be used with content that belong to a similar category. They act like a filter for toggling through different states of similar content.

The maximum recommended amount of pill tabs is 4.

import * as React from 'react';
import { Tabs } from '@itwin/itwinui-react';

export default () => {
  return (
    <Tabs.Wrapper type='pill' className='demo-container'>
      <Tabs.TabList>
        <Tabs.Tab value='apple' label='Apple' key='apple' />
        <Tabs.Tab value='orange' label='Orange' key='orange' />
        <Tabs.Tab value='pear' label='Pear' key='pear' />
      </Tabs.TabList>

      <Tabs.Panel value='apple' key='apple'>
        An apple is a round, edible fruit produced by an apple tree (Malus
        domestica). Apple trees are cultivated worldwide and are the most widely
        grown species in the genus Malus.
      </Tabs.Panel>
      <Tabs.Panel value='orange' key='orange'>
        An orange is a fruit of various citrus species in the family Rutaceae
        (see list of plants known as orange); it primarily refers to Citrus x
        sinensis, which is also called sweet orange, to distinguish it from the
        related Citrus x aurantium, referred to as bitter orange.
      </Tabs.Panel>
      <Tabs.Panel value='pear' key='pear'>
        Pears are fruits produced and consumed around the world, growing on a
        tree and harvested in late summer into mid-autumn.
      </Tabs.Panel>
    </Tabs.Wrapper>
  );
};

Actions

The Tabs.Action subcomponent can be used to add action buttons to the end of tab list.

import * as React from 'react';
import { Tabs, Button } from '@itwin/itwinui-react';

export default () => {
  return (
    <Tabs.Wrapper className='demo-container'>
      <Tabs.TabList>
        <Tabs.Tab value='apple' label='Apple' key='apple' />
        <Tabs.Tab value='orange' label='Orange' key='orange' />
        <Tabs.Tab value='pear' label='Pear' key='pear' />
      </Tabs.TabList>

      <Tabs.Actions>
        <Button size='small'>My action</Button>
      </Tabs.Actions>

      <Tabs.Panel value='apple' key='apple'>
        An apple is a round, edible fruit produced by an apple tree (Malus
        domestica). Apple trees are cultivated worldwide and are the most widely
        grown species in the genus Malus.
      </Tabs.Panel>
      <Tabs.Panel value='orange' key='orange'>
        An orange is a fruit of various citrus species in the family Rutaceae
        (see list of plants known as orange); it primarily refers to Citrus x
        sinensis, which is also called sweet orange, to distinguish it from the
        related Citrus x aurantium, referred to as bitter orange.
      </Tabs.Panel>
      <Tabs.Panel value='pear' key='pear'>
        Pears are fruits produced and consumed around the world, growing on a
        tree and harvested in late summer into mid-autumn.
      </Tabs.Panel>
    </Tabs.Wrapper>
  );
};

Props

Unfinished

Prop Description Default
actions
Content displayed to the right/bottom of the horizontal/vertical tabs
If type = 'pill', actions is not applicable.
ReactNode[]
labels
Elements shown for each tab. Recommended to pass an array of Tab components.
ReactNode[]
onTabSelected
Handler for activating a tab.
(index: number) => void
activeIndex
Index of the active tab.
number
focusActivationMode
Control whether focusing tabs (using arrow keys) should automatically select them. Use 'manual' if tab panel content is not preloaded.
"auto" | "manual"
'auto'
color
Color of the bar on the active tab.
"blue" | "green"
'blue'
tabsClassName
Custom CSS class name for tabs.
string
contentClassName
Custom CSS class name for tab panel.
string
wrapperClassName
Custom CSS class name for the tabs wrapper.
string
children
Content inside the tab panel.
ReactNode
overflowOptions
@deprecated Tabs will now overflow by default, so this prop does nothing.
{ useOverflow?: boolean; }
defaultValue
never
defaultChecked
never
orientation
Orientation of the tabs.
"horizontal" | "vertical"
'horizontal'
type
Type of the tabs.
If orientation = 'vertical', pill is not applicable.
"default" | "borderless" | "pill"
'default'
as
"symbol" | "object" | "button" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "canvas" | ... 159 more ... | FunctionComponent<...>