From 386c184a848815928657c4da83aa821b8b08f5d8 Mon Sep 17 00:00:00 2001 From: skal Date: Thu, 5 Feb 2026 21:26:18 +0100 Subject: feat(timeline-editor): Add floating properties panel and effect tooltips UI improvements: - Properties panel now floats in top-right corner (fixed position) - Added collapse/expand button for properties panel - Panel slides out of view when collapsed, button appears to restore - Effects now show only class name, full details on hover (tooltip) - Tooltip shows: ClassName, Time, Priority, Args - Effect bars reduced from 35px to 26px height (cleaner appearance) - Effect spacing reduced from 40px to 30px (more compact stacking) - Effects use flexbox centering for better text alignment - Added hover highlight for better visual feedback CSS changes: - Properties panel: position fixed, z-index 1000, slide animation - Collapse button appears at top-right when panel hidden - Effects: single-line display with ellipsis overflow - Improved padding and font sizing for compact effect bars The properties panel is now always accessible without scrolling to the bottom of the page, and effect bars are much cleaner while still showing all information on hover. --- tools/timeline_editor/index.html | 119 ++++++++++++++++++++++++++++++++++----- 1 file changed, 105 insertions(+), 14 deletions(-) (limited to 'tools') diff --git a/tools/timeline_editor/index.html b/tools/timeline_editor/index.html index b84908a..c77ae41 100644 --- a/tools/timeline_editor/index.html +++ b/tools/timeline_editor/index.html @@ -154,14 +154,20 @@ background: #3a3d41; border: 1px solid #858585; border-radius: 3px; - padding: 6px; + padding: 4px 8px; cursor: move; - font-size: 12px; + font-size: 11px; transition: box-shadow 0.2s; + display: flex; + align-items: center; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } .effect:hover { box-shadow: 0 0 8px rgba(133, 133, 133, 0.5); + background: #45484d; } .effect.selected { @@ -169,16 +175,80 @@ box-shadow: 0 0 8px rgba(206, 145, 120, 0.5); } + .effect small { + font-size: 11px; + color: #d4d4d4; + } + .properties-panel { + position: fixed; + top: 80px; + right: 20px; + width: 350px; + max-height: 80vh; background: #252526; - padding: 20px; + padding: 15px; border-radius: 8px; - margin-top: 20px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5); + z-index: 1000; + overflow-y: auto; + transition: transform 0.3s ease; + } + + .properties-panel.collapsed { + transform: translateX(370px); } - .properties-panel h2 { + .panel-header { + display: flex; + justify-content: space-between; + align-items: center; margin-bottom: 15px; + padding-bottom: 10px; + border-bottom: 1px solid #3c3c3c; + } + + .panel-header h2 { + margin: 0; color: #4ec9b0; + font-size: 16px; + } + + .panel-toggle { + background: transparent; + border: 1px solid #858585; + color: #d4d4d4; + padding: 4px 8px; + border-radius: 3px; + cursor: pointer; + font-size: 12px; + } + + .panel-toggle:hover { + background: #3c3c3c; + } + + .panel-collapse-btn { + position: fixed; + top: 80px; + right: 20px; + background: #252526; + border: 1px solid #858585; + color: #d4d4d4; + padding: 8px 12px; + border-radius: 4px; + cursor: pointer; + z-index: 999; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); + display: none; + } + + .panel-collapse-btn:hover { + background: #3c3c3c; + } + + .panel-collapse-btn.visible { + display: block; } .property-group { @@ -267,8 +337,13 @@
+ + @@ -476,7 +551,8 @@ // Calculate sequence height based on number of effects (stacked vertically) const numEffects = seq.effects.length; - const seqHeight = Math.max(70, 25 + numEffects * 40 + 5); + const effectSpacing = 30; // Reduced from 40px + const seqHeight = Math.max(70, 20 + numEffects * effectSpacing + 5); seqDiv.style.left = `${seq.startTime * pixelsPerSecond}px`; seqDiv.style.top = `${seqIndex * 80}px`; @@ -521,11 +597,11 @@ const effectWidth = (effect.endTime - effect.startTime) * pixelsPerSecond; effectDiv.style.left = `${effectStart}px`; - effectDiv.style.top = `${seqIndex * 80 + 25 + effectIndex * 40}px`; + effectDiv.style.top = `${seqIndex * 80 + 20 + effectIndex * 30}px`; effectDiv.style.width = `${effectWidth}px`; - effectDiv.style.height = '35px'; + effectDiv.style.height = '26px'; - // Format time display based on mode + // Format time display based on mode (for tooltip) let timeDisplay; if (showBeats) { const beatDuration = 60.0 / bpm; @@ -536,10 +612,9 @@ timeDisplay = `${effect.startTime.toFixed(1)}-${effect.endTime.toFixed(1)}s`; } - effectDiv.innerHTML = ` - ${effect.className}
- ${timeDisplay} - `; + // Show only class name, full info on hover + effectDiv.innerHTML = `${effect.className}`; + effectDiv.title = `${effect.className}\n${timeDisplay}\nPriority: ${effect.priority}\n${effect.args || '(no args)'}`; if (selectedItem && selectedItem.type === 'effect' && selectedItem.seqIndex === seqIndex && selectedItem.effectIndex === effectIndex) { @@ -771,6 +846,22 @@ renderTimeline(); }); + // Properties panel collapse/expand + const panelToggle = document.getElementById('panelToggle'); + const panelCollapseBtn = document.getElementById('panelCollapseBtn'); + + panelToggle.addEventListener('click', () => { + propertiesPanel.classList.add('collapsed'); + panelCollapseBtn.classList.add('visible'); + panelToggle.textContent = '◀ Expand'; + }); + + panelCollapseBtn.addEventListener('click', () => { + propertiesPanel.classList.remove('collapsed'); + panelCollapseBtn.classList.remove('visible'); + panelToggle.textContent = '▶ Collapse'; + }); + // Click outside to deselect timeline.addEventListener('click', () => { selectedItem = null; -- cgit v1.2.3