From 63476b39aae10c3ccec7d2c10a6428d07ad8a648 Mon Sep 17 00:00:00 2001 From: Ali <010109ali@gmail.com> Date: Mon, 13 Jul 2026 12:22:07 +0000 Subject: [PATCH] fix: keep subtabs open when Frappe re-activates a tab MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Frappe's tab model does not know subtabs exist. Tab.set_active() strips `show active` off every pane except the one it activates, and Frappe calls it on every refresh_sections() — which runs on every refresh_field() and every value change. So editing any field wiped the open subtab: its content appeared for a fraction of a second and vanished. Clicking a subtab now registers its top-level ancestor as the active tab, so Frappe's own bookkeeping stays coherent and keeps re-activating the right tab, and Tab.set_active is wrapped to re-assert the rest of the chain once Frappe is done. The whole ancestor chain has to be restored, not just the leaf: subtabs nest two deep in several declarations, where the top pane holds the first subtab bar, the middle pane holds the second and the leaf holds the content — three panes active at once, which Frappe's one-tab-at-a-time model will never do on its own. This replaces the MutationObserver, which was fighting the same battle from the wrong end: it could not tell a genuine tab switch from a refresh re-asserting the tab already open. Verified: 70 subtabs across 11 doctypes stay visible through refresh_field() and refresh_sections(). Co-Authored-By: Claude Opus 4.8 (1M context) --- .../custom_subtabs.bundle.DYDKGLKL.css | 2 + ...=> custom_subtabs.bundle.DYDKGLKL.css.map} | 4 +- .../custom_subtabs.bundle.HFXJTVZI.css | 68 --- .../css/custom_subtabs.bundle.6DBL7IOJ.css | 68 --- .../css/custom_subtabs.bundle.CJRWDWV2.css | 2 + ...=> custom_subtabs.bundle.CJRWDWV2.css.map} | 4 +- .../dist/js/custom_subtabs.bundle.DIIPT3ZZ.js | 197 ------- .../js/custom_subtabs.bundle.DIIPT3ZZ.js.map | 7 - .../dist/js/custom_subtabs.bundle.QW446NRW.js | 2 + .../js/custom_subtabs.bundle.QW446NRW.js.map | 7 + .../public/js/custom_subtabs.bundle.js | 485 ++++++++---------- 11 files changed, 231 insertions(+), 615 deletions(-) create mode 100644 custom_subtabs/public/dist/css-rtl/custom_subtabs.bundle.DYDKGLKL.css rename custom_subtabs/public/dist/css-rtl/{custom_subtabs.bundle.HFXJTVZI.css.map => custom_subtabs.bundle.DYDKGLKL.css.map} (85%) delete mode 100644 custom_subtabs/public/dist/css-rtl/custom_subtabs.bundle.HFXJTVZI.css delete mode 100644 custom_subtabs/public/dist/css/custom_subtabs.bundle.6DBL7IOJ.css create mode 100644 custom_subtabs/public/dist/css/custom_subtabs.bundle.CJRWDWV2.css rename custom_subtabs/public/dist/css/{custom_subtabs.bundle.6DBL7IOJ.css.map => custom_subtabs.bundle.CJRWDWV2.css.map} (85%) delete mode 100644 custom_subtabs/public/dist/js/custom_subtabs.bundle.DIIPT3ZZ.js delete mode 100644 custom_subtabs/public/dist/js/custom_subtabs.bundle.DIIPT3ZZ.js.map create mode 100644 custom_subtabs/public/dist/js/custom_subtabs.bundle.QW446NRW.js create mode 100644 custom_subtabs/public/dist/js/custom_subtabs.bundle.QW446NRW.js.map diff --git a/custom_subtabs/public/dist/css-rtl/custom_subtabs.bundle.DYDKGLKL.css b/custom_subtabs/public/dist/css-rtl/custom_subtabs.bundle.DYDKGLKL.css new file mode 100644 index 0000000..b647954 --- /dev/null +++ b/custom_subtabs/public/dist/css-rtl/custom_subtabs.bundle.DYDKGLKL.css @@ -0,0 +1,2 @@ +.sub-tab-container{margin:0!important;padding:0!important;display:flex!important;justify-content:flex-start!important;border-bottom:1px solid #ddd!important}.sub-tab-container .sub-tab{margin:0!important;background:none!important;border:none!important;padding:0!important}.sub-tab-container .sub-tab a,.sub-tab-container .sub-tab button{text-decoration:none!important;display:block!important;padding:6px 15px!important;color:#555!important;border:none!important;font-size:14px!important;font-weight:400!important;margin:0!important;background:transparent!important;box-shadow:none!important}.sub-tab-container .sub-tab a:hover,.sub-tab-container .sub-tab button:hover{color:#000!important}.sub-tab-container .sub-tab.active a,.sub-tab-container .sub-tab.active button{color:#000!important;font-weight:600!important;border-bottom:2px solid #000!important;background-color:transparent!important;border-radius:0!important}.form-section:has(.sub-tab-container){padding-top:0!important;padding-bottom:0!important;margin-bottom:0!important}.form-section .section-body:empty,.form-section .section-body:has(> .form-column > form > .frappe-control[data-fieldname="html_vohk"] > span.tooltip-content:only-child){display:none!important;padding:0!important;margin:0!important;min-height:0!important}.sub-tab-container.nav{display:flex;list-style:none;padding:0;margin:0}.sub-tab-container.nav>li[style*="display: none"]{display:none!important}.sub-tab-container.subtab-hidden{display:none!important;visibility:hidden!important;pointer-events:none!important;height:0!important;overflow:hidden!important} +/*# sourceMappingURL=custom_subtabs.bundle.DYDKGLKL.css.map */ diff --git a/custom_subtabs/public/dist/css-rtl/custom_subtabs.bundle.HFXJTVZI.css.map b/custom_subtabs/public/dist/css-rtl/custom_subtabs.bundle.DYDKGLKL.css.map similarity index 85% rename from custom_subtabs/public/dist/css-rtl/custom_subtabs.bundle.HFXJTVZI.css.map rename to custom_subtabs/public/dist/css-rtl/custom_subtabs.bundle.DYDKGLKL.css.map index c198156..1900faf 100644 --- a/custom_subtabs/public/dist/css-rtl/custom_subtabs.bundle.HFXJTVZI.css.map +++ b/custom_subtabs/public/dist/css-rtl/custom_subtabs.bundle.DYDKGLKL.css.map @@ -1,7 +1,7 @@ { "version": 3, - "sources": ["../../../../../../../../tmp/tmp-18495-vJNc0fl1RN65/custom_subtabs/custom_subtabs/public/css/custom_subtabs.bundle.css"], + "sources": ["../../../../../../../../tmp/tmp-15812-S7Giyd0UpxCO/custom_subtabs/custom_subtabs/public/css/custom_subtabs.bundle.css"], "sourcesContent": [".sub-tab-container {\n margin: 0 !important;\n padding: 0 !important;\n display: flex !important;\n justify-content: flex-start !important;\n border-bottom: 1px solid #ddd !important;\n}\n\n.sub-tab-container .sub-tab {\n margin: 0 !important;\n background: none !important;\n border: none !important;\n padding: 0 !important;\n}\n\n/* Support both and