Tabs

Use to alternate among related views within the same context.

Use for most cases, especially when the number of tabs may be more than three.

import {Card, Tabs} from '@shopify/polaris';
import {useState, useCallback} from 'react';

function TabsExample() {
  const [selected, setSelected] = useState(0);

  const handleTabChange = useCallback(
    (selectedTabIndex) => setSelected(selectedTabIndex),
    [],
  );

  const tabs = [
    {
      id: 'all-customers-1',
      content: 'All',
      accessibilityLabel: 'All customers',
      panelID: 'all-customers-content-1',
    },
    {
      id: 'accepts-marketing-1',
      content: 'Accepts marketing',
      panelID: 'accepts-marketing-content-1',
    },
    {
      id: 'repeat-customers-1',
      content: 'Repeat customers',
      panelID: 'repeat-customers-content-1',
    },
    {
      id: 'prospects-1',
      content: 'Prospects',
      panelID: 'prospects-content-1',
    },
  ];

  return (
    <Card>
      <Tabs tabs={tabs} selected={selected} onSelect={handleTabChange}>
        <Card.Section title={tabs[selected].content}>
          <p>Tab {selected} selected</p>
        </Card.Section>
      </Tabs>
    </Card>
  );
}

Use when tabs contain a few (2 or 3) items within a narrow column.

import {Card, Tabs} from '@shopify/polaris';
import {useState, useCallback} from 'react';

function FittedTabsExample() {
  const [selected, setSelected] = useState(0);

  const handleTabChange = useCallback(
    (selectedTabIndex) => setSelected(selectedTabIndex),
    [],
  );

  const tabs = [
    {
      id: 'all-customers-fitted-2',
      content: 'All',
      accessibilityLabel: 'All customers',
      panelID: 'all-customers-fitted-content-2',
    },
    {
      id: 'accepts-marketing-fitted-2',
      content: 'Accepts marketing',
      panelID: 'accepts-marketing-fitted-Ccontent-2',
    },
  ];

  return (
    <Card>
      <Tabs tabs={tabs} selected={selected} onSelect={handleTabChange} fitted>
        <Card.Section title={tabs[selected].content}>
          <p>Tab {selected} selected</p>
        </Card.Section>
      </Tabs>
    </Card>
  );
}

Use to inform a piece of information about the tabs.

import {Badge, Card, Tabs} from '@shopify/polaris';
import {useState, useCallback} from 'react';

function TabsWithBadgeExample() {
  const [selected, setSelected] = useState(0);

  const handleTabChange = useCallback(
    (selectedTabIndex) => setSelected(selectedTabIndex),
    [],
  );

  const tabs = [
    {
      id: 'all-customers-fitted-3',
      content: (
        <span>
          All <Badge status="new">10+</Badge>
        </span>
      ),
      accessibilityLabel: 'All customers',
      panelID: 'all-customers-fitted-content-3',
    },
    {
      id: 'accepts-marketing-fitted-3',
      content: (
        <span>
          Accepts marketing <Badge status="new">4</Badge>
        </span>
      ),
      panelID: 'accepts-marketing-fitted-content-3',
    },
  ];

  return (
    <Card>
      <Tabs tabs={tabs} selected={selected} onSelect={handleTabChange} fitted>
        <Card.Section title={tabs[selected].content}>
          <p>Tab {selected} selected</p>
        </Card.Section>
      </Tabs>
    </Card>
  );
}

Use to provide information about the popover contents

import {Card, Tabs} from '@shopify/polaris';
import {useState, useCallback} from 'react';

function TabsWithCustomDisclosureExample() {
  const [selected, setSelected] = useState(0);

  const handleTabChange = useCallback(
    (selectedTabIndex) => setSelected(selectedTabIndex),
    [],
  );

  const tabs = [
    {
      id: 'all-customers-4',
      content: 'All',
      accessibilityLabel: 'All customers',
      panelID: 'all-customers-content-4',
    },
    {
      id: 'accepts-marketing-4',
      content: 'Accepts marketing',
      panelID: 'accepts-marketing-content-4',
    },
    {
      id: 'repeat-customers-4',
      content: 'Repeat customers',
      panelID: 'repeat-customers-content-4',
    },
    {
      id: 'prospects-4',
      content: 'Prospects',
      panelID: 'prospects-content-4',
    },
  ];

  return (
    <Card>
      <Tabs
        tabs={tabs}
        selected={selected}
        onSelect={handleTabChange}
        disclosureText="More views"
      >
        <Card.Section title={tabs[selected].content}>
          <p>Tab {selected} selected</p>
        </Card.Section>
      </Tabs>
    </Card>
  );
}

Props

Want to help make this feature better? Please share your feedback.

interface TabsProps
children?React.ReactNode

Content to display in tabs.

selectednumber

Index of selected tab.

tabs[]

List of tabs.

fitted?boolean

Fit tabs to container.

disclosureText?string

Text to replace disclosures horizontal dots.

onSelect?(selectedTabIndex: number) => void

Callback when tab is selected.

Best practices

Tabs should:

  • Represent the same kind of content, such as a list-view with different filters applied. Don’t use tabs to group content that is dissimilar.
  • Only be active one at a time.
  • Not force merchants to jump back and forth to do a single task. Merchants should be able to complete their work and find what they need under each tab.
  • Not be used for primary navigation.

Content guidelines

Tabs

Tabs should:

  • Be clearly labeled to help differentiate the different sections beneath them.

  • Have short and scannable labels, generally kept to single word.

  • Relate to the section of Shopify they’re on. Imagine the page section title is an invisible noun after the tab. For example, the tabs for the orders section are:

    • All
    • Open
    • Unfulfilled
    • Unpaid

The tabs for the gift cards section are:

  • All
  • New
  • Partially used
  • Used
  • Disabled

And for the customers section, the tabs are:

  • All
  • New
  • Returning
  • Abandoned checkouts
  • Email subscribers

Where possible, follow this pattern when writing tabs.