From 6725fd64267a4b3d5b4380d13ff87dd2e60ca2a8 Mon Sep 17 00:00:00 2001 From: Dimitrie Hoekstra Date: Mon, 29 Sep 2025 20:15:30 +0200 Subject: [PATCH] Hide scrollbars and add auto-show/hide minimap on navigation - Hide scrollbars on canvas while keeping it scrollable - Add minimap auto-show functionality that triggers on zoom and pan - Minimap appears for 2 seconds during navigation then fades out - Add smooth fade in/out animations for minimap visibility - Emit view:navigate events for all zoom and pan operations - Minimap stays visible if manually toggled with button --- .../editor-client/src/js/ui/view-navigator.js | 59 +++++++++++++++++-- .../@node-red/editor-client/src/js/ui/view.js | 6 ++ .../editor-client/src/sass/workspace.scss | 18 ++++++ 3 files changed, 79 insertions(+), 4 deletions(-) diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/view-navigator.js b/packages/node_modules/@node-red/editor-client/src/js/ui/view-navigator.js index 6450d45bd..904265728 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/view-navigator.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/view-navigator.js @@ -31,6 +31,8 @@ var dimensions; var isDragging; var isShowing = false; + var autoHideTimeout; + var isManuallyToggled = false; function refreshNodes() { if (!isShowing) { @@ -68,19 +70,59 @@ function toggle() { if (!isShowing) { isShowing = true; + isManuallyToggled = true; + clearTimeout(autoHideTimeout); $("#red-ui-view-navigate").addClass("selected"); resizeNavBorder(); refreshNodes(); $("#red-ui-workspace-chart").on("scroll",onScroll); - navContainer.fadeIn(200); + navContainer.addClass('red-ui-navigator-container'); + navContainer.show(); + setTimeout(function() { + navContainer.addClass('red-ui-navigator-visible'); + }, 10); } else { isShowing = false; - navContainer.fadeOut(100); + isManuallyToggled = false; + clearTimeout(autoHideTimeout); + navContainer.removeClass('red-ui-navigator-visible'); + setTimeout(function() { + navContainer.hide(); + }, 300); $("#red-ui-workspace-chart").off("scroll",onScroll); $("#red-ui-view-navigate").removeClass("selected"); } } + function showTemporary() { + if (!isManuallyToggled) { + clearTimeout(autoHideTimeout); + + if (!isShowing) { + isShowing = true; + resizeNavBorder(); + refreshNodes(); + $("#red-ui-workspace-chart").on("scroll",onScroll); + navContainer.addClass('red-ui-navigator-container'); + navContainer.show(); + setTimeout(function() { + navContainer.addClass('red-ui-navigator-visible'); + }, 10); + } + + autoHideTimeout = setTimeout(function() { + if (!isManuallyToggled && isShowing) { + isShowing = false; + navContainer.removeClass('red-ui-navigator-visible'); + setTimeout(function() { + navContainer.hide(); + }, 300); + $("#red-ui-workspace-chart").off("scroll",onScroll); + } + }, 2000); + } + } + return { init: function() { @@ -94,7 +136,7 @@ "bottom":$("#red-ui-workspace-footer").height(), "right":0, zIndex: 1 - }).appendTo("#red-ui-workspace").hide(); + }).addClass('red-ui-navigator-container').appendTo("#red-ui-workspace").hide(); navBox = d3.select(navContainer[0]) .append("svg:svg") @@ -148,10 +190,19 @@ toggle(); }) RED.popover.tooltip($("#red-ui-view-navigate"),RED._('actions.toggle-navigator'),'core:toggle-navigator'); + + // Listen for canvas interactions to show minimap temporarily + RED.events.on("view:selection-changed", function() { + showTemporary(); + }); + RED.events.on("view:navigate", function() { + showTemporary(); + }); }, refresh: refreshNodes, resize: resizeNavBorder, - toggle: toggle + toggle: toggle, + showTemporary: showTemporary } diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js index bbe0438c7..3f322cf0d 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js @@ -480,6 +480,7 @@ RED.view = (function() { mouse_mode = RED.state.PANNING; mouse_position = [touch0.pageX,touch0.pageY] scroll_position = [chart.scrollLeft(),chart.scrollTop()]; + RED.events.emit("view:navigate"); } } @@ -568,6 +569,7 @@ RED.view = (function() { var currentScroll = [chart.scrollLeft(), chart.scrollTop()]; chart.scrollLeft(currentScroll[0] - dx); chart.scrollTop(currentScroll[1] - dy); + RED.events.emit("view:navigate"); } // Update the center for next move moveTouchCenter = currentTouchCenter; @@ -1514,6 +1516,7 @@ RED.view = (function() { mouse_mode = RED.state.PANNING; mouse_position = [d3.event.pageX,d3.event.pageY] scroll_position = [chart.scrollLeft(),chart.scrollTop()]; + RED.events.emit("view:navigate"); return; } @@ -1523,6 +1526,7 @@ RED.view = (function() { mouse_mode = RED.state.PANNING; mouse_position = [d3.event.pageX,d3.event.pageY] scroll_position = [chart.scrollLeft(),chart.scrollTop()]; + RED.events.emit("view:navigate"); return; } if (d3.event.button === 2) { @@ -2080,6 +2084,7 @@ RED.view = (function() { chart.scrollLeft(scroll_position[0]+deltaPos[0]) chart.scrollTop(scroll_position[1]+deltaPos[1]) + RED.events.emit("view:navigate"); return } @@ -2831,6 +2836,7 @@ RED.view = (function() { RED.view.navigator.resize(); redraw(); + RED.events.emit("view:navigate"); if (RED.settings.get("editor.view.view-store-zoom")) { RED.settings.setLocal('zoom-level', factor.toFixed(1)) } diff --git a/packages/node_modules/@node-red/editor-client/src/sass/workspace.scss b/packages/node_modules/@node-red/editor-client/src/sass/workspace.scss index 7e03b063f..46be67158 100644 --- a/packages/node_modules/@node-red/editor-client/src/sass/workspace.scss +++ b/packages/node_modules/@node-red/editor-client/src/sass/workspace.scss @@ -38,6 +38,15 @@ box-sizing:border-box; transition: right 0.2s ease; touch-action: none; + + // Hide scrollbars + scrollbar-width: none; /* Firefox */ + -ms-overflow-style: none; /* Internet Explorer 10+ */ + &::-webkit-scrollbar { /* WebKit */ + width: 0; + height: 0; + } + &:focus { outline: none; } @@ -151,6 +160,15 @@ background: var(--red-ui-view-navigator-background); box-shadow: -1px 0 3px var(--red-ui-shadow); } + +.red-ui-navigator-container { + transition: opacity 0.3s ease; + opacity: 0; + + &.red-ui-navigator-visible { + opacity: 1; + } +} .red-ui-navigator-border { stroke-dasharray: 5,5; pointer-events: none;