Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
71554f5
feat: tabbed bottom panel initial architecture
devvaannsh Feb 17, 2026
013f774
feat: improve bottom panel tab bar styling
devvaannsh Feb 17, 2026
68b7ab9
feat: remove redundant box shadow color between panel and tabbar
devvaannsh Feb 17, 2026
3e97a59
refactor: reduce height of active tab styling
devvaannsh Feb 17, 2026
65492cd
feat: better support for bottom panel tab bar title
devvaannsh Feb 17, 2026
f6c95cc
feat: better support for tab naming using dom lookup
devvaannsh Feb 17, 2026
6892665
feat: prevent full tab bar dom rebuild on panel switch
devvaannsh Feb 17, 2026
5b6b6c9
feat: deprecate min size param from bottom panel
devvaannsh Feb 17, 2026
52ad891
refactor: improve bottom panel tab bar styling
devvaannsh Feb 17, 2026
10a6444
fix: redundant duplicated jsdoc
devvaannsh Feb 18, 2026
a101ca3
feat: add single close button that hides panel
devvaannsh Feb 18, 2026
9b11b69
feat: hide the bottom panel and don’t destroy any active ones
devvaannsh Feb 18, 2026
32265c4
feat: add button to toggle the bottom panel via status bar
devvaannsh Feb 18, 2026
ca9b32f
feat: animate buttons when panel toggles its state via non status bar…
devvaannsh Feb 18, 2026
aa5fd1d
refactor: better styling for the hide panel button in bottom panel ta…
devvaannsh Feb 18, 2026
29d192c
chore: localize the strings
devvaannsh Feb 18, 2026
457fcd4
fix: some panel content getting cut off and not taking full available…
devvaannsh Feb 18, 2026
ab7825f
refactor: update shortcuts panel styles to make it consistent with th…
devvaannsh Feb 18, 2026
bf8e75a
refactor: update custom snippets style as per new tabbed panel archit…
devvaannsh Feb 18, 2026
dfae384
feat: update git panel styles to fit new architecture
devvaannsh Feb 18, 2026
9ce2e87
feat: update problems panel style to match new architecture
devvaannsh Feb 18, 2026
ab4e324
feat: update test builder styles
devvaannsh Feb 18, 2026
27aa6ba
feat: update search panel styles
devvaannsh Feb 18, 2026
4a68213
feat: move the tabbed bottom panel logic to panel view
devvaannsh Feb 19, 2026
983faba
feat: set title and attribute using the functions
devvaannsh Feb 19, 2026
a23a4e4
refactor: set title and attr using functions
devvaannsh Feb 19, 2026
169ffef
fix: escape key destroying non-visible panels
devvaannsh Feb 19, 2026
50642aa
feat: update the title only on setTitle instead of full dom rebuild
devvaannsh Feb 19, 2026
7f6e377
feat: hide all open bottom panels at once instead of closing them ind…
devvaannsh Feb 19, 2026
eeb11d6
fix: event shown event not firing
devvaannsh Feb 19, 2026
7af00d5
feat: remove snippets count tracking from the title
devvaannsh Feb 19, 2026
a014c00
fix: git more options button appearing at incorrect position due to r…
devvaannsh Feb 19, 2026
116a036
feat: open quick access panel when on other panel is opened
devvaannsh Feb 19, 2026
fc65b40
feat: remove read more from the quick access panel for better accessi…
devvaannsh Feb 19, 2026
694ba3b
feat: show no results page when no results match in find in files
devvaannsh Feb 19, 2026
62b3a49
feat: only show no results page when modal has valid query
devvaannsh Feb 19, 2026
19e6987
feat: escape key hides the bottom panel instead of destroying a panel
devvaannsh Feb 19, 2026
7c2e1bc
fix: checkmark/active indicators not getting removed when tab is closed
devvaannsh Feb 19, 2026
da8b0e8
feat: only show the buttons available in the quick access panel
devvaannsh Feb 19, 2026
c4773b2
fix: find in files buttons getting misplaced with empty input boxes
devvaannsh Feb 20, 2026
f7d0301
feat: add singular add/destroy panel functions to prevent whole DOM r…
devvaannsh Feb 20, 2026
39b9bee
refactor: show the add snippets button on the centre of the panel
devvaannsh Feb 20, 2026
f6206c2
chore: auto update API docs
devvaannsh Feb 20, 2026
c2c0c56
fix: file filters integ tests failing
devvaannsh Feb 20, 2026
351463e
feat: dont auto show problems panel
devvaannsh Feb 21, 2026
0499f50
fix: always show problems panel option in the quick access as it show…
devvaannsh Feb 21, 2026
5b90f65
fix: code inspection jshint eslint integ tests failing
devvaannsh Feb 21, 2026
b05e1fc
feat: jshint integ tests failing when run individually
devvaannsh Feb 21, 2026
abf52bf
chore: auto update api docs
devvaannsh Feb 21, 2026
459ec24
fix: code inspection legacy integ tests failing
devvaannsh Feb 21, 2026
314bd3f
feat: add support to maximize/restore bottom panel window
devvaannsh Feb 21, 2026
392009c
refactor: add expand and compress icons
devvaannsh Feb 21, 2026
b7ce11f
refactor: better styling for bottom panel tab bar action buttons
devvaannsh Feb 21, 2026
b594cde
feat: better resize handling support for maximize and restore option
devvaannsh Feb 21, 2026
fedcf67
fix: find in files legacy integ tests failing
devvaannsh Feb 21, 2026
4ad58b4
fix: main view manager tests failing
devvaannsh Feb 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/API-Reference/command/Commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -992,6 +992,12 @@ Performs a mixed reset
## CMD\_GIT\_TOGGLE\_PANEL
Toggles the git panel

**Kind**: global variable
<a name="CMD_CUSTOM_SNIPPETS_PANEL"></a>

## CMD\_CUSTOM\_SNIPPETS\_PANEL
Toggles the custom snippets panel

**Kind**: global variable
<a name="CMD_GIT_GOTO_NEXT_CHANGE"></a>

Expand Down
2 changes: 1 addition & 1 deletion docs/API-Reference/document/Document.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ Given a character index within the document text (assuming \n newlines),
returns the corresponding {line, ch} position. Works whether or not
a master editor is attached.

**Kind**: instance method of [<code>Document</code>](#Document)
**Kind**: instance method of [<code>Document</code>](#Document)

| Param | Type | Description |
| --- | --- | --- |
Expand Down
3 changes: 2 additions & 1 deletion docs/API-Reference/search/SearchResultsView.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ Dispatches the following events_
### new Handles the search results panel.
Dispatches the following events:
replaceBatch - when the Replace button is clicked.
close - when the panel is closed.(model, panelID, panelName, type)
close - when the panel is closed.(model, panelID, panelName, type, [title])

| Param | Type | Description |
| --- | --- | --- |
| model | <code>SearchModel</code> | The model that this view is showing. |
| panelID | <code>string</code> | The CSS ID to use for the panel. |
| panelName | <code>string</code> | The name to use for the panel, as passed to WorkspaceManager.createBottomPanel(). |
| type | <code>string</code> | type to identify if it is reference search or string match serach |
| [title] | <code>string</code> | Display title for the panel tab. |

89 changes: 87 additions & 2 deletions docs/API-Reference/view/PanelView.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,29 @@ const PanelView = brackets.getModule("view/PanelView")
**Kind**: global class

* [Panel](#Panel)
* [new Panel($panel)](#new_Panel_new)
* [new Panel($panel, id, [title])](#new_Panel_new)
* [.$panel](#Panel+$panel) : <code>jQueryObject</code>
* [.isVisible()](#Panel+isVisible) ⇒ <code>boolean</code>
* [.registerCanBeShownHandler(canShowHandlerFn)](#Panel+registerCanBeShownHandler) ⇒ <code>boolean</code>
* [.canBeShown()](#Panel+canBeShown) ⇒ <code>boolean</code>
* [.show()](#Panel+show)
* [.hide()](#Panel+hide)
* [.setVisible(visible)](#Panel+setVisible)
* [.setTitle(newTitle)](#Panel+setTitle)
* [.destroy()](#Panel+destroy)
* [.getPanelType()](#Panel+getPanelType) ⇒ <code>string</code>

<a name="new_Panel_new"></a>

### new Panel($panel)
### new Panel($panel, id, [title])
Represents a panel below the editor area (a child of ".content").


| Param | Type | Description |
| --- | --- | --- |
| $panel | <code>jQueryObject</code> | The entire panel, including any chrome, already in the DOM. |
| id | <code>string</code> | Unique panel identifier. |
| [title] | <code>string</code> | Optional display title for the tab bar. |

<a name="Panel+$panel"></a>

Expand Down Expand Up @@ -84,12 +88,66 @@ Sets the panel's visibility state
| --- | --- | --- |
| visible | <code>boolean</code> | true to show, false to hide |

<a name="Panel+setTitle"></a>

### panel.setTitle(newTitle)
Updates the display title shown in the tab bar for this panel.

**Kind**: instance method of [<code>Panel</code>](#Panel)

| Param | Type | Description |
| --- | --- | --- |
| newTitle | <code>string</code> | The new title to display. |

<a name="Panel+destroy"></a>

### panel.destroy()
Destroys the panel, removing it from the tab bar, internal maps, and the DOM.
After calling this, the Panel instance should not be reused.

**Kind**: instance method of [<code>Panel</code>](#Panel)
<a name="Panel+getPanelType"></a>

### panel.getPanelType() ⇒ <code>string</code>
gets the Panel's type

**Kind**: instance method of [<code>Panel</code>](#Panel)
<a name="_panelMap"></a>

## \_panelMap : <code>Object.&lt;string, Panel&gt;</code>
Maps panel ID to Panel instance

**Kind**: global variable
<a name="_$container"></a>

## \_$container : <code>jQueryObject</code>
The single container wrapping all bottom panels

**Kind**: global variable
<a name="_$tabBar"></a>

## \_$tabBar : <code>jQueryObject</code>
The tab bar inside the container

**Kind**: global variable
<a name="_$tabsOverflow"></a>

## \_$tabsOverflow : <code>jQueryObject</code>
Scrollable area holding the tab elements

**Kind**: global variable
<a name="_openIds"></a>

## \_openIds : <code>Array.&lt;string&gt;</code>
Ordered list of currently open (tabbed) panel IDs

**Kind**: global variable
<a name="_activeId"></a>

## \_activeId : <code>string</code> \| <code>null</code>
The panel ID of the currently visible (active) tab

**Kind**: global variable
<a name="EVENT_PANEL_HIDDEN"></a>

## EVENT\_PANEL\_HIDDEN : <code>string</code>
Expand All @@ -108,3 +166,30 @@ Event when panel is shown
type for bottom panel

**Kind**: global constant
<a name="init"></a>

## init($container, $tabBar, $tabsOverflow)
Initializes the PanelView module with references to the bottom panel container DOM elements.
Called by WorkspaceManager during htmlReady.

**Kind**: global function

| Param | Type | Description |
| --- | --- | --- |
| $container | <code>jQueryObject</code> | The bottom panel container element. |
| $tabBar | <code>jQueryObject</code> | The tab bar element inside the container. |
| $tabsOverflow | <code>jQueryObject</code> | The scrollable area holding tab elements. |

<a name="getOpenBottomPanelIDs"></a>

## getOpenBottomPanelIDs() ⇒ <code>Array.&lt;string&gt;</code>
Returns a copy of the currently open bottom panel IDs in tab order.

**Kind**: global function
<a name="hideAllOpenPanels"></a>

## hideAllOpenPanels() ⇒ <code>Array.&lt;string&gt;</code>
Hides every open bottom panel tab in a single batch

**Kind**: global function
**Returns**: <code>Array.&lt;string&gt;</code> - The IDs of panels that were open (useful for restoring later).
41 changes: 38 additions & 3 deletions docs/API-Reference/view/WorkspaceManager.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,14 @@ Events:
* [.PANEL_TYPE_BOTTOM_PANEL](#module_view/WorkspaceManager.PANEL_TYPE_BOTTOM_PANEL) : <code>string</code>
* [.PANEL_TYPE_PLUGIN_PANEL](#module_view/WorkspaceManager.PANEL_TYPE_PLUGIN_PANEL) : <code>string</code>
* _inner_
* [.$bottomPanelContainer](#module_view/WorkspaceManager..$bottomPanelContainer) : <code>jQueryObject</code>
* [.$statusBarPanelToggle](#module_view/WorkspaceManager..$statusBarPanelToggle) : <code>jQueryObject</code>
* [._statusBarToggleInProgress](#module_view/WorkspaceManager.._statusBarToggleInProgress) : <code>boolean</code>
* [.EVENT_WORKSPACE_UPDATE_LAYOUT](#module_view/WorkspaceManager..EVENT_WORKSPACE_UPDATE_LAYOUT)
* [.EVENT_WORKSPACE_PANEL_SHOWN](#module_view/WorkspaceManager..EVENT_WORKSPACE_PANEL_SHOWN)
* [.EVENT_WORKSPACE_PANEL_HIDDEN](#module_view/WorkspaceManager..EVENT_WORKSPACE_PANEL_HIDDEN)
* [.createBottomPanel(id, $panel, [minSize])](#module_view/WorkspaceManager..createBottomPanel) ⇒ <code>Panel</code>
* [.createBottomPanel(id, $panel, [minSize], [title])](#module_view/WorkspaceManager..createBottomPanel) ⇒ <code>Panel</code>
* [.destroyBottomPanel(id)](#module_view/WorkspaceManager..destroyBottomPanel)
* [.createPluginPanel(id, $panel, [minSize], $toolbarIcon, [initialSize])](#module_view/WorkspaceManager..createPluginPanel) ⇒ <code>Panel</code>
* [.getAllPanelIDs()](#module_view/WorkspaceManager..getAllPanelIDs) ⇒ <code>Array</code>
* [.getPanelForID(panelID)](#module_view/WorkspaceManager..getPanelForID) ⇒ <code>Object</code>
Expand All @@ -47,6 +51,24 @@ Constant representing the type of bottom panel
Constant representing the type of plugin panel

**Kind**: static property of [<code>view/WorkspaceManager</code>](#module_view/WorkspaceManager)
<a name="module_view/WorkspaceManager..$bottomPanelContainer"></a>

### view/WorkspaceManager.$bottomPanelContainer : <code>jQueryObject</code>
The single container wrapping all bottom panels

**Kind**: inner property of [<code>view/WorkspaceManager</code>](#module_view/WorkspaceManager)
<a name="module_view/WorkspaceManager..$statusBarPanelToggle"></a>

### view/WorkspaceManager.$statusBarPanelToggle : <code>jQueryObject</code>
Chevron toggle in the status bar

**Kind**: inner property of [<code>view/WorkspaceManager</code>](#module_view/WorkspaceManager)
<a name="module_view/WorkspaceManager.._statusBarToggleInProgress"></a>

### view/WorkspaceManager.\_statusBarToggleInProgress : <code>boolean</code>
True while the status bar toggle button is handling a click

**Kind**: inner property of [<code>view/WorkspaceManager</code>](#module_view/WorkspaceManager)
<a name="module_view/WorkspaceManager..EVENT_WORKSPACE_UPDATE_LAYOUT"></a>

### view/WorkspaceManager.EVENT\_WORKSPACE\_UPDATE\_LAYOUT
Expand All @@ -67,7 +89,7 @@ Event triggered when a panel is hidden.
**Kind**: inner constant of [<code>view/WorkspaceManager</code>](#module_view/WorkspaceManager)
<a name="module_view/WorkspaceManager..createBottomPanel"></a>

### view/WorkspaceManager.createBottomPanel(id, $panel, [minSize]) ⇒ <code>Panel</code>
### view/WorkspaceManager.createBottomPanel(id, $panel, [minSize], [title]) ⇒ <code>Panel</code>
Creates a new resizable panel beneath the editor area and above the status bar footer. Panel is initially invisible.
The panel's size & visibility are automatically saved & restored as a view-state preference.

Expand All @@ -77,7 +99,20 @@ The panel's size & visibility are automatically saved & restored as a view-state
| --- | --- | --- |
| id | <code>string</code> | Unique id for this panel. Use package-style naming, e.g. "myextension.feature.panelname" |
| $panel | <code>jQueryObject</code> | DOM content to use as the panel. Need not be in the document yet. Must have an id attribute, for use as a preferences key. |
| [minSize] | <code>number</code> | Minimum height of panel in px. |
| [minSize] | <code>number</code> | @deprecated No longer used. Pass `undefined`. |
| [title] | <code>string</code> | Display title shown in the bottom panel tab bar. |

<a name="module_view/WorkspaceManager..destroyBottomPanel"></a>

### view/WorkspaceManager.destroyBottomPanel(id)
Destroys a bottom panel, removing it from internal registries, the tab bar, and the DOM.
After calling this, the panel ID is no longer valid and the Panel instance should not be reused.

**Kind**: inner method of [<code>view/WorkspaceManager</code>](#module_view/WorkspaceManager)

| Param | Type | Description |
| --- | --- | --- |
| id | <code>string</code> | The panel ID that was passed to createBottomPanel. |

<a name="module_view/WorkspaceManager..createPluginPanel"></a>

Expand Down
1 change: 1 addition & 0 deletions src/brackets.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ define(function (require, exports, module) {
require("utils/NodeUtils");
require("utils/ColorUtils");
require("view/ThemeManager");
require("view/DefaultPanelView");
require("thirdparty/lodash");
require("language/XMLUtils");
require("language/JSONUtils");
Expand Down
3 changes: 3 additions & 0 deletions src/command/Commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,9 @@ define(function (require, exports, module) {
/** Toggles the git panel */
exports.CMD_GIT_TOGGLE_PANEL = "git-toggle-panel";

/** Toggles the custom snippets panel */
exports.CMD_CUSTOM_SNIPPETS_PANEL = "custom_snippets";

/** Goes to next git change */
exports.CMD_GIT_GOTO_NEXT_CHANGE = "git-gotoNextChange";

Expand Down
19 changes: 7 additions & 12 deletions src/extensions/default/DebugCommands/testBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ define(function (require, exports, module) {
function toggleTestBuilder() {
if(!$panel){
$panel = $(panelHTML);
builderPanel = WorkspaceManager.createBottomPanel("phcode-test-builder-panel", $panel, 100);
builderPanel = WorkspaceManager.createBottomPanel("phcode-test-builder-panel", $panel, 100, "Test Builder");
builderPanel.hide();
_setupPanel().then(()=>{
builderPanel.setVisible(!builderPanel.isVisible());
Expand All @@ -49,23 +49,19 @@ define(function (require, exports, module) {
}
const panelHTML = `
<div id="test-builder-panel-phcode" class="bottom-panel vert-resizable top-resizer">
<div class="toolbar" style="display: flex; justify-content: space-between;">
<div style="display: flex">
<div class="title">Test Builder</div>
<div class="toolbar" style="display: flex; justify-content: space-between; align-items: center; padding: 5px 8px;">
<div style="display: flex; gap: 4px;">
<button class="btn btn-mini no-focus save-test-builder">Save</button>
<button class="btn btn-mini primary no-focus run-test-builder">Run</button>
<button class="btn btn-mini no-focus run-selected">Run Selected</button>
</div>
<div>
<div style="display: flex; gap: 4px;">
<button class="btn btn-mini no-focus mark-validate" title="Validate marks at cursor">Marks</button>
<button class="btn btn-mini no-focus cursor-locate">cursor</button>
<button class="btn btn-mini no-focus text-validate" title="validate text" style="margin-right: 20px;">
Text</button>
<a href="#" class="close" style="right: 0;margin-right: 10px;">&times;</a>
</div>
<button class="btn btn-mini no-focus text-validate" title="validate text">Text</button>
</div>
</div>
<div style="display: flex; height: 100%; overflow: scroll;">
<!--27 px is status bar height. If this is not set, the preview code mirror editor gives weird layout issues at times-->
<div class="test_builder-editor" style="width: 100%; height: 100%;"></div>
</div>
</div>`;
Expand Down Expand Up @@ -161,7 +157,6 @@ define(function (require, exports, module) {
builderEditor && builderEditor.updateLayout();
}).observe($panel[0]);

$panel.find(".close").click(toggleTestBuilder);
$panel.find(".save-test-builder").click(saveFile);
$panel.find(".run-test-builder").click(()=>{
runTests();
Expand All @@ -177,7 +172,7 @@ define(function (require, exports, module) {
return;
}
$panel = $(panelHTML);
builderPanel = WorkspaceManager.createBottomPanel("phcode-test-builder-panel", $panel, 100);
builderPanel = WorkspaceManager.createBottomPanel("phcode-test-builder-panel", $panel, 100, "Test Builder");
builderPanel.hide();
_setupPanel();
});
Expand Down
16 changes: 13 additions & 3 deletions src/extensions/default/Git/src/Panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -1212,7 +1212,7 @@ define(function (require, exports) {
return;
}
const mainToolbarWidth = $mainToolbar.width();
let overFlowWidth = 565;
let overFlowWidth = 540;
const breakpoints = [
{ width: overFlowWidth, className: "hide-when-small" },
{ width: 400, className: "hide-when-x-small" }
Expand Down Expand Up @@ -1240,13 +1240,12 @@ define(function (require, exports) {
var $panelHtml = $(panelHtml);
$panelHtml.find(".git-available, .git-not-available").hide();

gitPanel = WorkspaceManager.createBottomPanel("main-git.panel", $panelHtml, 100);
gitPanel = WorkspaceManager.createBottomPanel("main-git.panel", $panelHtml, 100, Strings.GIT_PANEL_TITLE);
$gitPanel = gitPanel.$panel;
const resizeObserver = new ResizeObserver(_panelResized);
resizeObserver.observe($gitPanel[0]);
$mainToolbar = $gitPanel.find(".mainToolbar");
$gitPanel
.on("click", ".close", toggle)
.on("click", ".check-all", function () {
if ($(this).is(":checked")) {
return Git.stageAll().then(function () {
Expand Down Expand Up @@ -1502,6 +1501,17 @@ define(function (require, exports) {
handleGitCommit(lastCommitMessage[ProjectManager.getProjectRoot().fullPath], false, COMMIT_MODE.DEFAULT);
});

// When the panel tab is closed externally (e.g. via the × button),
// update the toolbar icon and menu checked state to stay in sync.
WorkspaceManager.on(WorkspaceManager.EVENT_WORKSPACE_PANEL_HIDDEN, function (event, panelID) {
if (panelID === "main-git.panel" && gitPanel) {
Main.$icon.toggleClass("on", false);
Main.$icon.toggleClass("selected-button", false);
CommandManager.get(Constants.CMD_GIT_TOGGLE_PANEL).setChecked(false);
Preferences.set("panelEnabled", false);
}
});

exports.init = init;
exports.refresh = refresh;
exports.toggle = toggle;
Expand Down
19 changes: 9 additions & 10 deletions src/extensions/default/Git/styles/git-styles.less
Original file line number Diff line number Diff line change
Expand Up @@ -1013,17 +1013,12 @@

.toolbar {
overflow: visible;
.close {
position: absolute;
top: 22px;
margin-top: -10px;
}
}
.git-more-options-btn {
position: absolute;
right: 25px;
top: 8px;
padding: 4px 8px 2px 8px;
right: 8px;
top: 5px;
padding: 4px 9px 2px 8px;
opacity: .7;
.dark & {
opacity: .5;
Expand Down Expand Up @@ -1070,7 +1065,11 @@
.btn-group {
line-height: 1;
button {
height: 26px;
height: 22px;
margin-top: 2px;
margin-bottom: 2px;
padding-top: 2px;
padding-bottom: 2px;
}
}
}
Expand All @@ -1086,7 +1085,7 @@
}
.git-right-icons {
position:absolute;
right: 55px;
right: 32px;
top: 5px;
}
.octicon:not(:only-child) {
Expand Down
Loading
Loading