Skip to content

Commit fd94e00

Browse files
committed
Bug 1971382 - allow dropping tabs into collapsed tab groups r=jswinarton,dao,desktop-theme-reviewers,tabbrowser-reviewers
Dragging a tab(s) and hovering it over a collapsed tab group label for a short duration will highlight the dragged tab(s) and the collapsed tab group label in order to indicate that dropping the tab(s) will put it into the group. Since the dragged tab is always the active tab, dropping the moving tab(s) into the collapsed tab group will cause the collapsed tab group to enter the "collapsed-but-with-active-tab" state. If the active tab is in a collapsed tab group and you try to drag it, dropping the tab right away will drop it after the tab group. In order to "cancel" the operation and return the active tab to its prior position in the collapsed tab group, the user should drag the active tab back over the tab group label and hover over it until it highlights. This patch leverages the approach of the "create group" functionality + visuals when hovering an ungrouped tab(s) over another. I made the functionality + visuals a bit more generic by referring to it as "grouping" behavior. If tab group A is collapsed and contains the active tab, and if the user starts dragging tab group B, then the "overflow counter" of tab group A will disappear for the duration of the drag operation. It would be possible to keep that element visible, but it would require opting that element into all of the drag-drop animation logic. That's too large of a change to include in this patch. Tab selection/tab activation can now cause a tab to appear or disappear if it's in a collapsed tab group, so the <tabs> element's cache of visible tab strip items needs to be updated if that happens. Differential Revision: https://phabricator.services.mozilla.com/D256745
1 parent 062a426 commit fd94e00

File tree

6 files changed

+315
-99
lines changed

6 files changed

+315
-99
lines changed

browser/components/tabbrowser/content/tab.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282
static get inheritedAttributes() {
8383
return {
8484
".tab-background":
85-
"selected=visuallyselected,fadein,multiselected,dragover-createGroup",
85+
"selected=visuallyselected,fadein,multiselected,dragover-groupTarget",
8686
".tab-group-line": "selected=visuallyselected,multiselected",
8787
".tab-loading-burst": "pinned,bursting,notselectedsinceload",
8888
".tab-content":
@@ -225,7 +225,9 @@
225225

226226
get visible() {
227227
return (
228-
this.isOpen && !this.hidden && (!this.group?.collapsed || this.selected)
228+
this.isOpen &&
229+
!this.hidden &&
230+
(!this.group || this.group.isTabVisibleInGroup(this))
229231
);
230232
}
231233

browser/components/tabbrowser/content/tabbrowser.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@
184184
window.addEventListener("framefocusrequested", this);
185185
window.addEventListener("activate", this);
186186
window.addEventListener("deactivate", this);
187+
window.addEventListener("TabGroupCollapse", this);
187188
window.addEventListener("TabGroupCreateByUser", this);
188189
window.addEventListener("TabGrouped", this);
189190
window.addEventListener("TabUngrouped", this);
@@ -7244,6 +7245,11 @@
72447245
}
72457246
break;
72467247
}
7248+
case "TabGroupCollapse":
7249+
aEvent.target.tabs.forEach(tab => {
7250+
this.removeFromMultiSelectedTabs(tab);
7251+
});
7252+
break;
72477253
case "TabGroupCreateByUser":
72487254
this.tabGroupMenu.openCreateModal(aEvent.target);
72497255
break;

browser/components/tabbrowser/content/tabgroup.js

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,16 +160,18 @@
160160
} else {
161161
let tabs = this.tabs;
162162
let tabCount = tabs.length;
163+
let hasActiveTab = false;
163164
tabs.forEach((tab, index) => {
164165
if (tab.selected) {
165-
this.hasActiveTab = true;
166+
hasActiveTab = true;
166167
}
167168

168169
// Renumber tabs so that a11y tools can tell users that a given
169170
// tab is "2 of 7" in the group, for example.
170171
tab.setAttribute("aria-posinset", index + 1);
171172
tab.setAttribute("aria-setsize", tabCount);
172173
});
174+
this.hasActiveTab = hasActiveTab;
173175

174176
// When a group containing the active tab is collapsed,
175177
// the overflow count displays the number of additional tabs
@@ -257,10 +259,16 @@
257259
this.setAttribute("id", val);
258260
}
259261

262+
/**
263+
* @returns {boolean}
264+
*/
260265
get hasActiveTab() {
261266
return this.hasAttribute("hasactivetab");
262267
}
263268

269+
/**
270+
* @param {boolean} val
271+
*/
264272
set hasActiveTab(val) {
265273
this.toggleAttribute("hasactivetab", val);
266274
}
@@ -370,10 +378,27 @@
370378
}
371379
}
372380

381+
/**
382+
* @returns {MozTabbrowserTab[]}
383+
*/
373384
get tabs() {
374385
return Array.from(this.children).filter(node => node.matches("tab"));
375386
}
376387

388+
/**
389+
* @param {MozTabbrowserTab} tab
390+
* @returns {boolean}
391+
*/
392+
isTabVisibleInGroup(tab) {
393+
if (this.isBeingDragged) {
394+
return false;
395+
}
396+
if (this.collapsed && !tab.selected) {
397+
return false;
398+
}
399+
return true;
400+
}
401+
377402
/**
378403
* @returns {MozTextLabel}
379404
*/
@@ -392,6 +417,20 @@
392417
this.#wasCreatedByAdoption = value;
393418
}
394419

420+
/**
421+
* @returns {boolean}
422+
*/
423+
get isBeingDragged() {
424+
return this.hasAttribute("movingtabgroup");
425+
}
426+
427+
/**
428+
* @param {boolean} val
429+
*/
430+
set isBeingDragged(val) {
431+
this.toggleAttribute("movingtabgroup", val);
432+
}
433+
395434
/**
396435
* add tabs to the group
397436
*
@@ -502,6 +541,9 @@
502541
}
503542
}
504543

544+
/**
545+
* @param {CustomEvent} event
546+
*/
505547
on_TabSelect(event) {
506548
const { previousTab } = event.detail;
507549
this.hasActiveTab = event.target.group === this;

0 commit comments

Comments
 (0)