A component to switch between different views within the same context.

Importing

The components can be imported via:

import {
	Tabs,
	TabsList,
	TabsTab,
	TabsPanel,
} from '@customerio/pluma-components/react';

PlumaTabs renders a group of tab buttons, and accepts their respective contents. The component follows the WAI ARIA APG Tabs pattern. It includes keyboard navigation (left/right arrows, Home and End keys to move between tabs, and Space or Enter to select a tab), as well as accessibility support (via the recommended aria attributes). It is not meant to be used for tabbed navigation where each tab is a link to a different page, or the same page with different query parameters - because links follow different semantic rules. For a tabbed navigation interface that consists of links, please see PlumaTabNav.

PlumaTabs accepts a tabs array of objects, defined by the TabsTabItem interface. A value (a unique id for the tab) and text string content must be provided for each tab. Additionally, the tabs' contents should be provided, wrapped in PlumaTabsPanel components, to associate them with their respective tab buttons (linked via the value string ids).

Intelligent, vocal, territorial, striking black-and-white bird

<Tabs
	tabs={[
		{ value: 'australian_magpie', text: 'Australian magpie' },
		{ value: 'galah', text: 'Galah' },
		{ value: 'rainbow_lorikeet', text: 'Rainbow lorikeet' },
	]}
>
	<TabsPanel value="australian_magpie">
		<Box p="200">
			<Paragraph>
				Intelligent, vocal, territorial, striking black-and-white bird
			</Paragraph>
		</Box>
	</TabsPanel>

	<TabsPanel value="galah">
		<Box p="200">
			<Paragraph>
				Pink and grey parrot with playful behavior and distinctive crest
			</Paragraph>
		</Box>
	</TabsPanel>

	<TabsPanel value="rainbow_lorikeet">
		<Box p="200">
			<Paragraph>
				Colorful parrot with vibrant plumage and a playful, energetic nature
			</Paragraph>
		</Box>
	</TabsPanel>
</Tabs>

State

Initial state

An initially selected tab can be chosen by providing the activeTab prop:

Pink and grey parrot with playful behavior and distinctive crest

<Tabs
	tabs={[
		{ value: 'australian_magpie', text: 'Australian magpie' },
		{ value: 'galah', text: 'Galah' },
		{ value: 'rainbow_lorikeet', text: 'Rainbow lorikeet' },
	]}
	activeTab="galah"
>
	<TabsPanel value="australian_magpie" p="200">
		<Paragraph>
			Intelligent, vocal, territorial, striking black-and-white bird
		</Paragraph>
	</TabsPanel>

	<TabsPanel value="galah" p="200">
		<Paragraph>
			Pink and grey parrot with playful behavior and distinctive crest
		</Paragraph>
	</TabsPanel>

	<TabsPanel value="rainbow_lorikeet" p="200">
		<Paragraph>
			Colorful parrot with vibrant plumage and a playful, energetic nature
		</Paragraph>
	</TabsPanel>
</Tabs>

Controlled state

The active tab state can be fully controlled by providing both activeTab and onChange:

Intelligent, vocal, territorial, striking black-and-white bird

import { Tabs, TabsPanel, Paragraph } from '@customerio/pluma-components/react';
import { useState } from 'react';

export default function Example() {
	const [activeTab, setActiveTab] = useState('australian_magpie');

	return (
		<Tabs
			tabs={[
				{ value: 'australian_magpie', text: 'Australian magpie' },
				{ value: 'galah', text: 'Galah' },
				{ value: 'rainbow_lorikeet', text: 'Rainbow lorikeet' },
			]}
			activeTab={activeTab}
			onChange={setActiveTab}
		>
			<TabsPanel value="australian_magpie" p="200">
				<Paragraph>
					Intelligent, vocal, territorial, striking black-and-white bird
				</Paragraph>
			</TabsPanel>

			<TabsPanel value="galah" p="200">
				<Paragraph>
					Pink and grey parrot with playful behavior and distinctive crest
				</Paragraph>
			</TabsPanel>

			<TabsPanel value="rainbow_lorikeet" p="200">
				<Paragraph>
					Colorful parrot with vibrant plumage and a playful, energetic nature
				</Paragraph>
			</TabsPanel>
		</Tabs>
	);
}

Note: When onChange is provided, the component will no longer keep track of the active tab internally, and activeTab will need to be set from the callback for the tab state to change.

Alignment

By default, tabs are aligned to the left (the start of the flex container). In some cases, we may need to change the alignment - for example when rendering tabs in a modal where we would like to center them, but still preserve the full-width bottom border.

The TabsList components is built using the InlineStack component, and accepts the same props. In this case, the alignInline prop can control horizontal alignment.

Additionally, TabsList accepts a tabsListAlignInline prop, which is propagated into the TabsList.

Intelligent, vocal, territorial, striking black-and-white bird

import { Tabs, TabsPanel, Paragraph } from '@customerio/pluma-components/react';
import { useState } from 'react';

export default function Example() {
	const [activeTab, setActiveTab] = useState('australian_magpie');

	return (
		<Tabs
			tabs={[
				{ value: 'australian_magpie', text: 'Australian magpie' },
				{ value: 'galah', text: 'Galah' },
				{ value: 'rainbow_lorikeet', text: 'Rainbow lorikeet' },
			]}
			activeTab={activeTab}
			onChange={setActiveTab}
			tabsListAlignInline="center"
		>
			<TabsPanel value="australian_magpie" p="200">
				<Paragraph>
					Intelligent, vocal, territorial, striking black-and-white bird
				</Paragraph>
			</TabsPanel>

			<TabsPanel value="galah" p="200">
				<Paragraph>
					Pink and grey parrot with playful behavior and distinctive crest
				</Paragraph>
			</TabsPanel>

			<TabsPanel value="rainbow_lorikeet" p="200">
				<Paragraph>
					Colorful parrot with vibrant plumage and a playful, energetic nature
				</Paragraph>
			</TabsPanel>
		</Tabs>
	);
}

Tab icons

An icon can be rendered in a tab by setting the icon key on the tab object. Additionally, the icon's color can be set with iconColor (which should be one of the supported Icon component colors).

Tab 1 content

<Tabs
	tabs={[
		{ 
			value: 'tab_1', 
			text: 'Tab 1',
			icon: 'check-circle',
			iconColor: 'success',
		},
		{ 
			value: 'tab_2', 
			text: 'Tab 2',
			icon: 'check-circle',
		},
		{ 
			value: 'tab_3', 
			text: 'Tab 3',
			icon: 'check-circle',
		},
	]}
>
	<TabsPanel value="tab_1" p="200">
		<Paragraph>
			Tab 1 content
		</Paragraph>
	</TabsPanel>

	<TabsPanel value="tab_2" p="200">
		<Paragraph>
			Tab 2 content
		</Paragraph>
	</TabsPanel>

	<TabsPanel value="tab_3" p="200">
		<Paragraph>
			Tab 3 content
		</Paragraph>
	</TabsPanel>
</Tabs>

Tab badges

A Badge can be rendered in a tab by providing a badge string on the tab object. The string will be rendered inside the badge.

Campaigns content

<Tabs
	tabs={[
		{ 
			value: 'campaigns', 
			text: 'Campaigns',
			icon: 'campaigns',
			badge: '123',
		},
		{ 
			value: 'newsletters', 
			text: 'Newsletters',
			icon: 'newsletter',
			badge: '5',
		},
	]}
>
	<TabsPanel value="campaigns" p="200">
		<Paragraph>
			Campaigns content
		</Paragraph>
	</TabsPanel>

	<TabsPanel value="newsletters" p="200">
		<Paragraph>
			Newsletters content
		</Paragraph>
	</TabsPanel>
</Tabs>

Disabling tabs

A tab can be disabled by setting isDisabled on the tab object:

Intelligent, vocal, territorial, striking black-and-white bird

<Tabs
	tabs={[
		{ value: 'australian_magpie', text: 'Australian magpie' },
		{ value: 'galah', text: 'Galah', isDisabled: true },
		{ value: 'rainbow_lorikeet', text: 'Rainbow lorikeet' },
	]}
>
	<TabsPanel value="australian_magpie" p="200">
		<Paragraph>
			Intelligent, vocal, territorial, striking black-and-white bird
		</Paragraph>
	</TabsPanel>

	<TabsPanel value="galah" p="200">
		<Paragraph>
			Pink and grey parrot with playful behavior and distinctive crest
		</Paragraph>
	</TabsPanel>

	<TabsPanel value="rainbow_lorikeet" p="200">
		<Paragraph>
			Colorful parrot with vibrant plumage and a playful, energetic nature
		</Paragraph>
	</TabsPanel>
</Tabs>

The entire tab group can be disabled by setting isDisabled on the Tabs component:

Intelligent, vocal, territorial, striking black-and-white bird

<Tabs
	tabs={[
		{ value: 'australian_magpie', text: 'Australian magpie' },
		{ value: 'galah', text: 'Galah' },
		{ value: 'rainbow_lorikeet', text: 'Rainbow lorikeet' },
	]}
	isDisabled={true}
>
	<TabsPanel value="australian_magpie" p="200">
		<Paragraph>
			Intelligent, vocal, territorial, striking black-and-white bird
		</Paragraph>
	</TabsPanel>

	<TabsPanel value="galah" p="200">
		<Paragraph>
			Pink and grey parrot with playful behavior and distinctive crest
		</Paragraph>
	</TabsPanel>

	<TabsPanel value="rainbow_lorikeet" p="200">
		<Paragraph>
			Colorful parrot with vibrant plumage and a playful, energetic nature
		</Paragraph>
	</TabsPanel>
</Tabs>

Panel variant

The tabs component accepts a variant prop that can be used to change the style of the tabs. The default value is default, while panel is available as an alternative.

The panel variant is meant to be used when the tabs are rendered on top of a panel component. Additionally, enable the withTabs prop on the Panel itself to apply a negative top margin, to make sure the tabs are visually "connected" to the panel.

Intelligent, vocal, territorial, striking black-and-white bird

<Tabs
	tabs={[
		{ value: 'australian_magpie', text: 'Australian magpie' },
		{ value: 'galah', text: 'Galah' },
		{ value: 'rainbow_lorikeet', text: 'Rainbow lorikeet' },
	]}
	variant="panel"
>
	<Panel withTabs={true}>
		<TabsPanel value="australian_magpie">
			<Paragraph>
				Intelligent, vocal, territorial, striking black-and-white bird
			</Paragraph>
		</TabsPanel>

		<TabsPanel value="galah">
			<Paragraph>
				Pink and grey parrot with playful behavior and distinctive crest
			</Paragraph>
		</TabsPanel>

		<TabsPanel value="rainbow_lorikeet">
			<Paragraph>
				Colorful parrot with vibrant plumage and a playful, energetic nature
			</Paragraph>
		</TabsPanel>
	</Panel>
</Tabs>

The "panel" variant tabs also support icons and badges:

Campaigns content

<Tabs
	tabs={[
		{ 
			value: 'campaigns', 
			text: 'Campaigns',
			icon: 'campaigns',
			badge: '123',
		},
		{ 
			value: 'newsletters', 
			text: 'Newsletters',
			icon: 'newsletter',
			badge: '5',
		},
	]}
	variant="panel"
>
	<Panel withTabs={true}>
		<TabsPanel value="campaigns">
			<Paragraph>
				Campaigns content
			</Paragraph>
		</TabsPanel>

		<TabsPanel value="newsletters">
			<Paragraph>
				Newsletters content
			</Paragraph>
		</TabsPanel>
	</Panel>
</Tabs>

Placing the tabs at a different location

By default, the tabs are rendered at the top of the panel. The tabs can by rending the <TabsList> component at a different location within the component tree.

something above the tabs
something below the tabs

Intelligent, vocal, territorial, striking black-and-white bird

import { Tabs, TabsPanel, Paragraph, TabsList } from '@customerio/pluma-components/react';
import { useState } from 'react';

export default function Example() {
	const [activeTab, setActiveTab] = useState('australian_magpie');

	return (
		<Tabs
			activeTab={activeTab}
			onChange={setActiveTab}
		>
			<div>something above the tabs</div>
			<TabsList>
				<TabsTab value="australian_magpie">
					Australian magpie
				</TabsTab>
				<TabsTab value="galah">
					Galah
				</TabsTab>
				<TabsTab value="rainbow_lorikeet">
					Rainbow lorikeet
				</TabsTab>
			</TabsList>
			 <div>something below the tabs</div>

			<TabsPanel value="australian_magpie" p="200">
				<Paragraph>
					Intelligent, vocal, territorial, striking black-and-white bird
				</Paragraph>
			</TabsPanel>

			<TabsPanel value="galah" p="200">
				<Paragraph>
					Pink and grey parrot with playful behavior and distinctive crest
				</Paragraph>
			</TabsPanel>

			<TabsPanel value="rainbow_lorikeet" p="200">
				<Paragraph>
					Colorful parrot with vibrant plumage and a playful, energetic nature
				</Paragraph>
			</TabsPanel>
		</Tabs>
	);
}

Customizing tabs

Tabs can be customized by using the PlumaTabsList and PlumaTabsTab components. When using these components, a tabs array should not be used, and activeTab along with onChange will need to be provided to control the currently active tab.

Tab 1 content

import { Tabs, TabsPanel, Paragraph, Box, Tooltip, Icon } from '@customerio/pluma-components/react';
import { useState } from 'react';

export default function Example() {
	const [activeTab, setActiveTab] = useState('tab_1');

	return (
		<Tabs
			activeTab={activeTab}
			onChange={setActiveTab}
		>
			<TabsList>
				<TabsTab as="div" value="tab_1">
					<Box display="flex" alignItems="center" gap="100" flexGrow="1">
						Custom tab 1
						<Tooltip content="I am the tooltip content" placement="top">
							<Icon name="help" />
						</Tooltip>
					</Box>
				</TabsTab>

				<TabsTab as="div" value="tab_2">
					<Box display="flex" alignItems="center" gap="100" flexGrow="1">
						Custom tab 2

						<Icon name="star" />
					</Box>
				</TabsTab>

				<TabsTab as="div" value="tab_3">
					Custom tab 3
				</TabsTab>
			</TabsList>

			<TabsPanel value="tab_1" p="200">
				<Paragraph>
					Tab 1 content
				</Paragraph>
			</TabsPanel>

			<TabsPanel value="tab_2" p="200">
				<Paragraph>
					Tab 2 content
				</Paragraph>
			</TabsPanel>

			<TabsPanel value="tab_3" p="200">
				<Paragraph>
					Tab 3 content
				</Paragraph>
			</TabsPanel>
		</Tabs>
	);
}

API

PlumaTabs extends Box

The currently active tab. If none is provided, the component will default to the first tab from the tabs prop. Use this prop along with onChange if you want to have full control over the active tab state.

Default:false

Whether the tab list should render without a border.

Whether all tabs should be disabled.

Default:true

Disable keyboard navigation via arrows and space/enter, which is enabled by default, and recommended by the Tabs pattern. Use this flag when the tabs are links (<a> tags), as links come with their own accessibility semantics already.

Array of tab items to display.

The alignInline argument passed through to the TabsList component. Controls alignment of the tabs in the inline axis.

Additional classes to apply to any of the tabs (each array item corresponding to the tabs array).

What style of tab to render.

Text content to show in a badge inside the tab.

An icon to show in the tab.

Whether this tab is currently active/selected.

Whether this tab is disabled.

The text content to show in the tab.

A unique value for the tab, used for identifying the currently active tab.

Array of tab items to display.

Additional classes to apply to any of the tabs (each array item corresponding to the tabs array).

Text content to show in a badge inside the tab.

An icon to show in the tab.

Whether this tab is currently active/selected.

Whether this tab is disabled.

A unique value for the tab, used for identifying the currently active tab.

Which tab this panel corresponds to.