e27f2381eb
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
268 lines
7.6 KiB
TypeScript
268 lines
7.6 KiB
TypeScript
export class LeftPanel {
|
|
private container: HTMLDivElement;
|
|
private panel: HTMLDivElement;
|
|
private headerEl: HTMLDivElement;
|
|
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' | 'inventions' | null = null;
|
|
private superlativesContent: HTMLDivElement;
|
|
private 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');
|
|
this.container.style.cssText = `
|
|
position: fixed;
|
|
left: 0;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
z-index: 1000;
|
|
display: flex;
|
|
flex-direction: row;
|
|
font-family: 'Press Start 2P', monospace;
|
|
transition: transform 0.35s ease;
|
|
`;
|
|
|
|
// Main panel
|
|
this.panel = document.createElement('div');
|
|
this.panel.style.cssText = `
|
|
width: 340px;
|
|
background: #1a1a2e;
|
|
border: 3px solid #e0d0b0;
|
|
border-left: none;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
max-height: 80vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
`;
|
|
|
|
// Inner frame (EarthBound double-border)
|
|
const innerFrame = document.createElement('div');
|
|
innerFrame.style.cssText = `
|
|
border: 2px solid #8878a8;
|
|
margin: 4px;
|
|
padding: 8px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
flex: 1;
|
|
`;
|
|
|
|
// Header
|
|
this.headerEl = document.createElement('div');
|
|
this.headerEl.style.cssText = `
|
|
text-align: center;
|
|
color: #e0d0b0;
|
|
font-size: 16px;
|
|
padding: 4px 0 8px 0;
|
|
border-bottom: 1px solid #8878a8;
|
|
margin-bottom: 8px;
|
|
flex-shrink: 0;
|
|
`;
|
|
this.headerEl.textContent = 'SUPERLATIVES';
|
|
|
|
// Content area (swaps between superlatives and events)
|
|
this.contentArea = document.createElement('div');
|
|
this.contentArea.style.cssText = `
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
display: flex;
|
|
flex-direction: column;
|
|
`;
|
|
|
|
innerFrame.appendChild(this.headerEl);
|
|
innerFrame.appendChild(this.contentArea);
|
|
this.panel.appendChild(innerFrame);
|
|
|
|
// Tab buttons container (stacked vertically on right edge)
|
|
const tabContainer = document.createElement('div');
|
|
tabContainer.style.cssText = `
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-self: center;
|
|
gap: 2px;
|
|
flex-shrink: 0;
|
|
`;
|
|
|
|
// Stats tab ("S")
|
|
this.statsTab = this.createTab('S');
|
|
this.statsTab.addEventListener('click', () => {
|
|
if (this.activeTab === 'stats' && this.expanded) {
|
|
this.collapse();
|
|
} else {
|
|
this.expand('stats');
|
|
}
|
|
});
|
|
|
|
// Events tab ("E")
|
|
this.eventsTab = this.createTab('E');
|
|
this.eventsTab.addEventListener('click', () => {
|
|
if (this.activeTab === 'events' && this.expanded) {
|
|
this.collapse();
|
|
} else {
|
|
this.expand('events');
|
|
}
|
|
});
|
|
|
|
// 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);
|
|
|
|
// Start collapsed
|
|
this.container.style.transform = 'translateY(-50%) translateX(-340px)';
|
|
|
|
document.body.appendChild(this.container);
|
|
}
|
|
|
|
private createTab(label: string): HTMLDivElement {
|
|
const tab = document.createElement('div');
|
|
tab.style.cssText = `
|
|
width: 32px;
|
|
height: 56px;
|
|
background: #1a1a2e;
|
|
border: 3px solid #e0d0b0;
|
|
border-left: none;
|
|
border-radius: 0 6px 6px 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
cursor: pointer;
|
|
flex-shrink: 0;
|
|
transition: background 0.2s;
|
|
`;
|
|
|
|
const tabInner = document.createElement('div');
|
|
tabInner.style.cssText = `
|
|
color: #e0d0b0;
|
|
font-size: 20px;
|
|
`;
|
|
tabInner.textContent = label;
|
|
tab.appendChild(tabInner);
|
|
|
|
tab.addEventListener('mouseenter', () => {
|
|
if (tab.dataset.active !== 'true') {
|
|
tab.style.background = '#2a2a4e';
|
|
}
|
|
});
|
|
tab.addEventListener('mouseleave', () => {
|
|
if (tab.dataset.active !== 'true') {
|
|
tab.style.background = '#1a1a2e';
|
|
}
|
|
});
|
|
|
|
return tab;
|
|
}
|
|
|
|
private updateTabs(): void {
|
|
this.statsTab.style.background =
|
|
this.activeTab === 'stats' && this.expanded ? '#2a2a4e' : '#1a1a2e';
|
|
this.statsTab.dataset.active =
|
|
this.activeTab === 'stats' && this.expanded ? 'true' : 'false';
|
|
|
|
this.eventsTab.style.background =
|
|
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' | 'inventions'): void {
|
|
// Remove current content
|
|
while (this.contentArea.firstChild) {
|
|
this.contentArea.removeChild(this.contentArea.firstChild);
|
|
}
|
|
|
|
if (tab === 'stats') {
|
|
this.headerEl.textContent = 'SUPERLATIVES';
|
|
this.contentArea.appendChild(this.superlativesContent);
|
|
} 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' | '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 } }),
|
|
);
|
|
}
|
|
|
|
collapse(): void {
|
|
this.expanded = false;
|
|
this.container.style.transform = 'translateY(-50%) translateX(-340px)';
|
|
this.updateTabs();
|
|
document.dispatchEvent(new CustomEvent('left-panel-closed'));
|
|
}
|
|
|
|
isExpanded(): boolean {
|
|
return this.expanded;
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|