The Active Item Plugin tracks which item is currently active in the registry. It's perfect for implementing tabs, navigation menus, or any single-selection scenario where only one item should be active at a time.
import { useCheckIn } from 'vue-airport';
import { createActiveItemPlugin } from '@vue-airport/plugins-base';
const { createDesk } = useCheckIn<TabItem>();
const { desk } = createDesk('tabs', {
plugins: [createActiveItemPlugin()]
});
interface TabItem {
label: string;
content: string;
}
const { createDesk } = useCheckIn<TabItem>();
const { desk } = createDesk('tabs', {
plugins: [createActiveItemPlugin()]
});
// Check in some tabs
desk.checkIn('tab-1', { label: 'Home', content: 'Welcome' });
desk.checkIn('tab-2', { label: 'About', content: 'About us' });
desk.checkIn('tab-3', { label: 'Contact', content: 'Get in touch' });
// Set active tab
desk.setActive('tab-1');
// Get active tab
const active = desk.getActive();
console.log(active?.data.label); // 'Home'
// Check if there's an active item
console.log(desk.hasActive); // true
// Get active ID directly
console.log(desk.activeId); // 'tab-1'
// Clear active
desk.clearActive();
console.log(desk.hasActive); // false
The plugin emits an active-changed event whenever the active item changes:
desk.on('active-changed', ({ id, data }) => {
if (id === undefined) {
console.log('Active cleared');
} else {
console.log('Active changed to:', id, data);
}
});
desk.setActive('tab-1');
// Logs: 'Active changed to: tab-1 { label: 'Home', content: 'Welcome' }'
desk.clearActive();
// Logs: 'Active cleared'
Here's how to use the Active Item Plugin in a Vue component:
<script setup lang="ts">
import { useCheckIn, createActiveItemPlugin } from 'vue-airport';
interface Tab {
label: string;
content: string;
}
const { createDesk } = useCheckIn<Tab>();
const { desk } = createDesk('tabs', {
plugins: [createActiveItemPlugin()]
});
// Initialize tabs
const tabs = [
{ id: 'home', label: 'Home', content: 'Welcome home' },
{ id: 'about', label: 'About', content: 'About us' },
{ id: 'contact', label: 'Contact', content: 'Contact us' }
];
tabs.forEach(tab => {
desk.checkIn(tab.id, { label: tab.label, content: tab.content });
});
// Set initial active tab
desk.setActive('home');
// Get active tab for display
const activeTab = computed(() => desk.getActive());
</script>
<template>
<div class="tabs">
<div class="tab-buttons">
<button
v-for="item in desk.items"
:key="item.id"
:class="{ active: desk.activeId === item.id }"
@click="desk.setActive(item.id)"
>
{{ item.data.label }}
</button>
</div>
<div class="tab-content">
<p v-if="activeTab">{{ activeTab.data.content }}</p>
<p v-else>No tab selected</p>
</div>
</div>
</template>
setActive(id: string | number | null): booleanSets the active item by ID. Returns true if successful, false if the item doesn't exist.
desk.setActive('tab-1'); // true
desk.setActive('non-existent'); // false
desk.setActive(null); // Clears active, returns true
getActive(): CheckInItem<T> | nullReturns the currently active item or null if no item is active.
const active = desk.getActive();
if (active) {
console.log(active.id, active.data);
}
clearActive(): booleanClears the active item. Equivalent to setActive(null).
desk.clearActive();
console.log(desk.hasActive); // false
activeId: Ref<string | number | null>A reactive reference to the ID of the currently active item.
watchEffect(() => {
console.log('Active ID:', desk.activeId);
});
desk.setActive('tab-1');
// Logs: 'Active ID: tab-1'
hasActive: booleanA computed boolean indicating whether there's an active item.
if (desk.hasActive) {
console.log('There is an active item');
}
active-changedEmitted when the active item changes.
desk.on('active-changed', ({ id, data }) => {
// id and data are undefined when cleared
// otherwise, id is the item ID and data is the item data
});
interface MenuItem {
label: string;
route: string;
}
const { desk } = createDesk('menu', {
plugins: [createActiveItemPlugin()]
});
// Listen to route changes
desk.on('active-changed', ({ id, data }) => {
if (data) {
router.push(data.route);
}
});
interface Image {
url: string;
caption: string;
}
const { desk } = createDesk('gallery', {
plugins: [createActiveItemPlugin()]
});
// Show full-size image when selected
const selectedImage = computed(() => desk.getActive());
interface FormSection {
title: string;
fields: string[];
}
const { desk } = createDesk('form-sections', {
plugins: [createActiveItemPlugin()]
});
// Navigate through form sections
const goToNextSection = () => {
const current = desk.getActive();
if (current) {
const items = desk.items;
const currentIndex = items.findIndex(item => item.id === current.id);
if (currentIndex < items.length - 1) {
desk.setActive(items[currentIndex + 1].id);
}
}
};
desk.on('check-out', ({ id }) => {
if (desk.activeId === id) {
desk.clearActive();
// Or set a new active item
const remaining = desk.items;
if (remaining.length > 0) {
desk.setActive(remaining[0].id);
}
}
});
setActive() with an ID that doesn't exist in the registry will return false and not change the active item.See the Tabs Example for a complete working implementation.