Skip to content

Tabs

Status: Stable

Latest released: 2018

Current version: v2.1.3

Storybook
GitHub

Standard NerdWallet tabbed UI component. Tabs can be controlled or uncontrolled to modify which tab the user is currently viewing.


Variants

Basic

Hello

Initial Tab Open

The example will show with this tab open initially

Accessibility

The <Tabs> component is built on Reakit's tabs implementation     , which takes care of providing accessibility according to the WAI-ARIA Tabs Pattern     .

Labels

Either aria-label or aria-labelledby must be provided for the component to be accessible. The label will be read by a screen reader as part of the announcement of the tabs when focus initially lands inside the tab group. It should give a high-level description of what the tabs as a whole contain or represent.

  • If aria-label is provided, it must be a string that describes the tabs as a whole.
  • If aria-labelledby is provided, it must be the ID of another element that describes the tabs as a whole.

As an example, the <MarketplaceProductCard>      component contains tabs with additional information about the product. So, an appropriate aria-label value could be "More information about this product".

IDs

The component will automatically generate IDs for internal components using the useId() hook from @nerdwallet/react-accessibility     . If manual control over the IDs is needed, there are two ways to control them:

  • If a baseId prop is provided, this will be used instead of an automatically-generated ID from useId().

    <Tabs
    aria-label="Demo of tabs component"
    baseId="tabs-demo"
    tabs={[
    {
    label: "Hello",
    content: "Hello",
    },
    {
    label: "World",
    content: "World",
    },
    ]}
    />;
  • If the individual items in the tabs array prop have an id property, that will be used for the individual tabs.

    <Tabs
    aria-label="Demo of tabs component"
    tabs={[
    {
    label: "Hello",
    content: "Hello",
    id="tabs-demo-tabs-1",
    },
    {
    label: "World",
    content: "World",
    id="tabs-demo-tabs-2",
    },
    ]}
    />;

In both cases, care should be taken to ensure that the IDs are globally unique on the page the component is rendered on.


Development

import { Tabs } from '@nerdwallet/react-tabs';
<Tabs
aria-label="Demo of tabs component"
baseId="tabs-demo"
tabs={[
{
label: "Hello",
content: "Hello",
},
{
label: "World",
content: "World",
},
]}
/>

Controlled tabs

By default, the <Tabs> component manages its own state. If you need explicit control over the component's state or want to react to state changes, you can use the <ControlledTabs> component in conjunction with the useTabState hook. This is a thin wrapper around Reakit's useTabState hook      that adds APIs based on tab index.

What

Open in Playroom

Tracking

The component has legacy (non-Bedrock) event instrumentation built in to it. Tracking is opt-in.

<Tabs
aria-label="Demo of tabs tracking"
baseId="tabs-demo"
tracking={{
enabled: true,
sectionCategory: 'MY_SECTION_CATEGORY',
}}
tabs={[
{
label: "Hello",
content: "Hello",
// If `trackingProps` is specified on a particular tab, that object will
// be spread into the element interaction payload.
trackingProps: {
myExtraProp: 1234,
},
},
{
label: "World",
content: "World",
},
]}
/>;

Props

<Tabs>

aria-label

string

The value for `aria-label` on the tablist. Either this or `aria-labelledby` must be provided.


aria-labelledby

string

The value for `aria-labelledby` on the tablist. Either this or `aria-label` must be provided.


hasSpacingBetweenTabsAndContent

boolean


tracking

Object

Configuration for legacy event tracking.

{

/**

Whether to enable legacy event tracking; defaults to false.

*/

enabled: Custom validator function
PropTypes.boolean

/**

The section category for legacy tracking events.

*/

sectionCategory: string
}

baseId

string

If provided, this ID will be used to construct unique IDs for the tabs that are rendered by this component. If not provided, a base ID will be automatically generated.


defaultTabId

string

The ID of the tab that should be initially selected.


defaultTabIndex

number

The index of the tab that should be initially selected. If both this prop and `defaultTabId` are provided, `defaultTabId` will take precedence.


tabs

Array<Object>

An array of objects representing the tabs that should be rendered.

Array<{

/**

The title for this tab.

*/

label: node Required

/**

The content for this tab.

*/

content: node Required

/**

An optional ID for the given tab.

*/

id: string
}>

<ControlledTabs>

aria-label

string

The value for `aria-label` on the tablist. Either this or `aria-labelledby` must be provided.


aria-labelledby

string

The value for `aria-labelledby` on the tablist. Either this or `aria-label` must be provided.


hasSpacingBetweenTabsAndContent

boolean


tracking

Object

Configuration for legacy event tracking.

{

/**

Whether to enable legacy event tracking; defaults to false.

*/

enabled: Custom validator function
PropTypes.boolean

/**

The section category for legacy tracking events.

*/

sectionCategory: string
}

tabState

Object

If provided, this prop must be the return value of the `useTabState` hook exported by this component. Providing the tab state allows you to use the component in "controlled" mode, where you can interact with the underlying state. If this prop is not provided, `useTabState` will be called internally by this component so that the component can manage its own state.