Skip to content

Commit 8aa117c

Browse files
committed
feat: implement tab system in inspector for better navigation
1 parent 0d70a8f commit 8aa117c

1 file changed

Lines changed: 143 additions & 24 deletions

File tree

src/view/frontend/web/js/inspector.js

Lines changed: 143 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ document.addEventListener('alpine:init', () => {
1919
hoverDelay: 50, // ms delay for accurate position calculation
2020
lastBadgeUpdate: 0,
2121
badgeUpdateDelay: 150, // ms delay to prevent flickering
22+
activeTab: 'structure', // Current active tab in inspector
2223
panelData: {
2324
template: '',
2425
block: '',
@@ -459,36 +460,154 @@ document.addEventListener('alpine:init', () => {
459460
// Clear badge
460461
this.infoBadge.innerHTML = '';
461462

462-
// Template section with override indicator
463-
const templateDisplay = data.isOverride ? '🔧 ' + data.template : data.template;
464-
this.infoBadge.appendChild(this.createInfoSection('📄 Template', templateDisplay, '#60a5fa'));
463+
// Create tab system
464+
this.createTabSystem(data);
465465

466-
// Block section
467-
this.infoBadge.appendChild(this.createInfoSection('📦 Block', data.blockClass, '#a78bfa'));
466+
// Branding footer
467+
this.infoBadge.appendChild(this.createBrandingFooter());
468+
},
468469

469-
// Optional sections
470-
if (data.blockAlias) {
471-
this.infoBadge.appendChild(this.createInfoSection('🏷️ Block Name', data.blockAlias, '#34d399'));
472-
}
473-
if (data.parentBlock) {
474-
this.infoBadge.appendChild(this.createInfoSection('⬆️ Parent Block', data.parentBlock, '#fb923c'));
475-
}
476-
if (data.viewModel) {
477-
this.infoBadge.appendChild(this.createInfoSection('⚡ ViewModel', data.viewModel, '#22d3ee'));
470+
/**
471+
* Create tab system for inspector
472+
*/
473+
createTabSystem(data) {
474+
// Tab container
475+
const tabContainer = document.createElement('div');
476+
tabContainer.style.cssText = 'margin-bottom: 16px;';
477+
478+
// Tab header
479+
const tabHeader = document.createElement('div');
480+
tabHeader.style.cssText = `
481+
display: flex;
482+
gap: 4px;
483+
margin-bottom: 16px;
484+
border-bottom: 1px solid rgba(148, 163, 184, 0.15);
485+
`;
486+
487+
// Define tabs
488+
const tabs = [
489+
{ id: 'structure', label: 'Structure', icon: '🏰' },
490+
{ id: 'coming-soon', label: 'Coming Soon', icon: '🚀' }
491+
// Future tabs can be added here:
492+
// { id: 'performance', label: 'Performance', icon: '⚡' },
493+
// { id: 'seo', label: 'SEO', icon: '🔍' },
494+
];
495+
496+
// Tab content container
497+
const tabContentContainer = document.createElement('div');
498+
499+
// Create tab buttons
500+
tabs.forEach(tab => {
501+
const button = document.createElement('button');
502+
button.type = 'button';
503+
button.textContent = tab.label;
504+
button.style.cssText = `
505+
padding: 8px 12px;
506+
background: ${this.activeTab === tab.id ? 'rgba(59, 130, 246, 0.15)' : 'transparent'};
507+
color: ${this.activeTab === tab.id ? '#60a5fa' : '#94a3b8'};
508+
border: none;
509+
border-bottom: 2px solid ${this.activeTab === tab.id ? '#60a5fa' : 'transparent'};
510+
cursor: pointer;
511+
font-size: 11px;
512+
font-weight: 600;
513+
letter-spacing: 0.025em;
514+
transition: all 0.2s ease;
515+
border-radius: 6px 6px 0 0;
516+
font-family: inherit;
517+
`;
518+
519+
button.onmouseenter = () => {
520+
if (this.activeTab !== tab.id) {
521+
button.style.background = 'rgba(255, 255, 255, 0.05)';
522+
button.style.color = '#cbd5e1';
523+
}
524+
};
525+
526+
button.onmouseleave = () => {
527+
if (this.activeTab !== tab.id) {
528+
button.style.background = 'transparent';
529+
button.style.color = '#94a3b8';
530+
}
531+
};
532+
533+
button.onclick = (e) => {
534+
e.preventDefault();
535+
e.stopPropagation();
536+
this.switchTab(tab.id, data);
537+
};
538+
539+
tabHeader.appendChild(button);
540+
});
541+
542+
tabContainer.appendChild(tabHeader);
543+
tabContainer.appendChild(tabContentContainer);
544+
this.infoBadge.appendChild(tabContainer);
545+
546+
// Render initial tab content
547+
this.renderTabContent(this.activeTab, data, tabContentContainer);
548+
},
549+
550+
/**
551+
* Switch to different tab
552+
*/
553+
switchTab(tabId, data) {
554+
this.activeTab = tabId;
555+
556+
// Find the element to rebuild
557+
const element = this.hoveredElement || this.selectedElement;
558+
if (element) {
559+
const rect = this.getElementRect(element);
560+
this.buildBadgeContent(element, rect);
478561
}
562+
},
563+
564+
/**
565+
* Render content for specific tab
566+
*/
567+
renderTabContent(tabId, data, container) {
568+
container.innerHTML = '';
479569

480-
// Module section
481-
this.infoBadge.appendChild(this.createInfoSection('📍 Module', data.module, '#fbbf24'));
570+
if (tabId === 'structure') {
571+
// Template section with override indicator
572+
const templateDisplay = data.isOverride ? '🔧 ' + data.template : data.template;
573+
container.appendChild(this.createInfoSection('📄 Template', templateDisplay, '#60a5fa'));
482574

483-
// Dimensions section
484-
const dimensionsDiv = this.createInfoSection('📐 Dimensions', `${Math.round(rect.width)} × ${Math.round(rect.height)} px`, '#6b7280');
485-
dimensionsDiv.style.borderTop = '1px solid rgba(148, 163, 184, 0.12)';
486-
dimensionsDiv.style.paddingTop = '12px';
487-
dimensionsDiv.style.marginTop = '12px';
488-
this.infoBadge.appendChild(dimensionsDiv);
575+
// Block section
576+
container.appendChild(this.createInfoSection('📦 Block', data.blockClass, '#a78bfa'));
489577

490-
// Branding footer
491-
this.infoBadge.appendChild(this.createBrandingFooter());
578+
// Optional sections
579+
if (data.blockAlias) {
580+
container.appendChild(this.createInfoSection('🏷️ Block Name', data.blockAlias, '#34d399'));
581+
}
582+
if (data.parentBlock) {
583+
container.appendChild(this.createInfoSection('⬆️ Parent Block', data.parentBlock, '#fb923c'));
584+
}
585+
if (data.viewModel) {
586+
container.appendChild(this.createInfoSection('⚡ ViewModel', data.viewModel, '#22d3ee'));
587+
}
588+
589+
// Module section
590+
container.appendChild(this.createInfoSection('📍 Module', data.module, '#fbbf24'));
591+
} else if (tabId === 'coming-soon') {
592+
// Coming Soon content
593+
const comingSoonDiv = document.createElement('div');
594+
comingSoonDiv.style.cssText = `
595+
text-align: center;
596+
padding: 24px 16px;
597+
color: #94a3b8;
598+
font-size: 12px;
599+
line-height: 1.6;
600+
`;
601+
comingSoonDiv.innerHTML = `
602+
<div style="font-size: 32px; margin-bottom: 12px;">🚀</div>
603+
<div style="color: #cbd5e1; font-weight: 600; margin-bottom: 8px;">Coming Soon</div>
604+
<div style="color: #94a3b8;">MageForge is currently building something beautiful for you</div>
605+
`;
606+
container.appendChild(comingSoonDiv);
607+
}
608+
// Future tabs can be added here:
609+
// else if (tabId === 'performance') { ... }
610+
// else if (tabId === 'seo') { ... }
492611
},
493612

494613
/**

0 commit comments

Comments
 (0)