React Tabs Components
Tabs
The CoreUI React Tabs component provides a flexible and accessible way to create tabbed navigation in your application. It supports various styles and configurations to meet different design requirements.
Example#
The basic React tabs example uses the variant="tabs"
props to generate a tabbed interface.
<CTabs activeItemKey="profile"> <CTabList variant="tabs"> <CTab itemKey="home">Home</CTab> <CTab itemKey="profile">Profile</CTab> <CTab itemKey="contact">Contact</CTab> <CTab disabled itemKey="disabled">Disabled</CTab> </CTabList> <CTabContent> <CTabPanel className="p-3" itemKey="home"> Home tab content </CTabPanel> <CTabPanel className="p-3" itemKey="profile"> Profile tab content </CTabPanel> <CTabPanel className="p-3" itemKey="contact"> Contact tab content </CTabPanel> <CTabPanel className="p-3" itemKey="disabled"> Disabled tab content </CTabPanel> </CTabContent></CTabs>
Available styles#
Change the style of <CTabs>
's component with modifiers and utilities. Mix and match as needed, or build your own.
Unstyled#
If you don’t provide the variant
prop, the component will default to a basic style.
<CTabs activeItemKey="profile"> <CTabList> <CTab itemKey="home">Home</CTab> <CTab itemKey="profile">Profile</CTab> <CTab itemKey="contact">Contact</CTab> <CTab disabled itemKey="disabled">Disabled</CTab> </CTabList> <CTabContent> <CTabPanel className="p-3" itemKey="home"> Home tab content </CTabPanel> <CTabPanel className="p-3" itemKey="profile"> Profile tab content </CTabPanel> <CTabPanel className="p-3" itemKey="contact"> Contact tab content </CTabPanel> <CTabPanel className="p-3" itemKey="disabled"> Disabled tab content </CTabPanel> </CTabContent></CTabs>
Pills#
Take that same code, but use variant="pills"
instead:
<CTabs activeItemKey={2}> <CTabList variant="pills"> <CTab aria-controls="home-tab-pane" itemKey={1}>Home</CTab> <CTab aria-controls="profile-tab-pane" itemKey={2}>Profile</CTab> <CTab aria-controls="contact-tab-pane" itemKey={3}>Contact</CTab> <CTab aria-controls="disabled-tab-pane" disabled itemKey={4}>Disabled</CTab> </CTabList> <CTabContent> <CTabPanel className="p-3" aria-labelledby="home-tab-pane" itemKey={1}> Home tab content </CTabPanel> <CTabPanel className="p-3" aria-labelledby="profile-tab-pane" itemKey={2}> Profile tab content </CTabPanel> <CTabPanel className="p-3" aria-labelledby="contact-tab-pane" itemKey={3}> Contact tab content </CTabPanel> <CTabPanel className="p-3" aria-labelledby="disabled-tab-pane" itemKey={4}> Disabled tab content </CTabPanel> </CTabContent></CTabs>
Underline#
Take that same code, but use variant="underline"
instead:
<CTabs activeItemKey={2}> <CTabList variant="underline"> <CTab aria-controls="home-tab-pane" itemKey={1}>Home</CTab> <CTab aria-controls="profile-tab-pane" itemKey={2}>Profile</CTab> <CTab aria-controls="contact-tab-pane" itemKey={3}>Contact</CTab> <CTab aria-controls="disabled-tab-pane" disabled itemKey={4}>Disabled</CTab> </CTabList> <CTabContent> <CTabPanel className="py-3" aria-labelledby="home-tab-pane" itemKey={1}> Home tab content </CTabPanel> <CTabPanel className="py-3" aria-labelledby="profile-tab-pane" itemKey={2}> Profile tab content </CTabPanel> <CTabPanel className="py-3" aria-labelledby="contact-tab-pane" itemKey={3}> Contact tab content </CTabPanel> <CTabPanel className="py-3" aria-labelledby="disabled-tab-pane" itemKey={4}> Disabled tab content </CTabPanel> </CTabContent></CTabs>
Underline border#
Take that same code, but use variant="underline-border"
instead:
<CTabs activeItemKey={2}> <CTabList variant="underline-border"> <CTab aria-controls="home-tab-pane" itemKey={1}>Home</CTab> <CTab aria-controls="profile-tab-pane" itemKey={2}>Profile</CTab> <CTab aria-controls="contact-tab-pane" itemKey={3}>Contact</CTab> <CTab aria-controls="disabled-tab-pane" disabled itemKey={4}>Disabled</CTab> </CTabList> <CTabContent> <CTabPanel className="py-3" aria-labelledby="home-tab-pane" itemKey={1}> Home tab content </CTabPanel> <CTabPanel className="py-3" aria-labelledby="profile-tab-pane" itemKey={2}> Profile tab content </CTabPanel> <CTabPanel className="py-3" aria-labelledby="contact-tab-pane" itemKey={3}> Contact tab content </CTabPanel> <CTabPanel className="py-3" aria-labelledby="disabled-tab-pane" itemKey={4}> Disabled tab content </CTabPanel> </CTabContent></CTabs>
Fill and justify#
Force your <CTabs>
's contents to extend the full available width one of two modifier classes. To proportionately fill all available space use layout="fill"
. Notice that all horizontal space is occupied, but not every nav item has the same width.
<CTabs activeItemKey={2}> <CTabList variant="tabs" layout="fill"> <CTab aria-controls="home-tab-pane" itemKey={1}>Home</CTab> <CTab aria-controls="profile-tab-pane" itemKey={2}>Profile tab with longer content</CTab> <CTab aria-controls="contact-tab-pane" itemKey={3}>Contact</CTab> <CTab aria-controls="disabled-tab-pane" disabled itemKey={4}>Disabled</CTab> </CTabList> <CTabContent> <CTabPanel className="py-3" aria-labelledby="home-tab-pane" itemKey={1}> Home tab content </CTabPanel> <CTabPanel className="py-3" aria-labelledby="profile-tab-pane" itemKey={2}> Profile tab content </CTabPanel> <CTabPanel className="py-3" aria-labelledby="contact-tab-pane" itemKey={3}> Contact tab content </CTabPanel> <CTabPanel className="py-3" aria-labelledby="disabled-tab-pane" itemKey={4}> Disabled tab content </CTabPanel> </CTabContent></CTabs>
For equal-width elements, use layout="justified"
. All horizontal space will be occupied by nav links, but unlike the layout="fill"
above, every nav item will be the same width.
<CTabs activeItemKey={2}> <CTabList variant="tabs" layout="justified"> <CTab aria-controls="home-tab-pane" itemKey={1}>Home</CTab> <CTab aria-controls="profile-tab-pane" itemKey={2}>Profile</CTab> <CTab aria-controls="contact-tab-pane" itemKey={3}>Contact</CTab> <CTab aria-controls="disabled-tab-pane" disabled itemKey={4}>Disabled</CTab> </CTabList> <CTabContent> <CTabPanel className="py-3" aria-labelledby="home-tab-pane" itemKey={1}> Home tab content </CTabPanel> <CTabPanel className="py-3" aria-labelledby="profile-tab-pane" itemKey={2}> Profile tab content </CTabPanel> <CTabPanel className="py-3" aria-labelledby="contact-tab-pane" itemKey={3}> Contact tab content </CTabPanel> <CTabPanel className="py-3" aria-labelledby="disabled-tab-pane" itemKey={4}> Disabled tab content </CTabPanel> </CTabContent></CTabs>
Accessibility#
Dynamic tabbed interfaces, as described in the WAI ARIA Authoring Practices, require role="tablist"
, role="tab"
, role="tabpanel"
, and additional aria-
attributes in order to convey their structure, functionality and current state to users of assistive technologies (such as screen readers).
WAI-ARIA Roles#
- The element that serves as the container for the set of tabs has the role
tablist
. - Each element that serves as a tab has the role
tab
and is contained within the element with the roletablist
. - Each element that contains the content panel for a tab has the role
tabpanel
. - If the tab list has a visible label, the element with the role
tablist
hasaria-labelledby
set to a value that refers to the labeling element. Otherwise, thetablist
element has a label provided byaria-label
. - Each element with the role
tab
has the propertyaria-controls
referring to its associatedtabpanel
element. - The active tab element has the state
aria-selected
set totrue
, and all other tab elements have it set tofalse
. - Each element with the role
tabpanel
has the propertyaria-labelledby
referring to its associatedtab
element.
Our React Tabs component automatically manages all role="..."
and aria-
attributes for accessibility. It also handles the selected state by adding aria-selected="true"
to the active tab. Additionally, you have the flexibility to manually set these attributes, as shown in the example below:
<CTabs activeItemKey={2}> <CTabList variant="tabs"> <CTab id="home-tab" aria-controls="home-tab-pane" itemKey={1}>Home</CTab> <CTab id="profile-tab" aria-controls="profile-tab-pane" itemKey={2}>Profile</CTab> <CTab id="contact-tab" aria-controls="contact-tab-pane" itemKey={3}>Contact</CTab> <CTab id="disabled-tab" aria-controls="disabled-tab-pane" disabled itemKey={4}>Disabled</CTab> </CTabList> <CTabContent> <CTabPanel id="home-tab-pane" className="p-3" aria-labelledby="home-tab-pane" aria-labelledby="home-tab" itemKey={1}> Home tab content </CTabPanel> <CTabPanel id="profile-tab-pane" className="p-3" aria-labelledby="profile-tab-pane" aria-labelledby="profile-tab" itemKey={2}> Profile tab content </CTabPanel> <CTabPanel id="contact-tab-pane" className="p-3" aria-labelledby="contact-tab-pane" aria-labelledby="contact-tab" itemKey={3}> Contact tab content </CTabPanel> <CTabPanel id="disabled-tab-pane" className="p-3" aria-labelledby="disabled-tab-pane" aria-labelledby="disabled-tab" itemKey={4}> Disabled tab content </CTabPanel> </CTabContent></CTabs>
This example demonstrates how to manually set aria-selected
, aria-controls
, and aria-labelledby
attributes on your <CTab>
's and <CTabPanels>
's.
Keyboard Interaction#
When focus enters the tab list:
Tab: It places focus on the active tab
element.
When focus is on a tab element:
Tab: Moves focus to the next element in the tab sequence, typically the tabpanel unless the first focusable element inside the tabpanel is found earlier.
Left Arrow: Moves focus to the previous tab. If on the first tab, it wraps around to the last tab.
Right Arrow: Moves focus to the next tab. If on the last tab, it wraps around to the first tab.
Home: Moves focus to the first tab.
End: Moves focus to the last tab.
Customizing#
CSS variables#
React tabs use local CSS variables on .nav
, .nav-tabs
, .nav-pills
, .nav-underline
and .nav-underline-border
for enhanced real-time customization. Values for the CSS variables are set via Sass, so Sass customization is still supported, too.
On the .nav
base class:
--cui-nav-link-padding-x: #{$nav-link-padding-x};--cui-nav-link-padding-y: #{$nav-link-padding-y};@include rfs($nav-link-font-size, --cui-nav-link-font-size);--cui-nav-link-font-weight: #{$nav-link-font-weight};--cui-nav-link-color: #{$nav-link-color};--cui-nav-link-hover-color: #{$nav-link-hover-color};--cui-nav-link-disabled-color: #{$nav-link-disabled-color};
On the .nav-tabs
modifier class:
--cui-nav-tabs-border-width: #{$nav-tabs-border-width};--cui-nav-tabs-border-color: #{$nav-tabs-border-color};--cui-nav-tabs-border-radius: #{$nav-tabs-border-radius};--cui-nav-tabs-link-hover-border-color: #{$nav-tabs-link-hover-border-color};--cui-nav-tabs-link-active-color: #{$nav-tabs-link-active-color};--cui-nav-tabs-link-active-bg: #{$nav-tabs-link-active-bg};--cui-nav-tabs-link-active-border-color: #{$nav-tabs-link-active-border-color};
On the .nav-pills
modifier class:
--cui-nav-pills-border-radius: #{$nav-pills-border-radius};--cui-nav-pills-link-active-color: #{$nav-pills-link-active-color};--cui-nav-pills-link-active-bg: #{$nav-pills-link-active-bg};
On the .nav-underline
modifier class:
--cui-nav-underline-gap: #{$nav-underline-gap};--cui-nav-underline-border-width: #{$nav-underline-border-width};--cui-nav-underline-link-active-color: #{$nav-underline-link-active-color};
On the .nav-underline-border
modifier class:
--cui-nav-underline-border-gap: #{$nav-underline-border-gap};--cui-nav-underline-border-border-color: #{$nav-underline-border-border-color};--cui-nav-underline-border-border-width: #{$nav-underline-border-border-width};--cui-nav-underline-border-link-padding-x: #{$nav-underline-border-link-padding-x};--cui-nav-underline-border-link-padding-y: #{$nav-underline-border-link-padding-y};--cui-nav-underline-border-link-color: #{$nav-underline-border-link-color};--cui-nav-underline-border-link-active-color: #{$nav-underline-border-link-active-color};--cui-nav-underline-border-link-disabled-color: #{$nav-underline-border-link-disabled-color};
How to use CSS variables#
const vars = { '--my-css-var': 10, '--my-another-css-var': "red" }return <CTabs style={vars}>...</CTabs>
SASS variables#
$nav-link-padding-y: .5rem !default;$nav-link-padding-x: 1rem !default;$nav-link-font-size: null !default;$nav-link-font-weight: null !default;$nav-link-color: var(--cui-link-color) !default;$nav-link-hover-color: var(--cui-link-hover-color) !default;$nav-link-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out !default;$nav-link-disabled-color: var(--cui-secondary-color) !default;$nav-link-focus-box-shadow: $focus-ring-box-shadow !default;
$nav-tabs-border-color: var(--cui-border-color) !default;$nav-tabs-border-width: var(--cui-border-width) !default;$nav-tabs-border-radius: var(--cui-border-radius) !default;$nav-tabs-link-hover-border-color: var(--cui-secondary-bg) var(--cui-secondary-bg) $nav-tabs-border-color !default;$nav-tabs-link-active-color: var(--cui-emphasis-color) !default;$nav-tabs-link-active-bg: var(--cui-body-bg) !default;$nav-tabs-link-active-border-color: var(--cui-border-color) var(--cui-border-color) $nav-tabs-link-active-bg !default;
$nav-pills-border-radius: var(--cui-border-radius) !default;$nav-pills-link-active-color: $component-active-color !default;$nav-pills-link-active-bg: $component-active-bg !default;
$nav-underline-gap: 1rem !default;$nav-underline-border-width: .125rem !default;$nav-underline-link-active-color: var(--cui-emphasis-color) !default;
$nav-underline-border-gap: .5rem !default;$nav-underline-border-border-color: var(--cui-border-color) !default;$nav-underline-border-border-width: .125rem !default;$nav-underline-border-link-padding-y: .5rem !default;$nav-underline-border-link-padding-x: .5rem !default;$nav-underline-border-link-color: var(--cui-secondary-color) !default;$nav-underline-border-link-active-color: var(--cui-primary) !default;$nav-underline-border-link-disabled-color: var(--cui-tertiary-color) !default;
API#
CTab#
import { CTab } from '@coreui/react'// orimport CTab from '@coreui/react/src/components/tabs/CTab'
Property | Description | Type | Default |
---|---|---|---|
className | A string of all className you want applied to the base component. | string | - |
itemKey | Item key. | string | number | - |
CTabContent#
import { CTabContent } from '@coreui/react'// orimport CTabContent from '@coreui/react/src/components/tabs/CTabContent'
Property | Description | Type | Default |
---|---|---|---|
className | A string of all className you want applied to the base component. | string | - |
CTabList#
import { CTabList } from '@coreui/react'// orimport CTabList from '@coreui/react/src/components/tabs/CTabList'
Property | Description | Type | Default |
---|---|---|---|
className | A string of all className you want applied to the base component. | string | - |
layout | Specify a layout type for component. | 'fill' | 'justified' | - |
variant | Set the nav variant to tabs or pills. | 'pills' | 'tabs' | 'underline' | 'underline-border' | - |
CTabPanel#
import { CTabPanel } from '@coreui/react'// orimport CTabPanel from '@coreui/react/src/components/tabs/CTabPanel'
Property | Description | Type | Default |
---|---|---|---|
className | A string of all className you want applied to the base component. | string | - |
itemKey | Item key. | string | number | - |
onHide | Callback fired when the component requests to be hidden. | () => void | - |
onShow | Callback fired when the component requests to be shown. | () => void | - |
transition | Enable fade in and fade out transition. | boolean | true |
visible | Toggle the visibility of component. | boolean | - |
CTabs#
import { CTabs } from '@coreui/react'// orimport CTabs from '@coreui/react/src/components/tabs/CTabs'
Property | Description | Type | Default |
---|---|---|---|
activeItemKey | The active item key. | string | number | - |
className | A string of all className you want applied to the base component. | string | - |
onChange | The callback is fired when the active tab changes. | (value: string | number) => void | - |