Bug 1899336 - Position pinned tabs and new tab button for vertical tabs mode r=dao,sidebar-reviewers,desktop-theme-reviewers,tabbrowser-reviewers,kcochrane

* Create a new container to house pinned tabs, new tab button and non-pinned tabs
* Create new pinned tabs container to apply grid layout and overflow scrolling
* Update test coverage for pinned tabs for both horizontal and vertical tabs

Differential Revision: https://phabricator.services.mozilla.com/D215482
This commit is contained in:
Sarah Clements 2024-07-29 11:30:37 +00:00
parent 78c45e20c4
commit d4f7db068b
12 changed files with 466 additions and 65 deletions

View File

@ -5,8 +5,7 @@
<hbox flex="1" id="browser">
<box context="sidebar-context-menu" id="sidebar-main" hidden="true">
<html:sidebar-main flex="1">
<html:div id="vertical-tabs" slot="tabstrip">
</html:div>
<html:div id="vertical-tabs" slot="tabstrip"></html:div>
</html:sidebar-main>
</box>
<vbox id="sidebar-box" hidden="true" class="chromeclass-extrachrome">

View File

@ -5002,6 +5002,7 @@ const nodeToTooltipMap = {
"appMenu-zoomReduce-button2": "zoomReduce-button.tooltip",
"reader-mode-button": "reader-mode-button.tooltip",
"reader-mode-button-icon": "reader-mode-button.tooltip",
"vertical-tabs-newtab-button": "newTabButton.tooltip",
};
const nodeToShortcutMap = {
"bookmarks-menu-button": "manBookmarkKb",
@ -5021,6 +5022,7 @@ const nodeToShortcutMap = {
"appMenu-zoomReduce-button2": "key_fullZoomReduce",
"reader-mode-button": "key_toggleReaderMode",
"reader-mode-button-icon": "key_toggleReaderMode",
"vertical-tabs-newtab-button": "key_newNavigatorTab",
};
const gDynamicTooltipCache = new Map();

View File

@ -50,12 +50,22 @@
aria-multiselectable="true"
setfocus="false"
tooltip="tabbrowser-tab-tooltip"
orient="horizontal"
stopwatchid="FX_TAB_CLICK_MS">
<hbox class="tab-drop-indicator" hidden="true"/>
# If the name (tabbrowser-arrowscrollbox) or structure of this changes
# significantly, there is an optimization in
# DisplayPortUtils::MaybeCreateDisplayPortInFirstScrollFrameEncountered based
# the current structure that we may want to revisit.
<html:div id="vertical-pinned-tabs-container"></html:div>
<html:div id="newtab-button-container">
<toolbarbutton id="vertical-tabs-newtab-button"
class="toolbarbutton-1"
command="cmd_newNavigatorTab"
onclick="gBrowser.handleNewTabMiddleClick(this, event);"
tooltip="dynamic-shortcut-tooltip"
data-l10n-id="tabs-toolbar-new-tab"/>
</html:div>
<arrowscrollbox id="tabbrowser-arrowscrollbox" orient="horizontal" flex="1" style="min-width: 1px;" clicktoscroll="true" scrolledtostart="true" scrolledtoend="true">
<tab is="tabbrowser-tab" class="tabbrowser-tab" selected="true" visuallyselected="" fadein=""/>
<hbox id="tabbrowser-arrowscrollbox-periphery">

View File

@ -124,6 +124,7 @@
border-radius: 2px;
margin: -3px 2px 0;
#vertical-pinned-tabs-container &,
#tabbrowser-tabs[orient="vertical"] & {
height: 100%;
margin: 0 -2px;

View File

@ -245,6 +245,8 @@ skip-if = ["true"] #Bug 1455602
["browser_restore_tabless_window.js"]
["browser_restore_verticalPinnedTabs.js"]
["browser_restored_window_features.js"]
["browser_revive_crashed_bg_tabs.js"]

View File

@ -0,0 +1,72 @@
add_setup(() =>
SpecialPowers.pushPrefEnv({
set: [
["sidebar.revamp", true],
["sidebar.verticalTabs", true],
],
})
);
registerCleanupFunction(() => SpecialPowers.popPrefEnv());
let newState = {
windows: [
{
tabs: [
{
entries: [{ url: "https://example.com", triggeringPrincipal_base64 }],
pinned: "true",
hidden: "false",
},
{
entries: [{ url: "about:mozilla", triggeringPrincipal_base64 }],
pinned: "true",
hidden: "false",
},
{
entries: [{ url: "about:home", triggeringPrincipal_base64 }],
hidden: "false",
},
{
entries: [
{ url: "https://www.example.net/", triggeringPrincipal_base64 },
],
hidden: "false",
pinned: "true",
},
],
},
],
};
add_task(async function test_pinned_tabs_restored_position() {
let win = await BrowserTestUtils.openNewBrowserWindow();
await setWindowState(win, newState, true);
const { document } = win;
const sidebar = document.querySelector("sidebar-main");
ok(sidebar, "Sidebar is shown.");
let tabStrip = document.getElementById("tabbrowser-tabs");
let verticalTabs = document.querySelector("#vertical-tabs");
let verticalPinnedTabsContainer = document.querySelector(
"#vertical-pinned-tabs-container"
);
ok(BrowserTestUtils.isVisible(verticalTabs), "Vertical tabs slot is visible");
is(
tabStrip.parentNode,
verticalTabs,
"Tabstrip is slotted into the sidebar vertical tabs container"
);
ok(
BrowserTestUtils.isVisible(verticalPinnedTabsContainer),
"Vertical pinned tabs container is visible"
);
is(
verticalPinnedTabsContainer.children.length,
win.gBrowser._numPinnedTabs,
"Three tabs are in the vertical pinned tabs container"
);
await BrowserTestUtils.closeWindow(win);
});

View File

@ -246,7 +246,11 @@ var SidebarController = {
this._switcherPanel = document.getElementById("sidebarMenu-popup");
this._switcherTarget = document.getElementById("sidebar-switcher-target");
this._switcherArrow = document.getElementById("sidebar-switcher-arrow");
let newTabButton = document.getElementById("vertical-tabs-newtab-button");
newTabButton.addEventListener("command", event => {
BrowserCommands.openTab({ event });
});
if (
Services.prefs.getBoolPref(
"browser.tabs.allow_transparent_browser",
@ -1198,12 +1202,10 @@ var SidebarController = {
if (this.sidebarVerticalTabsEnabled) {
arrowScrollbox.setAttribute("orient", "vertical");
tabStrip.setAttribute("orient", "vertical");
tabStrip.removeAttribute("overflow");
tabStrip._positionPinnedTabs();
verticalTabs.append(tabStrip);
} else {
arrowScrollbox.setAttribute("orient", "horizontal");
tabStrip.removeAttribute("orient");
tabStrip.setAttribute("orient", "horizontal");
// make sure we put the tabstrip back in its original position in the TabsToolbar
if (tabstripPlacement < tabsToolbarWidgets.length) {
@ -1219,7 +1221,7 @@ var SidebarController = {
.append(tabStrip);
}
}
verticalTabs.toggleAttribute("activated", this.sidebarVerticalTabsEnabled);
verticalTabs.toggleAttribute("visible", this.sidebarVerticalTabsEnabled);
},
};

View File

@ -4,13 +4,14 @@
.wrapper {
display: grid;
grid-template-rows: auto 1fr;
grid-template-rows: auto min-content min-content;
box-sizing: border-box;
height: 100%;
min-width: 50px;
padding-inline-start: var(--space-medium);
padding: var(--space-small);
padding-inline-end: 0;
border-inline-end: 1px solid var(--chrome-content-separator-color);
background-color: var(--sidebar-background-color);
background-color: var(--toolbar-bgcolor);
color: var(--sidebar-text-color);
:host([positionend]) & {
border-inline-start: 1px solid var(--chrome-content-separator-color);
@ -21,8 +22,8 @@
.actions-list {
display: flex;
flex-direction: column;
justify-content: end;
gap: var(--space-xsmall);
justify-content: center;
padding-inline-start: var(--space-xsmall);
}
.expanded-button {
@ -34,3 +35,11 @@
justify-content: flex-start;
}
}
.tools-and-extensions {
align-self: start;
}
.bottom-actions {
align-self: end;
}

View File

@ -346,6 +346,12 @@
return (this.tabpanels = document.getElementById("tabbrowser-tabpanels"));
},
get verticalPinnedTabsContainer() {
return (this.verticalPinnedTabsContainer = document.getElementById(
"vertical-pinned-tabs-container"
));
},
addEventListener(...args) {
this.tabpanels.addEventListener(...args);
},
@ -841,7 +847,15 @@
}
this.showTab(aTab);
this.moveTabTo(aTab, this._numPinnedTabs);
if (this.tabContainer.inVerticalTabsMode) {
let wasFocused = document.activeElement == this.selectedTab;
let oldPosition = aTab._tPos;
this.tabContainer._invalidateCachedTabs();
this.verticalPinnedTabsContainer.appendChild(aTab);
this._updateAfterMoveTabTo(aTab, oldPosition, wasFocused);
} else {
this.moveTabTo(aTab, this._numPinnedTabs);
}
aTab.setAttribute("pinned", "true");
this._updateTabBarForPinnedTabs();
this._notifyPinnedStatus(aTab);
@ -852,8 +866,20 @@
return;
}
this.moveTabTo(aTab, this._numPinnedTabs - 1);
aTab.removeAttribute("pinned");
if (this.tabContainer.inVerticalTabsMode) {
let wasFocused = document.activeElement == this.selectedTab;
let oldPosition = aTab._tPos;
// we remove this attribute first, so that allTabs represents
// the moving of a tab from the vertical pinned tabs container
// and back into arrowscrollbox.
aTab.removeAttribute("pinned");
this.tabContainer._invalidateCachedTabs();
this.tabContainer.arrowScrollbox.prepend(aTab);
this._updateAfterMoveTabTo(aTab, oldPosition, wasFocused);
} else {
this.moveTabTo(aTab, this._numPinnedTabs - 1);
aTab.removeAttribute("pinned");
}
aTab.style.marginInlineStart = "";
aTab._pinnedUnscrollable = false;
this._updateTabBarForPinnedTabs();
@ -5286,11 +5312,24 @@
let wasFocused = document.activeElement == this.selectedTab;
aIndex = aIndex < aTab._tPos ? aIndex : aIndex + 1;
let neighbor = this.tabs[aIndex];
if (aIndex < aTab._tPos) {
neighbor.before(aTab);
} else if (!neighbor) {
// Put the tab after the neighbor, as once we remove the tab from its current position,
// the indexing of the tabs will shift.
aTab.parentElement.append(aTab);
} else {
neighbor.after(aTab);
}
let neighbor = this.tabs[aIndex] || null;
// We want to clear _allTabs after moving nodes because the order of
// vertical tabs may have changed.
this.tabContainer._invalidateCachedTabs();
this.tabContainer.insertBefore(aTab, neighbor);
this._updateAfterMoveTabTo(aTab, oldPosition, wasFocused);
},
_updateAfterMoveTabTo(aTab, oldPosition, wasFocused = null) {
this._updateTabsAfterInsert();
if (wasFocused) {
@ -5302,7 +5341,11 @@
if (aTab.pinned) {
this.tabContainer._positionPinnedTabs();
}
// Pinning and unpinning vertical tabs bypasses moveTabTo,
// so we still want to check whether its worth dispatching an event
if (oldPosition == aTab._tPos) {
return;
}
var evt = document.createEvent("UIEvents");
evt.initUIEvent("TabMove", true, false, window, oldPosition);
aTab.dispatchEvent(evt);

View File

@ -12,6 +12,7 @@
const TAB_PREVIEW_PREF = "browser.tabs.hoverPreview.enabled";
class MozTabbrowserTabs extends MozElements.TabsBase {
static observedAttributes = ["orient"];
constructor() {
super();
@ -143,6 +144,19 @@
this._previewPanel = null;
}
attributeChangedCallback(name, oldValue, newValue) {
if (name != "orient") {
return;
}
if (oldValue == "vertical" && newValue == "horizontal") {
this._resetVerticalPinnedTabs();
}
this._positionPinnedTabs();
super.attributeChangedCallback(name, oldValue, newValue);
}
on_TabSelect() {
this._handleTabSelect();
}
@ -1130,16 +1144,26 @@
if (this._allTabs) {
return this._allTabs;
}
let verticalPinnedTabsContainer = document.getElementById(
"vertical-pinned-tabs-container"
);
let children = Array.from(this.arrowScrollbox.children);
// remove arrowScrollbox periphery element
children.pop();
this._allTabs = children;
return children;
let allChildren = [...verticalPinnedTabsContainer.children, ...children];
this._allTabs = allChildren;
return allChildren;
}
get previewPanel() {
return this._previewPanel;
}
get verticalMode() {
return this.getAttribute("orient") == "vertical";
}
_getVisibleTabs() {
if (!this._visibleTabs) {
this._visibleTabs = Array.prototype.filter.call(
@ -1173,7 +1197,8 @@
// We have a container for non-tab elements at the end of the scrollbox.
node = arrowScrollbox.lastChild;
}
return arrowScrollbox.insertBefore(tab, node);
return node.before(tab);
}
set _tabMinWidth(val) {
@ -1494,18 +1519,57 @@
this._handleTabSelect(true);
}
_updateVerticalPinnedTabs() {
// Move pinned tabs to another container when the tabstrip is toggled to vertical
// and when session restore code calls _positionPinnedTabs; update styling whenever
// the number of pinned tabs changes.
let verticalTabsContainer = document.getElementById(
"vertical-pinned-tabs-container"
);
let newTabButton = document.getElementById("newtab-button-container");
let numPinned = gBrowser._numPinnedTabs;
if (gBrowser._numPinnedTabs !== verticalTabsContainer.children.length) {
let tabs = this._getVisibleTabs();
for (let i = 0; i < numPinned; i++) {
tabs[i].style.marginInlineStart = "";
verticalTabsContainer.appendChild(tabs[i]);
}
}
newTabButton.toggleAttribute("showborder", gBrowser._numPinnedTabs !== 0);
this.style.removeProperty("--tab-overflow-pinned-tabs-width");
}
_resetVerticalPinnedTabs() {
let verticalTabsContainer = document.getElementById(
"vertical-pinned-tabs-container"
);
if (!verticalTabsContainer.children.length) {
return;
}
for (const child of Array.from(
verticalTabsContainer.children
).reverse()) {
this.arrowScrollbox.prepend(child);
}
}
_positionPinnedTabs() {
let tabs = this._getVisibleTabs();
let numPinned = gBrowser._numPinnedTabs;
let doPosition =
let absPositionHorizontalTabs =
this.hasAttribute("overflow") &&
tabs.length > numPinned &&
numPinned > 0;
this.toggleAttribute("haspinnedtabs", !!numPinned);
this.toggleAttribute("positionpinnedtabs", doPosition);
this.toggleAttribute("positionpinnedtabs", absPositionHorizontalTabs);
if (doPosition) {
if (this.verticalMode) {
this._updateVerticalPinnedTabs();
} else if (absPositionHorizontalTabs) {
let layoutData = this._pinnedTabsLayoutCache;
let uiDensity = document.documentElement.getAttribute("uidensity");
if (!layoutData || layoutData.uiDensity != uiDensity) {

View File

@ -1,7 +1,17 @@
add_setup(() =>
SpecialPowers.pushPrefEnv({
set: [
["sidebar.revamp", true],
["sidebar.verticalTabs", false],
],
})
);
registerCleanupFunction(() => SpecialPowers.popPrefEnv());
var tabs;
var tabbrowser;
function index(tab) {
return Array.prototype.indexOf.call(gBrowser.tabs, tab);
return Array.prototype.indexOf.call(tabbrowser.tabs, tab);
}
function indexTest(tab, expectedIndex, msg) {
@ -24,7 +34,7 @@ function PinUnpinHandler(tab, eventName) {
},
{ capture: true, once: true }
);
gBrowser.tabContainer.addEventListener(
tabbrowser.tabContainer.addEventListener(
eventName,
function (e) {
if (e.originalTarget == tab) {
@ -35,12 +45,15 @@ function PinUnpinHandler(tab, eventName) {
);
}
function test() {
add_task(async function test_pinned_horizontal_tabs() {
const win = await BrowserTestUtils.openNewBrowserWindow();
tabbrowser = win.gBrowser;
tabs = [
gBrowser.selectedTab,
BrowserTestUtils.addTab(gBrowser),
BrowserTestUtils.addTab(gBrowser),
BrowserTestUtils.addTab(gBrowser),
tabbrowser.selectedTab,
BrowserTestUtils.addTab(tabbrowser, "about:blank"),
BrowserTestUtils.addTab(tabbrowser, "about:mozilla"),
BrowserTestUtils.addTab(tabbrowser, "about:home"),
];
indexTest(0, 0);
indexTest(1, 1);
@ -49,10 +62,10 @@ function test() {
// Discard one of the test tabs to verify that pinning/unpinning
// discarded tabs does not regress (regression test for Bug 1852391).
gBrowser.discardBrowser(tabs[1], true);
tabbrowser.discardBrowser(tabs[1], true);
var eh = new PinUnpinHandler(tabs[3], "TabPinned");
gBrowser.pinTab(tabs[3]);
tabbrowser.pinTab(tabs[3]);
is(eh.eventCount, 2, "TabPinned event should be fired");
indexTest(0, 1);
indexTest(1, 2);
@ -60,21 +73,21 @@ function test() {
indexTest(3, 0);
eh = new PinUnpinHandler(tabs[1], "TabPinned");
gBrowser.pinTab(tabs[1]);
tabbrowser.pinTab(tabs[1]);
is(eh.eventCount, 2, "TabPinned event should be fired");
indexTest(0, 2);
indexTest(1, 1);
indexTest(2, 3);
indexTest(3, 0);
gBrowser.moveTabTo(tabs[3], 3);
tabbrowser.moveTabTo(tabs[3], 3);
indexTest(3, 1, "shouldn't be able to mix a pinned tab into normal tabs");
gBrowser.moveTabTo(tabs[2], 0);
tabbrowser.moveTabTo(tabs[2], 0);
indexTest(2, 2, "shouldn't be able to mix a normal tab into pinned tabs");
eh = new PinUnpinHandler(tabs[1], "TabUnpinned");
gBrowser.unpinTab(tabs[1]);
tabbrowser.unpinTab(tabs[1]);
is(eh.eventCount, 2, "TabUnpinned event should be fired");
indexTest(
1,
@ -82,16 +95,111 @@ function test() {
"unpinning a tab should move a tab to the start of normal tabs"
);
eh = new PinUnpinHandler(tabs[3], "TabUnpinned");
gBrowser.unpinTab(tabs[3]);
is(eh.eventCount, 2, "TabUnpinned event should be fired");
const { document } = win;
const sidebar = document.querySelector("sidebar-main");
ok(sidebar, "Sidebar is shown.");
let tabStrip = tabbrowser.tabContainer;
let verticalTabs = document.querySelector("#vertical-tabs");
let verticalPinnedTabsContainer = document.querySelector(
"#vertical-pinned-tabs-container"
);
is(tabbrowser._numPinnedTabs, 1, "One tab is pinned in horizontal tabstrip");
ok(tabs[3].pinned, "Third tab is pinned");
// flip the pref to move the tabstrip into the sidebar
await SpecialPowers.pushPrefEnv({ set: [["sidebar.verticalTabs", true]] });
ok(BrowserTestUtils.isVisible(verticalTabs), "Vertical tabs slot is visible");
is(
tabStrip.parentNode,
verticalTabs,
"Tabstrip is slotted into the sidebar vertical tabs container"
);
ok(
BrowserTestUtils.isVisible(verticalPinnedTabsContainer),
"Vertical pinned tabs container is visible"
);
is(
verticalPinnedTabsContainer.children.length,
1,
"One tab is pinned in vertical pinned tabs container"
);
is(tabbrowser._numPinnedTabs, 1, "One tab is pinned in global tabstrip");
tabbrowser.pinTab(tabs[1]);
is(
verticalPinnedTabsContainer.children.length,
2,
"Two tabs are pinned in the vertical pinned tabs container"
);
is(tabbrowser._numPinnedTabs, 2, "Two tabs are pinned in global tabstrip");
indexTest(
1,
1,
"unpinning a tab should move a tab to the start of normal tabs"
);
indexTest(3, 0, "about:home is the first pinned tab");
indexTest(1, 1, "about:blank is the second pinned tab");
await BrowserTestUtils.switchTab(tabbrowser, tabs[1]);
is(tabbrowser.selectedTab, tabs[1], "about:blank is the selected tab");
tabbrowser.moveTabToStart();
indexTest(1, 0, "about:blank is now the first pinned tab");
indexTest(3, 1, "about:home is now the second pinned tab");
is(
verticalPinnedTabsContainer.children[0],
tabs[1],
"about:blank is the first tab in the pinned tabs container"
);
tabbrowser.pinTab(tabs[2]);
indexTest(1, 0, "about:blank is now the first pinned tab");
indexTest(2, 2, "about:mozilla is now the third pinned tab");
indexTest(3, 1, "about:home is now the second pinned tab");
await BrowserTestUtils.switchTab(tabbrowser, tabs[3]);
is(tabbrowser.selectedTab, tabs[3], "about:home is the selected tab");
tabbrowser.moveTabToEnd();
indexTest(1, 0, "about:blank is now the first pinned tab");
indexTest(2, 1, "about:mozilla is now the second pinned tab");
indexTest(3, 2, "about:home is now the third pinned tab");
tabbrowser.moveTabTo(tabs[1], 1);
indexTest(1, 1, "about:blank is now the second pinned tab");
indexTest(2, 0, "about:mozilla is now the first pinned tab");
indexTest(3, 2, "about:home is now the third pinned tab");
is(
verticalPinnedTabsContainer.children[2],
tabs[3],
"about:home is the last tab in the pinned tabs container"
);
// flip the pref to move the tabstrip back into original location
await SpecialPowers.pushPrefEnv({ set: [["sidebar.verticalTabs", false]] });
await TestUtils.waitForCondition(
() => !verticalPinnedTabsContainer.children.length,
"Pinned tabs are no longer in vertical pinned tabs container"
);
is(
tabbrowser._numPinnedTabs,
3,
0,
"unpinning a tab should move a tab to the start of normal tabs"
"One tab is still pinned in global tabstrip"
);
indexTest(1, 1, "about:blank is still the second pinned tab");
indexTest(2, 0, "about:mozilla is still the first pinned tab");
indexTest(3, 2, "about:home is still the third pinned tab");
indexTest(0, 3, "initial tab is still the last tab");
gBrowser.removeTab(tabs[1]);
gBrowser.removeTab(tabs[2]);
gBrowser.removeTab(tabs[3]);
}
await BrowserTestUtils.closeWindow(win);
});

View File

@ -12,12 +12,13 @@
&[uidensity=touch] {
--tab-min-height: 41px;
}
--collapsed-tab-width: 40px;
--inline-tab-padding: 8px;
--tab-border-radius: 4px;
--tab-shadow-max-size: 6px;
--tab-block-margin: 4px;
--tab-loading-fill: #0A84FF;
--tab-hover-background-color: color-mix(in srgb, currentColor 11%, transparent);
--tab-selected-textcolor: var(--toolbar-color);
--tab-selected-bgcolor: var(--toolbar-bgcolor);
--tab-selected-color-scheme: var(--toolbar-color-scheme);
@ -579,7 +580,7 @@
/* Selected tab and tab hover */
.tabbrowser-tab:hover > .tab-stack > .tab-background:not([selected], [multiselected]) {
background-color: color-mix(in srgb, currentColor 11%, transparent);
background-color: var(--tab-hover-background-color);
outline-color: var(--tab-hover-outline-color);
}
@ -639,14 +640,8 @@
}
}
#tabbrowser-tabs[haspinnedtabs]:not([positionpinnedtabs]) > #tabbrowser-arrowscrollbox {
/* Add a gap between the last pinned tab and the first visible tab */
&:not([orient="vertical"]) > .tabbrowser-tab:nth-child(1 of :not([pinned], [hidden])) {
margin-inline-start: 12px;
}
&[orient="vertical"] > .tabbrowser-tab:nth-child(1 of :not([pinned], [hidden])) {
margin-block-start: 12px;
}
#tabbrowser-tabs[haspinnedtabs]:not([positionpinnedtabs]):not([orient="vertical"]) > #tabbrowser-arrowscrollbox > .tabbrowser-tab:nth-child(1 of :not([pinned], [hidden])) {
margin-inline-start: 12px;
}
.tab-label[attention]:not([selected]) {
@ -746,6 +741,7 @@
&::part(scrollbox) {
scrollbar-width: thin;
overflow-y: auto;
padding-inline-end: 0;
}
&[overflowing="true"]:not([scrolledtoend="true"]) {
@ -757,26 +753,117 @@
border-bottom: 1px solid color-mix(in srgb, currentColor 25%, transparent);
}
#vertical-tabs {
overflow-y: hidden;
display: none;
#vertical-tabs-newtab-button {
display: flex;
height: var(--tab-min-height);
border-radius: var(--border-radius-medium);
padding: 0 var(--space-small);
&[activated] {
display: flex;
&:hover {
background-color: var(--tab-hover-background-color);
}
> .toolbarbutton-text {
text-align: start;
padding-inline-start: var(--space-small);
}
}
sidebar-main:not([expanded]) > #vertical-tabs > #tabbrowser-tabs[orient="vertical"] .tabbrowser-tab {
/* TODO look into handlings this by setting --tab-min-width in tabs.js in bug 1899336. */
min-width: inherit;
width: inherit;
width: var(--collapsed-tab-width);
}
sidebar-main:not([expanded]) > #vertical-tabs > #tabbrowser-tabs[orient="vertical"] .tab-close-button,
sidebar-main[expanded] > #vertical-tabs > #tabbrowser-tabs[orient="vertical"] .tab-close-button:not([selected]) {
#newtab-button-container {
display: none;
}
#vertical-tabs {
overflow: hidden;
display: none;
&[visible] {
display: flex;
/* make the scrollbars hug the side of the container */
margin-inline-end: -2px;
}
}
#vertical-pinned-tabs-container {
display: none;
.tab-label-container {
display: none;
}
.tab-background {
border-radius: var(--border-radius-medium);
&:not([selected], [multiselected]) {
background-color: color-mix(in srgb, currentColor 7%, transparent);
}
}
}
#tabbrowser-tabs[orient="vertical"] {
overflow: hidden;
display: grid;
align-content: flex-start;
grid-gap: var(--space-small);
.tab-close-button {
display: none;
}
.tab-content {
align-content: center;
}
.tab-background {
border-radius: var(--border-radius-medium);
}
#newtab-button-container {
display: flex;
border-top: 0;
margin-inline-end: var(--space-medium);
font-size: var(--urlbarView-small-font-size);
flex-direction: column;
padding-top: var(--space-small);
&[showborder] {
border-top: 1px solid color-mix(in srgb, currentColor 25%, transparent);
}
sidebar-main:not([expanded]) & {
.toolbarbutton-text {
display: none;
}
}
}
#vertical-pinned-tabs-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(var(--collapsed-tab-width), auto));
overflow-y: auto;
overflow-x: hidden;
scrollbar-width: thin;
/* Fit slightly more than 5 tabs + padding before overflowing */
max-height: 244px;
column-gap: 4px;
padding-inline-end: var(--space-medium);
}
}
sidebar-main[expanded] #tabbrowser-tabs[orient="vertical"] #newtab-button-container {
border-top: 0;
}
sidebar-main:not([expanded]) {
.tab-label-container {
display: none;
}
}
sidebar-main[expanded] > #vertical-tabs > #tabbrowser-tabs[orient="vertical"] > #tabbrowser-arrowscrollbox > .tabbrowser-tab:is(:hover, [selected]) .tab-close-button {
display: flex;
}
/* Tab drag and drop */
.tab-drop-indicator {
@ -844,11 +931,13 @@ toolbar:not(#TabsToolbar) #firefox-view-button {
/* New tab button */
#tabs-newtab-button,
#vertical-tabs-newtab-button,
#TabsToolbar #new-tab-button {
list-style-image: url(chrome://global/skin/icons/plus.svg);
}
#tabbrowser-tabs[hasadjacentnewtabbutton]:not([overflow]) ~ #new-tab-button,
#tabbrowser-tabs[orient="vertical"] > #tabbrowser-arrowscrollbox > #tabbrowser-arrowscrollbox-periphery > #tabs-newtab-button,
#tabbrowser-tabs[overflow] > #tabbrowser-arrowscrollbox > #tabbrowser-arrowscrollbox-periphery > #tabs-newtab-button,
#tabbrowser-tabs:not([hasadjacentnewtabbutton]) > #tabbrowser-arrowscrollbox > #tabbrowser-arrowscrollbox-periphery > #tabs-newtab-button,
#TabsToolbar[customizing] #tabs-newtab-button {