Skip to content

Tabs

Status: Stable

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

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

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>

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

defaultTabIndex

number

tabs

Required
Array<{
label: string
content: ReactNode
id?: string
trackingProps?: Record<string, any>
}>

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
Adds spacing between the tabs list and the tab contents.

tracking

{
enabled: boolean
parentImpressionId?: string
sectionCategory: string
}
Configuration for legacy event tracking.

<ControlledTabs>

tabState

Required
TabState
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.

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
Adds spacing between the tabs list and the tab contents.

tracking

{
enabled: boolean
parentImpressionId?: string
sectionCategory: string
}
Configuration for legacy event tracking.