Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
f9de68b
feat: tabbed bottom panel initial architecture
devvaannsh Feb 17, 2026
5a62408
feat: improve bottom panel tab bar styling
devvaannsh Feb 17, 2026
d6a5ef7
feat: remove redundant box shadow color between panel and tabbar
devvaannsh Feb 17, 2026
6bf2d5c
refactor: reduce height of active tab styling
devvaannsh Feb 17, 2026
1ffd6e8
feat: better support for bottom panel tab bar title
devvaannsh Feb 17, 2026
753c9f4
feat: better support for tab naming using dom lookup
devvaannsh Feb 17, 2026
ebf500b
feat: prevent full tab bar dom rebuild on panel switch
devvaannsh Feb 17, 2026
a67bbf3
feat: deprecate min size param from bottom panel
devvaannsh Feb 17, 2026
4a7882f
refactor: improve bottom panel tab bar styling
devvaannsh Feb 17, 2026
8851d5e
fix: redundant duplicated jsdoc
devvaannsh Feb 18, 2026
8af9e92
feat: add single close button that hides panel
devvaannsh Feb 18, 2026
1f5679a
feat: hide the bottom panel and don’t destroy any active ones
devvaannsh Feb 18, 2026
b3571de
feat: add button to toggle the bottom panel via status bar
devvaannsh Feb 18, 2026
5405545
feat: animate buttons when panel toggles its state via non status bar…
devvaannsh Feb 18, 2026
35d5266
refactor: better styling for the hide panel button in bottom panel ta…
devvaannsh Feb 18, 2026
86c5bfc
chore: localize the strings
devvaannsh Feb 18, 2026
0a4e172
fix: some panel content getting cut off and not taking full available…
devvaannsh Feb 18, 2026
6ecac2f
refactor: update shortcuts panel styles to make it consistent with th…
devvaannsh Feb 18, 2026
1a4bf1a
refactor: update custom snippets style as per new tabbed panel archit…
devvaannsh Feb 18, 2026
fecf018
feat: update git panel styles to fit new architecture
devvaannsh Feb 18, 2026
fbaae46
feat: update problems panel style to match new architecture
devvaannsh Feb 18, 2026
9c87a57
feat: update test builder styles
devvaannsh Feb 18, 2026
0bbab6c
feat: update search panel styles
devvaannsh Feb 18, 2026
14355d6
feat: move the tabbed bottom panel logic to panel view
devvaannsh Feb 19, 2026
4f83cc6
feat: set title and attribute using the functions
devvaannsh Feb 19, 2026
6ee8c91
refactor: set title and attr using functions
devvaannsh Feb 19, 2026
28da722
fix: escape key destroying non-visible panels
devvaannsh Feb 19, 2026
2cc59f3
feat: update the title only on setTitle instead of full dom rebuild
devvaannsh Feb 19, 2026
a1dc184
feat: hide all open bottom panels at once instead of closing them ind…
devvaannsh Feb 19, 2026
c2abcf5
fix: event shown event not firing
devvaannsh Feb 19, 2026
b9cfb18
feat: remove snippets count tracking from the title
devvaannsh Feb 19, 2026
7a5649b
fix: git more options button appearing at incorrect position due to r…
devvaannsh Feb 19, 2026
b2e3442
feat: open quick access panel when on other panel is opened
devvaannsh Feb 19, 2026
2ca44a2
feat: remove read more from the quick access panel for better accessi…
devvaannsh Feb 19, 2026
a21f3d3
feat: show no results page when no results match in find in files
devvaannsh Feb 19, 2026
d568078
feat: only show no results page when modal has valid query
devvaannsh Feb 19, 2026
601493a
feat: escape key hides the bottom panel instead of destroying a panel
devvaannsh Feb 19, 2026
e60d3db
fix: checkmark/active indicators not getting removed when tab is closed
devvaannsh Feb 19, 2026
512c33b
feat: only show the buttons available in the quick access panel
devvaannsh Feb 19, 2026
ca1f83c
fix: find in files buttons getting misplaced with empty input boxes
devvaannsh Feb 20, 2026
4b77406
feat: add singular add/destroy panel functions to prevent whole DOM r…
devvaannsh Feb 20, 2026
361bac6
refactor: show the add snippets button on the centre of the panel
devvaannsh Feb 20, 2026
1364d8c
chore: auto update API docs
devvaannsh Feb 20, 2026
399a408
fix: file filters integ tests failing
devvaannsh Feb 20, 2026
a686d14
feat: dont auto show problems panel
devvaannsh Feb 21, 2026
37b854e
fix: always show problems panel option in the quick access as it show…
devvaannsh Feb 21, 2026
f67c823
fix: code inspection jshint eslint integ tests failing
devvaannsh Feb 21, 2026
f0d5b28
feat: jshint integ tests failing when run individually
devvaannsh Feb 21, 2026
54967a4
chore: auto update api docs
devvaannsh Feb 21, 2026
b3336c9
fix: code inspection legacy integ tests failing
devvaannsh Feb 21, 2026
ce2b9fd
feat: add support to maximize/restore bottom panel window
devvaannsh Feb 21, 2026
4a0fe49
refactor: add expand and compress icons
devvaannsh Feb 21, 2026
02c107b
refactor: better styling for bottom panel tab bar action buttons
devvaannsh Feb 21, 2026
5fcdb34
feat: better resize handling support for maximize and restore option
devvaannsh Feb 21, 2026
9cb8882
fix: find in files legacy integ tests failing
devvaannsh Feb 21, 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
14 changes: 14 additions & 0 deletions docs/API-Reference/document/Document.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const Document = brackets.getModule("document/Document")
* [.replaceRange(text, start, end, origin)](#Document+replaceRange)
* [.getRange(start, end)](#Document+getRange) ⇒ <code>string</code>
* [.getLine(Zero-based)](#Document+getLine) ⇒ <code>string</code>
* [.posFromIndex(index)](#Document+posFromIndex) ⇒ <code>Object</code>
* [.batchOperation(doOperation)](#Document+batchOperation)
* [.notifySaved()](#Document+notifySaved)
* [.adjustPosForChange(pos, textLines, start, end)](#Document+adjustPosForChange) ⇒ <code>Object</code>
Expand Down Expand Up @@ -240,6 +241,19 @@ Returns the text of the given line (excluding any line ending characters)
| --- | --- | --- |
| Zero-based | <code>number</code> | line number |

<a name="Document+posFromIndex"></a>

### document.posFromIndex(index) ⇒ <code>Object</code>
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)

| Param | Type | Description |
| --- | --- | --- |
| index | <code>number</code> | Zero-based character offset |

<a name="Document+batchOperation"></a>

### document.batchOperation(doOperation)
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
Loading
Loading