From fbac4503a4147c9680e102e79e9b9f1155a591b5 Mon Sep 17 00:00:00 2001 From: Pluto Date: Tue, 24 Feb 2026 23:15:23 +0530 Subject: [PATCH 1/5] feat: add support to open quick access panel --- src/nls/root/strings.js | 3 ++- src/styles/Extn-BottomPanelTabs.less | 27 +++++++++++++++++++++++++++ src/view/PanelView.js | 12 ++++++------ src/view/WorkspaceManager.js | 16 ++++++++++++---- 4 files changed, 47 insertions(+), 11 deletions(-) diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js index 68a7d5db1..a9d0dd475 100644 --- a/src/nls/root/strings.js +++ b/src/nls/root/strings.js @@ -1251,11 +1251,12 @@ define({ "REFERENCES_NO_RESULTS": "No References available for current cursor position", "REFERENCES_PANEL_TITLE": "References", "SEARCH_RESULTS_PANEL_TITLE": "Search Results", - "BOTTOM_PANEL_HIDE": "Hide Panel", + "BOTTOM_PANEL_MINIMIZE": "Minimize Panel", "BOTTOM_PANEL_SHOW": "Show Bottom Panel", "BOTTOM_PANEL_HIDE_TOGGLE": "Hide Bottom Panel", "BOTTOM_PANEL_DEFAULT_TITLE": "Quick Access", "BOTTOM_PANEL_DEFAULT_HEADING": "Open a Panel", + "BOTTOM_PANEL_OPEN_PANEL": "Open a Panel", "BOTTOM_PANEL_MAXIMIZE": "Maximize Panel", "BOTTOM_PANEL_RESTORE": "Restore Panel Size", diff --git a/src/styles/Extn-BottomPanelTabs.less b/src/styles/Extn-BottomPanelTabs.less index 03d38b9ab..530e6fcb1 100644 --- a/src/styles/Extn-BottomPanelTabs.less +++ b/src/styles/Extn-BottomPanelTabs.less @@ -194,6 +194,33 @@ } } +.bottom-panel-add-btn { + display: flex; + align-items: center; + justify-content: center; + width: 1.9rem; + height: 2rem; + cursor: pointer; + color: #888; + font-size: 0.82rem; + flex: 0 0 auto; + transition: color 0.12s ease, background-color 0.12s ease; + + .dark & { + color: #777; + } + + &:hover { + background-color: #e0e0e0; + color: #333; + + .dark & { + background-color: #333; + color: #eee; + } + } +} + .bottom-panel-tab-bar-actions { display: flex; align-items: center; diff --git a/src/view/PanelView.js b/src/view/PanelView.js index d6bb60b60..a827e93bf 100644 --- a/src/view/PanelView.js +++ b/src/view/PanelView.js @@ -467,9 +467,9 @@ define(function (require, exports, module) { _toggleMaximize(); }); - // Double-click on tab bar toggles maximize (exclude action buttons) + // Double-click on tab bar toggles maximize (exclude action buttons and add button) _$tabBar.on("dblclick", function (e) { - if ($(e.target).closest(".bottom-panel-tab-close-btn, .bottom-panel-hide-btn, .bottom-panel-maximize-btn").length) { + if ($(e.target).closest(".bottom-panel-tab-close-btn, .bottom-panel-hide-btn, .bottom-panel-maximize-btn, .bottom-panel-add-btn").length) { return; } _toggleMaximize(); @@ -568,12 +568,12 @@ define(function (require, exports, module) { let $btn = _$tabBar.find(".bottom-panel-maximize-btn"); let $icon = $btn.find("i"); if (_isMaximized) { - $icon.removeClass("fa-expand") - .addClass("fa-compress"); + $icon.removeClass("fa-regular fa-square") + .addClass("fa-solid fa-window-restore"); $btn.attr("title", Strings.BOTTOM_PANEL_RESTORE); } else { - $icon.removeClass("fa-compress") - .addClass("fa-expand"); + $icon.removeClass("fa-solid fa-window-restore") + .addClass("fa-regular fa-square"); $btn.attr("title", Strings.BOTTOM_PANEL_MAXIMIZE); } } diff --git a/src/view/WorkspaceManager.js b/src/view/WorkspaceManager.js index 1763460b0..ee793ad86 100644 --- a/src/view/WorkspaceManager.js +++ b/src/view/WorkspaceManager.js @@ -363,16 +363,19 @@ define(function (require, exports, module) { $bottomPanelContainer = $('
'); let $bottomPanelTabBar = $('
'); let $bottomPanelTabsOverflow = $('
'); + let $addPanelBtn = $('') + .attr('title', Strings.BOTTOM_PANEL_OPEN_PANEL); let $tabBarActions = $('
'); $tabBarActions.append( - $('') - .attr('title', Strings.BOTTOM_PANEL_MAXIMIZE) + $('') + .attr('title', Strings.BOTTOM_PANEL_MINIMIZE) ); $tabBarActions.append( - $('') - .attr('title', Strings.BOTTOM_PANEL_HIDE) + $('') + .attr('title', Strings.BOTTOM_PANEL_MAXIMIZE) ); $bottomPanelTabBar.append($bottomPanelTabsOverflow); + $bottomPanelTabBar.append($addPanelBtn); $bottomPanelTabBar.append($tabBarActions); $bottomPanelContainer.append($bottomPanelTabBar); $bottomPanelContainer.insertBefore("#status-bar"); @@ -402,6 +405,11 @@ define(function (require, exports, module) { _statusBarToggleInProgress = false; }); + // "+" button opens the quick access / default panel + $addPanelBtn.on("click", function () { + _showDefaultPanel(); + }); + // Make the container resizable (not individual panels) Resizer.makeResizable($bottomPanelContainer[0], Resizer.DIRECTION_VERTICAL, Resizer.POSITION_TOP, 200, false, undefined, true); From 6e276411d875b91dfd0d0efcd15ac4435f51380a Mon Sep 17 00:00:00 2001 From: Pluto Date: Tue, 24 Feb 2026 23:22:25 +0530 Subject: [PATCH 2/5] feat: dont show add panel button when quick panel is active --- src/view/PanelView.js | 57 ++++++++++++++++++++++++++++++++++-- src/view/WorkspaceManager.js | 10 +------ 2 files changed, 56 insertions(+), 11 deletions(-) diff --git a/src/view/PanelView.js b/src/view/PanelView.js index a827e93bf..a9f682785 100644 --- a/src/view/PanelView.js +++ b/src/view/PanelView.js @@ -100,6 +100,12 @@ define(function (require, exports, module) { /** @type {function} recomputeLayout callback from WorkspaceManager */ let _recomputeLayout = null; + /** @type {string|null} The default/quick-access panel ID */ + let _defaultPanelId = null; + + /** @type {jQueryObject} The "+" button inside the tab overflow area */ + let _$addBtn = null; + // --- Tab helper functions --- /** @@ -149,6 +155,12 @@ define(function (require, exports, module) { $tab.append($('×').attr('title', Strings.CLOSE)); _$tabsOverflow.append($tab); }); + + // Re-append the "+" button at the end (after all tabs) + if (_$addBtn) { + _$tabsOverflow.append(_$addBtn); + _updateAddButtonVisibility(); + } } /** @@ -190,7 +202,14 @@ define(function (require, exports, module) { .attr('data-panel-id', panelId); $tab.append($('').text(title)); $tab.append($('×').attr('title', Strings.CLOSE)); - _$tabsOverflow.append($tab); + + // Insert before the "+" button so it stays at the end + if (_$addBtn && _$addBtn.parent().length) { + _$addBtn.before($tab); + } else { + _$tabsOverflow.append($tab); + } + _updateAddButtonVisibility(); } /** @@ -204,6 +223,24 @@ define(function (require, exports, module) { return; } _$tabsOverflow.find('.bottom-panel-tab[data-panel-id="' + panelId + '"]').remove(); + _updateAddButtonVisibility(); + } + + /** + * Show or hide the "+" button based on whether the default panel is active. + * The button is hidden when the default panel is the active tab (since + * clicking "+" would be a no-op) and shown otherwise. + * @private + */ + function _updateAddButtonVisibility() { + if (!_$addBtn) { + return; + } + if (_defaultPanelId && _activeId === _defaultPanelId) { + _$addBtn.hide(); + } else { + _$addBtn.show(); + } } /** @@ -229,6 +266,7 @@ define(function (require, exports, module) { newPanel.$panel.addClass("active-bottom-panel"); } _updateActiveTabHighlight(); + _updateAddButtonVisibility(); } @@ -422,13 +460,20 @@ define(function (require, exports, module) { * @param {jQueryObject} $tabsOverflow The scrollable area holding tab elements. * @param {jQueryObject} $editorHolder The editor holder element (for maximize height calculation). * @param {function} recomputeLayoutFn Callback to trigger workspace layout recomputation. + * @param {string} defaultPanelId The ID of the default/quick-access panel. */ - function init($container, $tabBar, $tabsOverflow, $editorHolder, recomputeLayoutFn) { + function init($container, $tabBar, $tabsOverflow, $editorHolder, recomputeLayoutFn, defaultPanelId) { _$container = $container; _$tabBar = $tabBar; _$tabsOverflow = $tabsOverflow; _$editorHolder = $editorHolder; _recomputeLayout = recomputeLayoutFn; + _defaultPanelId = defaultPanelId; + + // Create the "+" button inside the tabs overflow area (after all tabs) + _$addBtn = $('') + .attr('title', Strings.BOTTOM_PANEL_OPEN_PANEL); + _$tabsOverflow.append(_$addBtn); // Tab bar click handlers _$tabBar.on("click", ".bottom-panel-tab-close-btn", function (e) { @@ -452,6 +497,14 @@ define(function (require, exports, module) { } }); + // "+" button opens the default/quick-access panel + _$addBtn.on("click", function (e) { + e.stopPropagation(); + if (_defaultPanelId && _panelMap[_defaultPanelId]) { + _panelMap[_defaultPanelId].show(); + } + }); + // Hide-panel button collapses the container but keeps tabs intact _$tabBar.on("click", ".bottom-panel-hide-btn", function (e) { e.stopPropagation(); diff --git a/src/view/WorkspaceManager.js b/src/view/WorkspaceManager.js index ee793ad86..882b3a58e 100644 --- a/src/view/WorkspaceManager.js +++ b/src/view/WorkspaceManager.js @@ -363,8 +363,6 @@ define(function (require, exports, module) { $bottomPanelContainer = $('
'); let $bottomPanelTabBar = $('
'); let $bottomPanelTabsOverflow = $('
'); - let $addPanelBtn = $('') - .attr('title', Strings.BOTTOM_PANEL_OPEN_PANEL); let $tabBarActions = $('
'); $tabBarActions.append( $('') @@ -375,7 +373,6 @@ define(function (require, exports, module) { .attr('title', Strings.BOTTOM_PANEL_MAXIMIZE) ); $bottomPanelTabBar.append($bottomPanelTabsOverflow); - $bottomPanelTabBar.append($addPanelBtn); $bottomPanelTabBar.append($tabBarActions); $bottomPanelContainer.append($bottomPanelTabBar); $bottomPanelContainer.insertBefore("#status-bar"); @@ -383,7 +380,7 @@ define(function (require, exports, module) { // Initialize PanelView with container DOM references and tab bar click handlers PanelView.init($bottomPanelContainer, $bottomPanelTabBar, $bottomPanelTabsOverflow, - $editorHolder, recomputeLayout); + $editorHolder, recomputeLayout, DEFAULT_PANEL_ID); // Create status bar chevron toggle for bottom panel $statusBarPanelToggle = $('
') @@ -405,11 +402,6 @@ define(function (require, exports, module) { _statusBarToggleInProgress = false; }); - // "+" button opens the quick access / default panel - $addPanelBtn.on("click", function () { - _showDefaultPanel(); - }); - // Make the container resizable (not individual panels) Resizer.makeResizable($bottomPanelContainer[0], Resizer.DIRECTION_VERTICAL, Resizer.POSITION_TOP, 200, false, undefined, true); From ad16dfe321da9db195c19fd36155a92ab911423c Mon Sep 17 00:00:00 2001 From: Pluto Date: Tue, 24 Feb 2026 23:43:31 +0530 Subject: [PATCH 3/5] fix: previously maximized state is not maintained when bottom panel is opened --- src/view/PanelView.js | 17 +++++++++++++++-- src/view/WorkspaceManager.js | 6 ++---- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/view/PanelView.js b/src/view/PanelView.js index a9f682785..2f3e58b44 100644 --- a/src/view/PanelView.js +++ b/src/view/PanelView.js @@ -505,11 +505,11 @@ define(function (require, exports, module) { } }); - // Hide-panel button collapses the container but keeps tabs intact + // Hide-panel button collapses the container but keeps tabs intact. + // Maximize state is preserved so the panel re-opens maximized. _$tabBar.on("click", ".bottom-panel-hide-btn", function (e) { e.stopPropagation(); if (_$container.is(":visible")) { - restoreIfMaximized(); Resizer.hide(_$container[0]); } }); @@ -527,6 +527,19 @@ define(function (require, exports, module) { } _toggleMaximize(); }); + + // When the container re-expands after being minimized, re-apply + // maximize if the user had maximized before minimizing. + // The Resizer restores the saved (maximized) height automatically, + // so we only need to update the button icon and recompute layout. + _$container.on("panelExpanded", function () { + if (_isMaximized) { + _updateMaximizeButton(); + if (_recomputeLayout) { + _recomputeLayout(); + } + } + }); } /** diff --git a/src/view/WorkspaceManager.js b/src/view/WorkspaceManager.js index 882b3a58e..dd2c89941 100644 --- a/src/view/WorkspaceManager.js +++ b/src/view/WorkspaceManager.js @@ -390,7 +390,6 @@ define(function (require, exports, module) { $statusBarPanelToggle.on("click", function () { _statusBarToggleInProgress = true; if ($bottomPanelContainer.is(":visible")) { - PanelView.restoreIfMaximized(); Resizer.hide($bottomPanelContainer[0]); triggerUpdateLayout(); } else if (PanelView.getOpenBottomPanelIDs().length > 0) { @@ -421,7 +420,6 @@ define(function (require, exports, module) { }); $bottomPanelContainer.on("panelCollapsed", function () { - PanelView.exitMaximizeOnResize(); $statusBarPanelToggle.find("i") .removeClass("fa-chevron-down") .addClass("fa-chevron-up"); @@ -634,9 +632,9 @@ define(function (require, exports, module) { } function _handleEscapeKey() { - // Collapse the entire bottom panel container, keeping all tabs intact + // Collapse the entire bottom panel container, keeping all tabs intact. + // Maximize state is preserved so the panel re-opens maximized. if ($bottomPanelContainer && $bottomPanelContainer.is(":visible")) { - PanelView.restoreIfMaximized(); Resizer.hide($bottomPanelContainer[0]); triggerUpdateLayout(); return true; From 8298b4d89108679b6b4e54a2b5ef545e02ce4fc0 Mon Sep 17 00:00:00 2001 From: Pluto Date: Wed, 25 Feb 2026 00:01:08 +0530 Subject: [PATCH 4/5] fix: maximize icon showing incorrect state after reload --- src/view/PanelView.js | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/src/view/PanelView.js b/src/view/PanelView.js index 2f3e58b44..839630a93 100644 --- a/src/view/PanelView.js +++ b/src/view/PanelView.js @@ -26,6 +26,7 @@ define(function (require, exports, module) { const EventDispatcher = require("utils/EventDispatcher"), + PreferencesManager = require("preferences/PreferencesManager"), Resizer = require("utils/Resizer"), Strings = require("strings"); @@ -91,6 +92,9 @@ define(function (require, exports, module) { */ const MIN_PANEL_HEIGHT = 200; + /** Preference key for persisting the maximize state across reloads. */ + const PREF_BOTTOM_PANEL_MAXIMIZED = "bottomPanelMaximized"; + /** @type {number|null} The panel height before maximize, for restore */ let _preMaximizeHeight = null; @@ -528,16 +532,24 @@ define(function (require, exports, module) { _toggleMaximize(); }); - // When the container re-expands after being minimized, re-apply - // maximize if the user had maximized before minimizing. - // The Resizer restores the saved (maximized) height automatically, - // so we only need to update the button icon and recompute layout. + // Restore maximize state from preferences (survives reload). + _isMaximized = PreferencesManager.getViewState(PREF_BOTTOM_PANEL_MAXIMIZED) === true; + + // When the container expands, re-apply maximize if the preference + // says we were maximized (covers both minimize→show and reload). _$container.on("panelExpanded", function () { if (_isMaximized) { - _updateMaximizeButton(); - if (_recomputeLayout) { - _recomputeLayout(); - } + // Defer to let all synchronous panelExpanded handlers + // (including WorkspaceManager's recomputeLayout) finish first. + setTimeout(function () { + let maxHeight = (_$editorHolder ? _$editorHolder.height() : 0) + + _$container.height(); + _$container.height(maxHeight); + _updateMaximizeButton(); + if (_recomputeLayout) { + _recomputeLayout(); + } + }, 0); } }); } @@ -566,6 +578,7 @@ define(function (require, exports, module) { let maxHeight = _$editorHolder.height() + _$container.height(); _$container.height(maxHeight); _isMaximized = true; + PreferencesManager.setViewState(PREF_BOTTOM_PANEL_MAXIMIZED, true); _updateMaximizeButton(); if (_recomputeLayout) { _recomputeLayout(); @@ -617,6 +630,7 @@ define(function (require, exports, module) { _$container.height(restoreHeight); _isMaximized = false; _preMaximizeHeight = null; + PreferencesManager.setViewState(PREF_BOTTOM_PANEL_MAXIMIZED, false); _updateMaximizeButton(); if (_recomputeLayout) { _recomputeLayout(); @@ -654,6 +668,7 @@ define(function (require, exports, module) { } _isMaximized = false; _preMaximizeHeight = null; + PreferencesManager.setViewState(PREF_BOTTOM_PANEL_MAXIMIZED, false); _updateMaximizeButton(); } @@ -669,6 +684,7 @@ define(function (require, exports, module) { } _isMaximized = true; _preMaximizeHeight = null; + PreferencesManager.setViewState(PREF_BOTTOM_PANEL_MAXIMIZED, true); _updateMaximizeButton(); } @@ -689,6 +705,7 @@ define(function (require, exports, module) { } _isMaximized = false; _preMaximizeHeight = null; + PreferencesManager.setViewState(PREF_BOTTOM_PANEL_MAXIMIZED, false); _updateMaximizeButton(); } From cd679ff51c6cfb9d8e40cd38c052db3a215b32b7 Mon Sep 17 00:00:00 2001 From: Pluto Date: Wed, 25 Feb 2026 00:04:41 +0530 Subject: [PATCH 5/5] refactor: better restore icon for bottom panel --- src/view/PanelView.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/view/PanelView.js b/src/view/PanelView.js index 839630a93..7cd2a4e97 100644 --- a/src/view/PanelView.js +++ b/src/view/PanelView.js @@ -649,10 +649,10 @@ define(function (require, exports, module) { let $icon = $btn.find("i"); if (_isMaximized) { $icon.removeClass("fa-regular fa-square") - .addClass("fa-solid fa-window-restore"); + .addClass("fa-regular fa-window-restore"); $btn.attr("title", Strings.BOTTOM_PANEL_RESTORE); } else { - $icon.removeClass("fa-solid fa-window-restore") + $icon.removeClass("fa-regular fa-window-restore") .addClass("fa-regular fa-square"); $btn.attr("title", Strings.BOTTOM_PANEL_MAXIMIZE); }