TabPanel
Tabs are used to navigate among groups of content that are related and at the same level of hierarchy. For example, tabs can display driving directions “from north”, “from east”, “from south” and “from west”. They contain a minimum of two tabs and one tab is active at a time.
A TabPanel is effective in shortening pages by reducing scrolling. Users decide if they want to read the content by clicking through tabs or deferring it for later. For this reason, it is ideal for details that are not critical to the user for general understanding of the content.
Keep in mind that even though a TabPanel shortens a page and reduces scrolling, it increases the interaction cost by requiring users to decide if the tab might contain information they are looking for.
#
Example<div class="bux-tabpanel">
<div class="bux-tabpanel__tabs--scrollable">
<button aria-hidden="true" aria-label="scroll left" tabindex="-1" type="button" class="bux-tabpanel__overflow-nav-button bux-tabpanel__overflow-nav-button--left">
<i class="icon icon-chevron-left"></i>
</button>
<ul class="bux-tabpanel__tabs" role="tablist" aria-label="An accessible tabpanel example">
<li class="bux-tabpanel__button" role="presentation">
<button id="bux-tabpanel__tab--1" class="bux-tabpanel__tab" role="tab" aria-selected="true" aria-controls="bux-tabpanel__panel--1">
Tab one
</button>
</li>
<li class="bux-tabpanel__button" role="presentation">
<button id="bux-tabpanel__tab--2" class="bux-tabpanel__tab" role="tab" aria-selected="false" aria-controls="bux-tabpanel__panel--2" tabindex="-1">
Tab two
</button>
</li>
<li class="bux-tabpanel__button" role="presentation">
<button id="bux-tabpanel__tab--3" class="bux-tabpanel__tab" role="tab" aria-selected="false" aria-controls="bux-tabpanel__panel--3" tabindex="-1">
Tab three has longer text
</button>
</li>
<li class="bux-tabpanel__button" role="presentation">
<button id="bux-tabpanel__tab--4" class="bux-tabpanel__tab" role="tab" aria-selected="false" aria-controls="bux-tabpanel__panel--4" tabindex="-1">
Tab four
</button>
</li>
</ul>
<button aria-hidden="true" aria-label="scroll right" tabindex="-1" type="button" class="bux-tabpanel__overflow-nav-button bux-tabpanel__overflow-nav-button--right">
<i class="icon icon-chevron-right"></i>
</button>
</div>
<div id="bux-tabpanel__panel--1" class="bux-tabpanel__panel" role="tabpanel" aria-labelledby="bux-tabpanel__tab--1" tabindex="0">
...
</div>
<div id="bux-tabpanel__panel--2" class="bux-tabpanel__panel" role="tabpanel" aria-labelledby="bux-tabpanel__tab--2" tabindex="0" hidden="hidden">
...
</div>
<div id="bux-tabpanel__panel--3" class="bux-tabpanel__panel" role="tabpanel" aria-labelledby="bux-tabpanel__tab--3" tabindex="0" hidden="hidden">
...
</div>
<div id="bux-tabpanel__panel--4" class="bux-tabpanel__panel" role="tabpanel" aria-labelledby="bux-tabpanel__tab--4" tabindex="0" hidden="hidden">
...
</div>
</div>
{% set panels = '' %}
<div class="bux-tabpanel">
<div class="bux-tabpanel__tabs--scrollable">
<button aria-hidden="true" aria-label="scroll left" tabindex="-1" type="button" class="bux-tabpanel__overflow-nav-button bux-tabpanel__overflow-nav-button--left">
<i class="icon icon-chevron-left"></i>
</button>
<ul class="bux-tabpanel__tabs" role="tablist" aria-label="{{ title }}">
{% for item in items %}
{% set isTabSelected = (loop.first) ? true : false %}
{% set tabTabIndex = (isTabSelected) ? '' : 'tabindex="-1"' %}
{% set tabId = 'bux-tabpanel__tab--' ~ item.id %}
{% set panel = '' %}
{% set panelId = 'bux-tabpanel__panel--' ~ item.id %}
{% set panelVisibility = (isTabSelected) ? '' : 'hidden="hidden"' %}
<li class="bux-tabpanel__button" role="presentation">
<button id="{{ tabId }}" class="bux-tabpanel__tab" role="tab" aria-selected="{{ isTabSelected }}" aria-controls="{{ panelId }}" {{ tabTabIndex }}>
{{ item.title }}
</button>
</li>
{% set panel %}
<div id="{{ panelId }}" class="bux-tabpanel__panel" role="tabpanel" aria-labelledby="{{ tabId }}" tabindex="0" {{panelVisibility}}>
{{ item.content }}
</div>
{% endset %}
{% set panels = panels ~ panel %}
{% endfor %}
</ul>
<button aria-hidden="true" aria-label="scroll right" tabindex="-1" type="button" class="bux-tabpanel__overflow-nav-button bux-tabpanel__overflow-nav-button--right">
<i class="icon icon-chevron-right"></i>
</button>
</div>
{{ panels }}
</div>
#
Usage#
Dos- Use when there are several pieces of content related to a single topic, but the user only needs to read some of them (i.e. driving directions from different locations)
- Use content that is closely related and at the same level of hierarchy
- Consider an TabPanel as a complementary component to the main content (likely above it)
- Write clear and concise tab labels
- Use a minimum of two tabs. In most scenarios, use two to six tabs
#
Don’ts- Don’t use for critical information in a TabPanel that might be overlooked by the user
- Don’t use to reduce page scrolling; rely on nested Headings or Accordions
- Don’t use as to navigate to different areas; rely on Menus
- Don’t use for comparing content; use a Table, Accordion or different component
#
Implementation notesEach tab and panel pair must be associated with each other by the following properties:
#
Tabid="TAB_ID"
— a unique identifier for the tab elementrole="tab"
— tells assistive technologies that this element behaves like a tabaria-controls="PANEL_ID"
— tells assistive technologies that this element controls another elementaria-selected="true|false"
— tells assistive technologies that this element has been activated or nottabindex="-1"
— removes non-active tabs from tab order so next tab goes to the active panel
#
Panelid="PANEL_ID"
— a unique identifier for the panel elementrole="tabpanel"
— tells assistive technologies that this element behaves like a tabpanelaria-labelledby="TAB_ID"
— tells assistive technologies that this element is labeled by another elementtabindex="0"
— places the panels into the tab orderhidden
— hides all non-active panels
Each tab and panel must have an unique ID. If you are using multiple tabpanels on the same page you'll want to add a unique identifier to each tab and panel.
#
Delay attributeThere is an optional attribute that you can add to the main <div>
element.
data-delay
— By adding a delay to the tabpanel each key stroke within the tablist will be delayed 300ms
<div class="bux-tabpanel" data-delay></div>
#
Accessibility#
Keyboard supportKey | Function |
---|---|
Tab |
|
Right Arrow |
|
Left Arrow |
|
Home | Moves focus to the first tab and activates it. |
End | Moves focus to the last tab and activates it. |