Tabs
Tabs help users understand and navigate groups of related content that are at the same level of hierarchy. There are two ways tabs are used to organize content. Either by navigating between pages or multiple tables on the same page.
Two variants: Line (default) and Enclosed
Use Line to navigate across pages
Use Enclosed to navigate multiple Tables
Tabs can have a supporting icon, badge or both. The height of all tabs is fixed to 36px. The width is variable depending on the length of the label. It is recommended to limit the label to two words.
Basic Usage
The <Tabs> and <Tab> components are used to render the tabs.
INFO
Dev Note: In order to maintain optimal accessibility, each tab's corresponding tab panel should have role="tabpanel" and id="tabpanel-my-tab-value" where my-tab-value matches the value prop on a <Tab> component; the TabPanel component will handle this for you.
<script setup lang="ts">
import { ref } from "vue";
import Tab from '@leaflink/stash/Tab';
import Tabs from '@leaflink/stash/Tabs';
import TabPanel from '@leaflink/stash/TabPanel';
const activeTab = ref("overview");
</script>
<template>
<Tabs v-model:active-tab="activeTab">
<Tab value="overview">Overview</Tab>
<Tab value="payment-and-transfers">Payment & Transfers</Tab>
<Tab value="transactions">Transactions</Tab>
</Tabs>
<TabPanel tab-value="overview" :active-tab="activeTab">
<Module>overview panel</Module>
</TabPanel>
<TabPanel tab-value="payment-and-transfers" :active-tab="activeTab">
<Module>payment-and-transfers panel</Module>
</TabPanel>
<TabPanel tab-value="transactions" :active-tab="activeTab">
<Module>transactions panel</Module>
</TabPanel>
</template>Tabs Playground
Tab Playground
Anatomy
- Icon
- Tab label
- Badge Slot
- Border
- Target / focus area
Vue Router's RouterLink
When the to prop is provided, <Tab> renders a RouterLink internally which allows vue-router to handle navigation.
Additionally, the routerLinkProps prop can be used to provide extra props to the RouterLink component internally.
<Tabs :active-tab="activeTab">
<Tab value="overview" to="overview">Overview</Tab>
<Tab value="payment-and-transfers" to="p-and-t">Payment & Transfers</Tab>
<Tab value="transactions" to="transactions">Transactions</Tab>
</Tabs>Hyperlinks and Server Navigation
When the href prop is provided, <Tab> renders an <a> internally which allows server-side navigation, such as with legacy Django pages in the Marketplace application.
Additionally, the anchorProps prop can be used to provide extra props to the <a> element internally.
<Tabs :active-tab="activeTab">
<Tab value="overview" href="overview">Overview</Tab>
<Tab value="payment-and-transfers" href="p-and-t">Payment & Transfers</Tab>
<Tab value="transactions" href="transactions">Transactions</Tab>
</Tabs>Badge
The Tab component can render an inline badge using the badge prop. The badge can be used to display extra information, such as the number of pending transactions:
<Tabs v-model:active-tab="activeTab">
<Tab value="overview">Overview</Tab>
<Tab value="payment-and-transfers">Payment & Transfers</Tab>
<Tab value="transactions" badge="19">Transactions</Tab>
</Tabs>Disabled
The Tab component can be disabled via the disabled prop
<Tabs v-model:active-tab="activeTab">
<Tab value="overview" disabled>Overview</Tab>
<Tab value="payment-and-transfers">Payment & Transfers</Tab>
<Tab value="transactions">Transactions</Tab>
<Tab value="documents" disabled badge="99">Documents</Tab>
</Tabs>Variants
The component has two variants:
- line (default)
- enclosed
The above examples show the "line" variant. Here is the "enclosed" variant:
<Tabs v-model:active-tab="activeTab" variant="enclosed">
<Tab value="overview">Overview</Tab>
<Tab value="payment-and-transfers">Payment & Transfers</Tab>
<Tab value="transactions">Transactions</Tab>
</Tabs>More Button
To use the More dropdown with menu items, you need to:
- Add
data-action-idto each<Tab>component - Add matching
data-action-idto each<MenuItem>in the#more-actionsslot - The
data-action-idmust match thevalueprop of the corresponding tab
The component will automatically handle tab switching and display a checkmark for the active tab in the dropdown menu.
<script setup lang="ts">
import { ref } from "vue";
import Tab from '@leaflink/stash/Tab';
import Tabs from '@leaflink/stash/Tabs';
import Menu from '@leaflink/stash/Menu';
import MenuItem from '@leaflink/stash/MenuItem';
import Badge from '@leaflink/stash/Badge';
const activeTab = ref("overview");
</script>
<template>
<Tabs v-model:active-tab="activeTab" variant="enclosed">
<Tab data-action-id="overview" value="overview">Overview</Tab>
<Tab data-action-id="transactions" value="transactions" badge="5">Transactions</Tab>
<Tab data-action-id="documents" value="documents">Documents</Tab>
<Tab data-action-id="accounts" value="accounts" disabled>Accounts</Tab>
<Tab data-action-id="recipients" value="recipients">Recipients</Tab>
<Tab data-action-id="settings" value="settings">Settings</Tab>
<Tab data-action-id="analytics" value="analytics" badge="12">Analytics</Tab>
<Tab data-action-id="notifications" value="notifications">Notifications</Tab>
<Tab data-action-id="integrations" value="integrations">Integrations</Tab>
<Tab data-action-id="security" value="security">Security</Tab>
<template #more-actions>
<Menu>
<MenuItem data-action-id="overview">Overview</MenuItem>
<MenuItem data-action-id="transactions">
<Badge content="5" position="inline" color="red">Transactions</Badge>
</MenuItem>
<MenuItem data-action-id="documents">Documents</MenuItem>
<MenuItem data-action-id="accounts" is-disabled>Accounts</MenuItem>
<MenuItem data-action-id="recipients">Recipients</MenuItem>
<MenuItem data-action-id="settings">Settings</MenuItem>
<MenuItem data-action-id="analytics">
<Badge content="12" position="inline" color="red">Analytics</Badge>
</MenuItem>
<MenuItem data-action-id="notifications">Notifications</MenuItem>
<MenuItem data-action-id="integrations">Integrations</MenuItem>
<MenuItem data-action-id="security">Security</MenuItem>
</Menu>
</template>
</Tabs>
</template>Using an Array (DRY Approach)
For better maintainability and to keep a single source of truth, you can use an array to define your tabs configuration:
<script setup lang="ts">
import { ref } from "vue";
import Tab from '@leaflink/stash/Tab';
import Tabs from '@leaflink/stash/Tabs';
import Menu from '@leaflink/stash/Menu';
import MenuItem from '@leaflink/stash/MenuItem';
import Badge from '@leaflink/stash/Badge';
const activeTab = ref("overview");
const tabsConfig = [
{
id: 'overview',
label: 'Overview',
},
{
id: 'transactions',
label: 'Transactions',
badge: 5,
},
{
id: 'documents',
label: 'Documents',
},
{
id: 'accounts',
label: 'Accounts',
disabled: true,
},
{
id: 'recipients',
label: 'Recipients',
},
{
id: 'settings',
label: 'Settings',
},
{
id: 'analytics',
label: 'Analytics',
badge: 12,
},
{
id: 'notifications',
label: 'Notifications',
},
{
id: 'integrations',
label: 'Integrations',
},
{
id: 'security',
label: 'Security',
},
] as const;
</script>
<template>
<Tabs v-model:active-tab="activeTab" variant="enclosed">
<Tab v-for="config in tabsConfig" :data-action-id="config.id" :value="config.id" :badge="config.badge" :disabled="config.disabled">
{{ config.label }}
</Tab>
<template #more-actions>
<Menu>
<MenuItem v-for="config in tabsConfig" :data-action-id="config.id" :is-disabled="config.disabled">
<Badge v-if="config.badge" :content="config.badge" position="inline" color="red">
{{ config.label }}
</Badge>
<span v-else>{{ config.label }}</span>
</MenuItem>
</Menu>
</template>
</Tabs>
</template>API
See the documentation below for a complete reference to all the props and classes available to the components mentioned here.