feat(client): add inventions tab with notification dot to LeftPanel

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
root
2026-03-09 00:45:10 +00:00
parent 6b932d12a7
commit e27f2381eb
+53 -6
View File
@@ -5,14 +5,18 @@ export class LeftPanel {
private contentArea: HTMLDivElement;
private statsTab: HTMLDivElement;
private eventsTab: HTMLDivElement;
private inventionsTab: HTMLDivElement;
private inventionsContent: HTMLDivElement;
private notificationDot: HTMLDivElement;
private expanded = false;
private activeTab: 'stats' | 'events' | null = null;
private activeTab: 'stats' | 'events' | 'inventions' | null = null;
private superlativesContent: HTMLDivElement;
private eventsFeedContent: HTMLDivElement;
constructor(superlativesContent: HTMLDivElement, eventsFeedContent: HTMLDivElement) {
constructor(superlativesContent: HTMLDivElement, eventsFeedContent: HTMLDivElement, inventionsContent: HTMLDivElement) {
this.superlativesContent = superlativesContent;
this.eventsFeedContent = eventsFeedContent;
this.inventionsContent = inventionsContent;
// Outer container for positioning
this.container = document.createElement('div');
@@ -110,8 +114,32 @@ export class LeftPanel {
}
});
// Inventions tab ("I")
this.inventionsTab = this.createTab('I');
this.inventionsTab.style.position = 'relative';
this.notificationDot = document.createElement('div');
this.notificationDot.style.cssText = `
position: absolute;
top: 4px;
right: 4px;
width: 8px;
height: 8px;
background: #f0d060;
border-radius: 50%;
display: none;
`;
this.inventionsTab.appendChild(this.notificationDot);
this.inventionsTab.addEventListener('click', () => {
if (this.activeTab === 'inventions' && this.expanded) {
this.collapse();
} else {
this.expand('inventions');
}
});
tabContainer.appendChild(this.statsTab);
tabContainer.appendChild(this.eventsTab);
tabContainer.appendChild(this.inventionsTab);
this.container.appendChild(this.panel);
this.container.appendChild(tabContainer);
@@ -171,9 +199,14 @@ export class LeftPanel {
this.activeTab === 'events' && this.expanded ? '#2a2a4e' : '#1a1a2e';
this.eventsTab.dataset.active =
this.activeTab === 'events' && this.expanded ? 'true' : 'false';
this.inventionsTab.style.background =
this.activeTab === 'inventions' && this.expanded ? '#2a2a4e' : '#1a1a2e';
this.inventionsTab.dataset.active =
this.activeTab === 'inventions' && this.expanded ? 'true' : 'false';
}
private showContent(tab: 'stats' | 'events'): void {
private showContent(tab: 'stats' | 'events' | 'inventions'): void {
// Remove current content
while (this.contentArea.firstChild) {
this.contentArea.removeChild(this.contentArea.firstChild);
@@ -182,18 +215,24 @@ export class LeftPanel {
if (tab === 'stats') {
this.headerEl.textContent = 'SUPERLATIVES';
this.contentArea.appendChild(this.superlativesContent);
} else {
} else if (tab === 'events') {
this.headerEl.textContent = 'EVENTS';
this.contentArea.appendChild(this.eventsFeedContent);
} else if (tab === 'inventions') {
this.headerEl.textContent = 'INVENTIONS';
this.contentArea.appendChild(this.inventionsContent);
}
}
expand(tab: 'stats' | 'events'): void {
expand(tab: 'stats' | 'events' | 'inventions'): void {
this.activeTab = tab;
this.expanded = true;
this.showContent(tab);
this.updateTabs();
this.container.style.transform = 'translateY(-50%) translateX(0)';
if (tab === 'inventions') {
this.hideNotificationDot();
}
document.dispatchEvent(
new CustomEvent('left-panel-opened', { detail: { tab } }),
);
@@ -210,10 +249,18 @@ export class LeftPanel {
return this.expanded;
}
getActiveTab(): 'stats' | 'events' | null {
getActiveTab(): 'stats' | 'events' | 'inventions' | null {
return this.expanded ? this.activeTab : null;
}
showNotificationDot(): void {
this.notificationDot.style.display = '';
}
hideNotificationDot(): void {
this.notificationDot.style.display = 'none';
}
destroy(): void {
this.container.remove();
}