Overview
Displays the tab list of a tabbed interface:
KTabsList
is meant to be used together with
KTabsPanel
, which displays tabs' content. Using these two
components is recommended in situations when KTabs
is not
sufficient, for example, when a tab list is rendered within a different component than tab
panels.
Basic usage
Tab list items are rendered as buttons. Tab panels' content is passed via
KTabsPanel
slots named by corresponding tabs' IDs from
objects of the tabs
array. The component takes care of displaying only content
corresponding to the active tab.
Each tabbed interface needs to have ariaLabel
or
ariaLabelledBy
and also an identifier, tabsID
, that is unique in
regard to a page where tabs are rendered. Another purpose of tabsId
is to link
KTabsList
and KTabsPanel
representing a single
tabbed interface. These two components also need to share information about the currently
active tab stored in activeTabId
.
<AppBar>
<KTabsList
v-model="activeTabId"
tabsId="coachReportsTabs"
ariaLabel="Coach reports"
:tabs="tabs"
/>
</AppBar>
<KTabsPanel
tabsId="coachReportsTabs"
:activeTabId="activeTabId"
>
<template #tabLessons> Lessons tab content </template>
<template #tabLearners> Learners tab content </template>
<template #tabGroups> Groups tab content </template>
</KTabsPanel>
data() {
return {
activeTabId: 'tabLessons',
tabs: [
{ id: 'tabLessons', label: 'Lessons' },
{ id: 'tabLearners', label: 'Learners' },
{ id: 'tabGroups', label: 'Groups' },
],
};
},
With router
When implementing tabs with the router, it's the router view rather than
KTabsPanel
that is responsible for displaying the active tab
content.
In such a case, define to
property with a router link object as its value in
objects of the tabs
array:
data() {
return {
tabs: [
{ id: 'tabLessons', label: 'Lessons', to: { path: '/lessons' } },
{ id: 'tabLearners', label: 'Learners', to: { path: '/learners' } },
{ id: 'tabGroups', label: 'Groups', to: { path: '/groups' } },
],
};
},
Then, tabs will be rendered as router links and you can use the router view to display the active tab content:
<AppBar>
<KTabsList
v-model="activeTabId"
tabsId="coachReportsTabs"
ariaLabel="Coach reports"
:tabs="tabs"
/>
</AppBar>
<KTabsPanel
tabsId="coachReportsTabs"
:activeTabId="activeTabId"
>
<router-view />
</KTabsPanel>
Note that here, tabs content is not passed to KTabsPanel
via
named slots, for it's the router view that's responsible for rendering it.
However, it is still required to wrap the active tab content in
KTabsPanel
. Otherwise, even though tabs may seem to function
correctly at first glance, accessibility would be broken.
<AppBar>
<KTabsList
v-model="activeTabId"
tabsId="coachReportsTabs"
ariaLabel="Coach reports"
:tabs="tabs"
/>
</AppBar>
<KTabsPanel
tabsId="coachReportsTabs"
:activeTabId="activeTabId"
>
<!-- the active tab content is displayed in this router view -->
<router-view />
</KTabsPanel>
Place the router view to KTabsPanel
default slot
<AppBar>
<KTabsList
v-model="activeTabId"
tabsId="coachReportsTabs"
ariaLabel="Coach reports"
:tabs="tabs"
/>
</AppBar>
<KTabsPanel
tabsId="coachReportsTabs"
:activeTabId="activeTabId"
/>
<!-- the active tab content is displayed in this router view -->
<router-view />
Place the router view outside of KTabsPanel
or forget to
use KTabsPanel
altogether
More tabs on a page
When there are two or more tabbed interfaces on one page, it is important to identify each one of them with an ID unique in regard to the page. Otherwise, some a11y features may break.
This is achieved by providing a unique value to tabsId
property:
<KTabsList tabsId="firstTabs" />
<KTabsPanel tabsId="firstTabs" />
<KTabsList tabsId="secondTabs" />
<KTabsPanel tabsId="secondTabs" />
Appearance
There are several ways to adjust tabs styling.
Using props is the most straightforward:
<KTabsList
v-model="activeTabId"
tabsId="tabsProps"
ariaLabel="Coach reports"
:tabs="tabs"
:color="$themeTokens.textInverted"
:colorActive="$themeTokens.textInverted"
:backgroundColor="$themeTokens.primary"
:hoverBackgroundColor="$themeTokens.primaryDark"
/>
When that's not sufficient, appearanceOverrides
and
appearanceOverridesActive
can be used, where the former complements or
overrides styles common to all tabs and the latter contains styles specific to an active
tab:
<KTabsList
v-model="activeTabId"
tabsId="tabsAppearanceOverrides"
ariaLabel="Coach reports"
:tabs="tabs"
:appearanceOverrides="{
':hover': {
color: $themeTokens.primary,
},
textTransform: 'none',
margin: '0 32px',
}"
:appearanceOverridesActive="{
borderBottomWidth: '6px',
}"
/>
Lastly, the tab
slot can be used to adjust labels, for example to add icons.
It's a scoped slot that exposes tab
object and isActive
boolean
value:
<KTabsList
v-model="activeTabId"
tabsId="tabsSlot"
ariaLabel="Coach reports"
:tabs="tabs"
>
<template #tab="{ tab, isActive }">
<KLabeledIcon
:icon="icons[tab.id]"
:label="tab.label"
:color="isActive ? $themeTokens.primary : $themeTokens.annotation"
/>
</template>
</KTabsList>
icons: {
tabLessons: 'lesson',
tabLearners: 'person',
tabGroups: 'people',
},
Related
- Tabs page has an overview and usage guidance for all tab-related components
KTabsPanel
is a component to be used together withKTabsList
KTabs
is an alternative way to implement tabs
Props
Name | Description | Type | Default | Required |
---|---|---|---|---|
tabs | An array of tab objects { id, label, to } where id and label
properties are required and to is optional.
When to is provided, tabs render as router links.
Otherwise, they render as buttons. | array | — | true |
ariaLabel | A label that describes the purpose of the set of tabs.
Providing either ariaLabel or ariaLabelledBy
is required. | string |
''
| — |
ariaLabelledBy | ID reference to a DOM element which provides a label
that describes the purpose of the set of tabs.
Providing either ariaLabel or ariaLabelledBy
is required. | string |
''
| — |
color | Tabs text color.
Defaults to $themeTokens.annotation . | string |
null
| — |
colorActive | Text color of an active tab.
Defaults to $themeTokens.primary . | string |
null
| — |
backgroundColor | Tabs background color.
Defaults to $themeTokens.surface . | string |
null
| — |
hoverBackgroundColor | Tabs hover background color.
Defaults to $themeBrand.primary.v_100 . | string |
null
| — |
appearanceOverrides | Tabs styles that complement or override default styles
or styles defined via props (will be sent to $computedClass ,
which means that styles that are accepted by $computedClass ,
e.g. pseudo-classes, are supported) | object |
null
| — |
appearanceOverridesActive | An active tab styles that complement or override default styles
or styles defined via props (will be sent to $computedClass ,
which means that styles that are accepted by $computedClass ,
e.g. pseudo-classes, are supported) | object |
null
| — |
enablePrint | Tab list items are hidden when printing by default.
enablePrint set to true makes them visible in print mode. | boolean |
false
| — |
tabsId | An ID of a tabbed interface that this component is part of.
Needs to be be unique in regards to all tabbed interfaces
rendered on one page. | string | — | true |
v-model | An ID of an active tab. | string | — | true |
Events
Name | Description |
---|---|
error | Emitted with an error when a misconfiguration error occurs, if a listener is attached |
activate | Emitted when a tab is activated. Its payload is the active tab ID. |
click | Emitted when a tab is clicked. Its payload is the active tab ID.
When compared to the activate event, click is emitted only when
a user is interacting with tabs, whereas activate can be emitted
programatically in addition to user interaction. |
Slots
Name | Description |
---|---|
tab | Optional slot for tab labels. Exposes tab object and isActive boolean. |
Methods
Name | Description |
---|---|
focusActiveTab | Puts focus on the active tab |