diff --git a/browser/components/tabbrowser/content/tabgroup.js b/browser/components/tabbrowser/content/tabgroup.js
index 65c89aab0902cb33ad33fc523d3e0b954618778e..b42298457fdd2f8df6ff202c804122ffc999d409 100644
--- a/browser/components/tabbrowser/content/tabgroup.js
+++ b/browser/components/tabbrowser/content/tabgroup.js
@@ -14,11 +14,11 @@
   class MozTabbrowserTabGroup extends MozXULElement {
     static markup = `
       <vbox class="tab-group-label-container" pack="center">
-        <vbox class="tab-group-label-hover-highlight" pack="center">
           <label class="tab-group-label" role="button" />
-        </vbox>
       </vbox>
-      <html:slot/>
+      <html:div class="tab-group-container">
+        <html:div class="zen-tab-group-start"/>
+      </html:div>
       <vbox class="tab-group-overflow-count-container" pack="center">
         <label class="tab-group-overflow-count" role="button" />
       </vbox>
@@ -71,21 +71,37 @@
     }
 
     connectedCallback() {
+      if (this._lastGroup && this._lastGroup !== this.group) {
+        this._lastGroup.dispatchEvent(
+          new CustomEvent("FolderUngrouped", {
+            bubbles: true,
+            detail: this,
+          })
+        );
+      }
+      if (this.group && this._lastGroup != this.group) {
+        this._lastGroup = this.group;
+        this.group.dispatchEvent(
+          new CustomEvent("FolderGrouped", {
+            bubbles: true,
+            detail: this,
+          })
+        );
+      } else if (!this.group) {
+        this._lastGroup = null;
+      }
       // Always set the mutation observer to listen for tab change events, even
       // if we are already initialized.
       // This is needed to ensure events continue to fire even if the tab group is
       // moved from the horizontal to vertical tab layout or vice-versa, which
       // causes the component to be repositioned in the DOM.
-      this.#observeTabChanges();
 
       // Similar to above, always set up TabSelect listener, as this gets
       // removed in disconnectedCallback
       this.ownerGlobal.addEventListener("TabSelect", this);
       this.addEventListener("SplitViewTabChange", this);
 
-      if (this._initialized) {
-        return;
-      }
+      if (!this._initialized) {
 
       this._initialized = true;
       this.saveOnWindowClose = true;
@@ -112,11 +128,14 @@
 
       this.#labelContainerElement.addEventListener("mouseover", this);
       this.#labelContainerElement.addEventListener("mouseout", this);
-      this.#labelElement.addEventListener("contextmenu", e => {
-        e.preventDefault();
-        gBrowser.tabGroupMenu.openEditModal(this);
-        return false;
-      });
+      this.appendChild = function (child) {
+        this.groupContainer.appendChild(child);
+        for (let tab of this.tabs) {
+          if (tab.hasAttribute("zen-empty-tab") && tab.group === this) {
+            this.groupStartElement.after(tab);
+          }
+        }
+      };
 
       this.#updateLabelAriaAttributes();
 
@@ -130,17 +149,21 @@
       let tabGroupCreateDetail = this.#wasCreatedByAdoption
         ? { isAdoptingGroup: true }
         : {};
+      if (!this.hasAttribute('drag-image')) {
       this.dispatchEvent(
         new CustomEvent("TabGroupCreate", {
           bubbles: true,
           detail: tabGroupCreateDetail,
         })
       );
+      }
       // Reset `wasCreatedByAdoption` to default of false so that we only
       // claim that a tab group was created by adoption the first time it
       // mounts after getting created by `Tabbrowser.adoptTabGroup`.
       this.#wasCreatedByAdoption = false;
     }
+      this.#observeTabChanges();
+    }
 
     resetDefaultGroupName = () => {
       this.#defaultGroupName = "";
@@ -175,10 +198,15 @@
       if (!this.#tabChangeObserver) {
         this.#tabChangeObserver = new window.MutationObserver(mutations => {
           if (!this.tabs.length) {
+            if (this.tagName === "zen-workspace-collapsible-pins") {
+              return;
+            }
             this.dispatchEvent(
               new CustomEvent("TabGroupRemoved", { bubbles: true })
             );
+          gZenVerticalTabsManager.animateItemClose(this).then(() => {
             this.remove();
+          });
             Services.obs.notifyObservers(
               this,
               "browser-tabgroup-removed-from-dom"
@@ -223,7 +251,10 @@
           }
         });
       }
-      this.#tabChangeObserver.observe(this, { childList: true });
+      const container = this.groupContainer;
+      if (container) {
+        this.#tabChangeObserver.observe(container, { childList: true });
+      }
     }
 
     get color() {
@@ -317,6 +348,9 @@
     }
 
     set collapsed(val) {
+      if (this.hasAttribute("split-view-group")) {
+        return;
+      }
       if (!!val == this.collapsed) {
         return;
       }
@@ -403,7 +437,6 @@
           tabGroupName,
         })
         .then(result => {
-          this.dataset.tooltip = result;
         });
     }
 
@@ -478,13 +511,65 @@
      * @returns {MozTabbrowserTab[]}
      */
     get tabs() {
-      let childrenArray = Array.from(this.children);
-      for (let i = childrenArray.length - 1; i >= 0; i--) {
-        if (childrenArray[i].tagName == "tab-split-view-wrapper") {
-          childrenArray.splice(i, 1, ...childrenArray[i].tabs);
+      // add other group tabs if they are under this group
+      let childs = Array.from(this.groupContainer?.children ?? []);
+      const tabsCollect = [];
+      for (let item of childs) {
+        tabsCollect.push(item);
+        if (gBrowser.isTabGroup(item)) {
+          tabsCollect.push(...item.tabs);
+        }
+      }
+      return tabsCollect.filter(node => node.matches("tab"));
+    }
+
+    get groupContainer() {
+      return this.querySelector(".tab-group-container");
+    }
+
+    get groupStartElement() {
+      return this.querySelector(".zen-tab-group-start");
+    }
+
+    get childGroupsAndTabs() {
+      const result = [];
+      const container = this.groupContainer;
+
+      for (const item of Array.from(container.children)) {
+        if (gBrowser.isTab(item)) {
+          result.push(item);
+        } else if (gBrowser.isTabGroup(item)) {
+          const labelContainer = item.labelElement;
+          labelContainer.visible = item.visible;
+          if (gBrowser.isTabGroupLabel(labelContainer)) {
+            result.push(labelContainer);
+          }
+          result.push(...item.childGroupsAndTabs);
         }
       }
-      return childrenArray.filter(node => node.matches("tab"));
+      return result;
+    }
+
+    get group() {
+      if (gBrowser.isTabGroup(this.parentElement?.parentElement)) {
+        return this.parentElement.parentElement;
+      }
+      return null;
+    }
+
+    get visible() {
+      let currentGroup = this;
+      while (currentGroup?.group) {
+        currentGroup = currentGroup?.group;
+        if (currentGroup.collapsed) {
+          return false;
+        }
+      }
+      return true;
+    }
+
+    get level() {
+      return this.group?.level + 1 || 0;
     }
 
     /**
@@ -592,7 +677,6 @@
           );
         } else {
           if (tabOrSplitView.pinned) {
-            tabOrSplitView.ownerGlobal.gBrowser.unpinTab(tabOrSplitView);
           }
           let tabToMove =
             this.ownerGlobal === tabOrSplitView.ownerGlobal
@@ -661,7 +745,7 @@
      */
     on_click(event) {
       let isToggleElement =
-        event.target === this.#labelElement ||
+        this.labelElement.parentElement.contains(event.target) ||
         event.target === this.#overflowCountLabel;
       if (isToggleElement && event.button === 0) {
         event.preventDefault();
@@ -740,5 +824,6 @@
     }
   }
 
+  window.MozTabbrowserTabGroup = MozTabbrowserTabGroup;
   customElements.define("tab-group", MozTabbrowserTabGroup);
 }
