Skip to main content

Overview

Tabs organize and allow navigation between groups of content that are related and at the same level of hierarchy. They consist of two components: TabContainer (the container) and TabItem (individual tabs).

Installation

npm install @naturacosmeticos/natds-web

Import

import { TabContainer, TabItem } from '@naturacosmeticos/natds-web';

Props

TabContainer

Inherits all props from Material-UI’s Tabs component.
value
any
required
The value of the currently selected tab.
onChange
(event, value) => void
Callback fired when the value changes.
variant
'standard' | 'scrollable' | 'fullWidth'
Determines the display behavior of tabs. Defaults to 'standard'.
  • standard: Tabs are centered and can wrap
  • scrollable: Tabs are scrollable horizontally
  • fullWidth: Tabs take full width of container
indicatorColor
'primary' | 'secondary'
Color of the active tab indicator. Defaults to 'secondary'.
textColor
'inherit' | 'primary' | 'secondary'
Color of the tab labels. Defaults to 'inherit'.
centered
boolean
If true, tabs will be centered. Only works with variant="standard".
scrollButtons
'auto' | 'on' | 'off'
Determine behavior of scroll buttons. Defaults to 'auto'.
children
ReactNode
The content of the component, typically TabItem components.

TabItem

Inherits all props from Material-UI’s Tab component.
label
ReactNode
The label element for the tab.
icon
ReactNode
The icon element to display for the tab.
value
any
The value to use for identifying the tab (only needed if not using index-based values).
disabled
boolean
If true, the tab will be disabled.
wrapped
boolean
If true, the label will wrap if there isn’t enough space.

Usage

Basic Tabs

import { TabContainer, TabItem } from '@naturacosmeticos/natds-web';
import { useState } from 'react';

function BasicTabs() {
  const [value, setValue] = useState(0);

  const handleChange = (event, newValue) => {
    setValue(newValue);
  };

  return (
    <>
      <TabContainer value={value} onChange={handleChange}>
        <TabItem label="Tab One" />
        <TabItem label="Tab Two" />
        <TabItem label="Tab Three" />
      </TabContainer>
      
      {value === 0 && <div style={{ padding: 16 }}>Content One</div>}
      {value === 1 && <div style={{ padding: 16 }}>Content Two</div>}
      {value === 2 && <div style={{ padding: 16 }}>Content Three</div>}
    </>
  );
}

Tabs with Icons

import { TabContainer, TabItem, Icon } from '@naturacosmeticos/natds-web';
import { useState } from 'react';

function TabsWithIcons() {
  const [value, setValue] = useState(0);

  return (
    <TabContainer value={value} onChange={(e, v) => setValue(v)}>
      <TabItem 
        icon={<Icon name="outlined-action-favorite" />}
        label="Favorites" 
      />
      <TabItem 
        icon={<Icon name="outlined-navigation-home" />}
        label="Home" 
      />
      <TabItem 
        icon={<Icon name="outlined-social-person" />}
        label="Profile" 
      />
    </TabContainer>
  );
}

Icon-Only Tabs

import { TabContainer, TabItem, Icon } from '@naturacosmeticos/natds-web';
import { useState } from 'react';

function IconTabs() {
  const [value, setValue] = useState(0);

  return (
    <TabContainer value={value} onChange={(e, v) => setValue(v)}>
      <TabItem 
        icon={<Icon name="outlined-action-favorite" />}
        aria-label="favorites"
      />
      <TabItem 
        icon={<Icon name="outlined-navigation-home" />}
        aria-label="home"
      />
      <TabItem 
        icon={<Icon name="outlined-social-person" />}
        aria-label="profile"
      />
    </TabContainer>
  );
}

Scrollable Tabs

Use when you have many tabs that don’t fit in the viewport.
import { TabContainer, TabItem } from '@naturacosmeticos/natds-web';
import { useState } from 'react';

function ScrollableTabs() {
  const [value, setValue] = useState(0);

  return (
    <TabContainer 
      value={value} 
      onChange={(e, v) => setValue(v)}
      variant="scrollable"
      scrollButtons="auto"
    >
      <TabItem label="Item One" />
      <TabItem label="Item Two" />
      <TabItem label="Item Three" />
      <TabItem label="Item Four" />
      <TabItem label="Item Five" />
      <TabItem label="Item Six" />
      <TabItem label="Item Seven" />
    </TabContainer>
  );
}

Full Width Tabs

import { TabContainer, TabItem } from '@naturacosmeticos/natds-web';
import { useState } from 'react';

function FullWidthTabs() {
  const [value, setValue] = useState(0);

  return (
    <TabContainer 
      value={value} 
      onChange={(e, v) => setValue(v)}
      variant="fullWidth"
    >
      <TabItem label="Overview" />
      <TabItem label="Details" />
      <TabItem label="Settings" />
    </TabContainer>
  );
}

Centered Tabs

import { TabContainer, TabItem } from '@naturacosmeticos/natds-web';
import { useState } from 'react';

function CenteredTabs() {
  const [value, setValue] = useState(0);

  return (
    <TabContainer 
      value={value} 
      onChange={(e, v) => setValue(v)}
      centered
    >
      <TabItem label="Home" />
      <TabItem label="Products" />
      <TabItem label="About" />
    </TabContainer>
  );
}

Tabs with Different Colors

import { TabContainer, TabItem } from '@naturacosmeticos/natds-web';
import { useState } from 'react';

// Primary text color
function PrimaryTabs() {
  const [value, setValue] = useState(0);

  return (
    <TabContainer 
      value={value} 
      onChange={(e, v) => setValue(v)}
      textColor="primary"
      indicatorColor="primary"
    >
      <TabItem label="Tab One" />
      <TabItem label="Tab Two" />
      <TabItem label="Tab Three" />
    </TabContainer>
  );
}

// Secondary text color
function SecondaryTabs() {
  const [value, setValue] = useState(0);

  return (
    <TabContainer 
      value={value} 
      onChange={(e, v) => setValue(v)}
      textColor="secondary"
      indicatorColor="secondary"
    >
      <TabItem label="Tab One" />
      <TabItem label="Tab Two" />
      <TabItem label="Tab Three" />
    </TabContainer>
  );
}

Tabs in AppBar

import { 
  AppBar, 
  Toolbar,
  TabContainer, 
  TabItem,
  Typography 
} from '@naturacosmeticos/natds-web';
import { useState } from 'react';

function TabsInAppBar() {
  const [value, setValue] = useState(0);

  return (
    <AppBar position="static">
      <Toolbar>
        <Typography variant="h6" style={{ marginRight: 32 }}>
          My App
        </Typography>
        <TabContainer 
          value={value} 
          onChange={(e, v) => setValue(v)}
          textColor="inherit"
          variant="fullWidth"
          scrollButtons="off"
        >
          <TabItem label="Home" />
          <TabItem label="Products" />
          <TabItem label="About" />
          <TabItem label="Contact" />
        </TabContainer>
      </Toolbar>
    </AppBar>
  );
}

Disabled Tab

import { TabContainer, TabItem } from '@naturacosmeticos/natds-web';
import { useState } from 'react';

function DisabledTab() {
  const [value, setValue] = useState(0);

  return (
    <TabContainer value={value} onChange={(e, v) => setValue(v)}>
      <TabItem label="Active" />
      <TabItem label="Disabled" disabled />
      <TabItem label="Active" />
    </TabContainer>
  );
}

With Tab Panels

import { TabContainer, TabItem } from '@naturacosmeticos/natds-web';
import { useState } from 'react';

function TabPanel({ children, value, index }) {
  return (
    <div
      role="tabpanel"
      hidden={value !== index}
      id={`tabpanel-${index}`}
      aria-labelledby={`tab-${index}`}
    >
      {value === index && (
        <div style={{ padding: 24 }}>
          {children}
        </div>
      )}
    </div>
  );
}

function TabsWithPanels() {
  const [value, setValue] = useState(0);

  return (
    <>
      <TabContainer value={value} onChange={(e, v) => setValue(v)}>
        <TabItem label="Overview" id="tab-0" aria-controls="tabpanel-0" />
        <TabItem label="Details" id="tab-1" aria-controls="tabpanel-1" />
        <TabItem label="Settings" id="tab-2" aria-controls="tabpanel-2" />
      </TabContainer>
      
      <TabPanel value={value} index={0}>
        <h2>Overview Content</h2>
        <p>This is the overview section.</p>
      </TabPanel>
      <TabPanel value={value} index={1}>
        <h2>Details Content</h2>
        <p>This is the details section.</p>
      </TabPanel>
      <TabPanel value={value} index={2}>
        <h2>Settings Content</h2>
        <p>This is the settings section.</p>
      </TabPanel>
    </>
  );
}

Best Practices

  • Use 2-5 tabs for optimal usability
  • Keep tab labels short and descriptive (1-2 words)
  • Use sentence case for tab labels
  • Don’t mix icons and text inconsistently across tabs
  • Use scrollable variant when you have many tabs
  • Don’t use tabs for sequential navigation (use Stepper instead)
  • Ensure the first tab contains the most important content

Accessibility

  • Tabs automatically implement proper ARIA roles and attributes
  • Use Arrow keys to navigate between tabs
  • Press Enter or Space to activate a tab
  • Include aria-label for icon-only tabs
  • Tab panels should have role="tabpanel" and proper ARIA attributes
  • Ensure adequate color contrast for selected and unselected states
  • Test with keyboard navigation

Responsive Considerations

  • Use variant="scrollable" on mobile devices
  • Use variant="fullWidth" for 2-3 tabs on smaller screens
  • Consider hiding tab labels on very small screens (icon-only)
  • Test overflow behavior with different tab quantities

Common Patterns

Product Details Tabs

<TabContainer value={value} onChange={handleChange}>
  <TabItem label="Overview" />
  <TabItem label="Specifications" />
  <TabItem label="Reviews" />
  <TabItem label="Q&A" />
</TabContainer>

User Profile Tabs

<TabContainer value={value} onChange={handleChange}>
  <TabItem label="Posts" />
  <TabItem label="About" />
  <TabItem label="Photos" />
  <TabItem label="Friends" />
</TabContainer>

Settings Tabs

<TabContainer value={value} onChange={handleChange} orientation="vertical">
  <TabItem label="Profile" />
  <TabItem label="Account" />
  <TabItem label="Privacy" />
  <TabItem label="Notifications" />
</TabContainer>

Material-UI Reference

These components are based on Material-UI’s Tabs and Tab. For advanced usage, see the Material-UI Tabs documentation.

Build docs developers (and LLMs) love