Overview
The tab system enables users to view different types of information (Summary, Define, Facts, AI, Translate) about selected text. Tabs are defined in a configuration array and rendered dynamically with icons, labels, and optional beta badges.
Tab Definitions
All tabs are configured in the TABS array:
const TABS = [
{ id: 'summary', label: 'Summary', labelAr: 'ملخص',
svg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>' },
{ id: 'define', label: 'Define', labelAr: 'تعريف',
svg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>' },
{ id: 'facts', label: 'Facts', labelAr: 'حقائق',
svg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>' },
{ id: 'ai', label: 'AI', labelAr: 'ذكاء',
svg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a4 4 0 0 1 4 4v1h1a3 3 0 0 1 3 3v1a3 3 0 0 1-3 3h-1v4a2 2 0 0 1-2 2H10a2 2 0 0 1-2-2v-4H7a3 3 0 0 1-3-3v-1a3 3 0 0 1 3-3h1V6a4 4 0 0 1 4-4z"/><circle cx="9.5" cy="10" r="1" fill="currentColor" stroke="none"/><circle cx="14.5" cy="10" r="1" fill="currentColor" stroke="none"/></svg>' },
{ id: 'translate', label: 'Translate', labelAr: 'ترجمة', beta: true,
svg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m5 8 6 6"/><path d="m4 14 6-6 2-3"/><path d="M2 5h12"/><path d="M7 2h1"/><path d="m22 22-5-10-5 10"/><path d="M14 18h6"/></svg>' }
];
Tab Properties:
id - Unique identifier for routing and state management
label - English display label
labelAr - Arabic display label (for RTL support)
svg - Inline SVG icon markup
beta (optional) - Shows a “beta” badge on the tab
SVG icons are inlined to avoid external dependencies and ensure consistent rendering across all web pages.
Creating the Tab Bar
The createTabBar() function iterates through the TABS array and builds the navigation:
function createTabBar(language) {
const tabBar = document.createElement('div');
tabBar.className = 'wiki-tooltip-tabs';
TABS.forEach(tab => {
const tabEl = document.createElement('button');
tabEl.className = 'wiki-tooltip-tab' + (tab.id === activeTab ? ' active' : '');
tabEl.dataset.tab = tab.id;
const icon = document.createElement('span');
icon.className = 'wiki-tooltip-tab-icon';
icon.innerHTML = tab.svg;
tabEl.appendChild(icon);
const label = document.createElement('span');
label.className = 'wiki-tooltip-tab-label';
label.textContent = language === 'ar' ? tab.labelAr : tab.label;
tabEl.appendChild(label);
if (tab.beta) {
const badge = document.createElement('span');
badge.className = 'wiki-tab-beta-badge';
badge.textContent = 'beta';
tabEl.appendChild(badge);
}
tabEl.addEventListener('click', () => {
switchTab(tab.id);
});
tabBar.appendChild(tabEl);
});
return tabBar;
}
Rendering Steps:
- Create tab button with appropriate active class
- Add SVG icon
- Add localized label (English or Arabic)
- Conditionally render beta badge
- Attach click handler for tab switching
The active tab is determined by the activeTab global state variable, which defaults to 'summary'.
Tab Switching
When a user clicks a tab, switchTab() updates the UI and loads content:
function switchTab(tabId) {
if (activeTab === tabId) return;
activeTab = tabId;
// Update tab UI
const tabs = tooltip.querySelectorAll('.wiki-tooltip-tab');
tabs.forEach(t => {
t.classList.toggle('active', t.dataset.tab === tabId);
});
// Load tab content
loadTabContent(tabId);
}
State Management:
- Prevents redundant switching if already on the target tab
- Updates
activeTab global state
- Toggles CSS classes for visual feedback
- Triggers content loading for the new tab
Content Loading
The loadTabContent() function routes to the appropriate data source:
function loadTabContent(tabId) {
const contentArea = tooltip.querySelector('#wiki-tooltip-content-area');
if (!contentArea) return;
// AI and Translate tabs have their own async state management
if (tabId === 'ai') {
loadAITab(contentArea);
return;
}
if (tabId === 'translate') {
loadTranslateTab(contentArea);
return;
}
const cleanedTerm = cleanSearchTerm(currentSearchTerm, currentLanguage);
// Check cache
const cached = getFromCache(cleanedTerm, tabId);
if (cached) {
renderTabContent(tabId, cached, contentArea);
return;
}
// Show loading
clearElement(contentArea);
contentArea.appendChild(createLoadingIndicator());
// Fetch data
switch (tabId) {
case 'summary':
fetchSummaryData(cleanedTerm);
break;
case 'define':
fetchDefineData(cleanedTerm);
break;
case 'facts':
fetchFactsData(cleanedTerm);
break;
}
}
Content Loading Flow:
- Check cache - Return instantly if data is cached
- Show loading indicator - Display spinner while fetching
- Fetch data - Call appropriate API via background script
- Render content - Display results in content area
AI and Translate tabs require API key validation, so they use specialized loading functions instead of the standard cache-and-fetch flow.
Content Rendering
Once data is available, renderTabContent() delegates to tab-specific renderers:
function renderTabContent(tabId, data, contentArea) {
clearElement(contentArea);
switch (tabId) {
case 'summary':
renderSummaryContent(data, contentArea);
break;
case 'define':
renderDefineContent(data, contentArea);
break;
case 'facts':
renderFactsContent(data, contentArea);
break;
case 'ai':
renderAITab(contentArea);
break;
case 'translate':
renderTranslateTab(contentArea, data);
break;
}
}
Adding New Tabs
To add a new tab:
- Add to TABS array:
{ id: 'mynew', label: 'My New Tab', labelAr: 'تبويب جديد',
svg: '<svg>...</svg>', beta: true }
- Add routing in loadTabContent():
case 'mynew':
fetchMyNewData(cleanedTerm);
break;
- Add renderer in renderTabContent():
case 'mynew':
renderMyNewContent(data, contentArea);
break;
New tabs automatically inherit RTL support, caching, and loading indicators through the shared infrastructure.