group | package | title | order | slug | category | description | componentPrefix | props | import | source | docs | styles | |||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
mantine-core |
@mantine/core |
Tabs |
1 |
/core/tabs/ |
navigation |
Switch between different views |
Tabs |
|
import { Tabs } from '@mantine/core'; |
mantine-core/src/Tabs/Tabs.tsx |
core/Tabs.mdx |
|
import { TabsDemos } from '@mantine/demos';
To control Tabs state provide value
and onTabChange
props:
import { useState } from 'react';
import { Tabs } from '@mantine/core';
function Demo() {
const [activeTab, setActiveTab] = useState<string | null>('first');
return (
<Tabs value={activeTab} onTabChange={setActiveTab}>
<Tabs.List>
<Tabs.Tab value="first">First tab</Tabs.Tab>
<Tabs.Tab value="second">Second tab</Tabs.Tab>
</Tabs.List>
<Tabs.Panel value="first">First panel</Tabs.Panel>
<Tabs.Panel value="second">Second panel</Tabs.Panel>
</Tabs>
);
}
If you do need to subscribe to Tabs state changes use defaultValue
:
import { Tabs } from '@mantine/core';
function Demo() {
return (
<Tabs defaultValue="first">
<Tabs.List>
<Tabs.Tab value="first">First tab</Tabs.Tab>
<Tabs.Tab value="second">Second tab</Tabs.Tab>
</Tabs.List>
<Tabs.Panel value="first">First panel</Tabs.Panel>
<Tabs.Panel value="second">Second panel</Tabs.Panel>
</Tabs>
);
}
You can use any React node as icon
and rightSection
in Tabs.Tab
component:
<Demo data={TabsDemos.icons} demoProps={{ toggle: true }} />
<Demo data={TabsDemos.rightSection} demoProps={{ toggle: true }} />
To change colors of all tabs set color
on Tabs
component, to change color of the individual tab set color
on Tabs.Tab
.
color
should be a key of theme.colors
:
To display tab on the opposite side, set margin-left to auto with ml="auto"
prop:
To make tabs inverted, place Tabs.Panel
components before Tabs.List
and add inverted
prop to Tabs
component:
Set disabled
prop on Tabs.Tab
component to disable tab.
Disabled tab cannot be activated with mouse or keyboard, will be skipped when user navigates with arrow keys:
By default, tabs are activated when user presses arrows and Home/End keys.
To disable that set activateTabWithKeyboard={false}
on Tabs
component,
then user will be able to deactivate active tab by clicking on it:
<Demo data={TabsDemos.keyboardActivation} demoProps={{ toggle: true }} />
By default, active cannot be deactivated. To allow that set allowTabDeactivation
on Tabs
component:
<Demo data={TabsDemos.deactivate} demoProps={{ toggle: true }} />
By default, inactive Tabs.Panel
will stay mounted, to unmount inactive tabs, set keepMounted={false}
on Tabs.
This is useful when you want to render components that impact performance inside Tabs.Panel
. Note that
components that are rendered inside Tabs.Panel
will reset their state on each mount (tab change).
import { Tabs } from '@mantine/core';
// Second tab panel will be mounted only when user activates second tab
function Demo() {
return (
<Tabs keepMounted={false} defaultValue="first">
<Tabs.List>
<Tabs.Tab value="first">First tab</Tabs.Tab>
<Tabs.Tab value="second">Second tab</Tabs.Tab>
</Tabs.List>
<Tabs.Panel value="first">First panel</Tabs.Panel>
<Tabs.Panel value="second">Second panel</Tabs.Panel>
</Tabs>
);
}
Set unstyled
prop on Tabs component to remove all non-essential library styles.
<Demo data={TabsDemos.unstyled} demoProps={{ toggle: true }} />
By doing so, you will be able to keep component behavior while providing your own styles with Styles API:
<Demo data={TabsDemos.stylesApi} demoProps={{ toggle: true }} />
import { useRef } from 'react';
import { Tabs } from '@mantine/core';
function Demo() {
const secondTabRef = useRef<HTMLButtonElement>(null);
return (
<Tabs defaultValue="first">
<Tabs.List>
<Tabs.Tab value="first">First tab</Tabs.Tab>
<Tabs.Tab value="Second" ref={secondTabRef}>
Second tab
</Tabs.Tab>
<Tabs.Tab value="third">Third tab</Tabs.Tab>
</Tabs.List>
</Tabs>
);
}
<Route path="/tabs/:tabValue" element={<Demo />} />
import { useNavigate, useParams } from 'react-router-dom';
import { Tabs } from '@mantine/core';
function Demo() {
const navigate = useNavigate();
const { tabValue } = useParams();
return (
<Tabs value={tabValue} onTabChange={(value) => navigate(`/tabs/${value}`)}>
<Tabs.List>
<Tabs.Tab value="first">First tab</Tabs.Tab>
<Tabs.Tab value="second">Second tab</Tabs.Tab>
</Tabs.List>
</Tabs>
);
}
// For file /tabs/[activeTab].tsx
import { useRouter } from 'next/router';
import { Tabs } from '@mantine/core';
function Demo() {
const router = useRouter();
return (
<Tabs
value={router.query.activeTab as string}
onTabChange={(value) => router.push(`/tabs/${value}`)}
>
<Tabs.List>
<Tabs.Tab value="first">First tab</Tabs.Tab>
<Tabs.Tab value="second">Second tab</Tabs.Tab>
</Tabs.List>
</Tabs>
);
}
Tabs component follows WAI-ARIA recommendations on accessibility.
If you use Tabs.Tab
without text content, for example, only with icon, then set aria-label
:
import { Tabs } from '@mantine/core';
import { IconCoin } from '@tabler/icon';
function Demo() {
return (
<Tabs defaultValue="chat">
<Tabs.List>
{/* aria-label is not required, tab is labelled by children */}
<Tabs.Tab value="chat">Chat</Tabs.Tab>
{/* aria-label is required, tab is not labelled by children */}
<Tabs.Tab icon={<IconCoin size={14} />} value="money" aria-label="Get money" />
</Tabs.List>
</Tabs>
);
}
To set tabs list label, set aria-label
on Tabs.List
component, it will be announced by screen reader:
import { Tabs } from '@mantine/core';
function Demo() {
return (
<Tabs defaultValue="recent">
{/* Tabs.List aria-label will be announced when tab is focused for the first time */}
<Tabs.List aria-label="Chats">
<Tabs.Tab value="recent">Most recent</Tabs.Tab>
<Tabs.Tab value="recent">Unanswered</Tabs.Tab>
<Tabs.Tab value="archived">Archived</Tabs.Tab>
</Tabs.List>
</Tabs>
);
}
<KeyboardEventsTable data={[ { key: 'ArrowRight', description: 'Focuses and activates next tab that is not disabled', condition: 'orientation="horizontal"', }, { key: 'ArrowLeft', description: 'Focuses and activates previous tab that is not disabled', condition: 'orientation="horizontal"', }, { key: 'ArrowDown', description: 'Focuses and activates next tab that is not disabled', condition: 'orientation="vertical"', }, { key: 'ArrowUp', description: 'Focuses and activates previous tab that is not disabled', condition: 'orientation="vertical"', }, { key: 'Home', description: 'Focuses and activates first tab' }, { key: 'End', description: 'Focuses and activates last tab' }, ]} />