mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-08-28 17:21:05 +00:00
fix: fix sidebar animation weirdness in sidebar folders
This commit is contained in:
+31
-15
@@ -722,6 +722,13 @@ html.bsplus-custom-title-pending #title > :not(#bsplus-title-root),
|
||||
pointer-events: none !important;
|
||||
}
|
||||
|
||||
/* Same locks keyed off `.drilling` so nested leaf clicks do not flicker when
|
||||
SEQTA briefly strips `.active` from folder rows. */
|
||||
> #bsplus-sidebar-root.drilling > li:not(.hasChildren),
|
||||
> #bsplus-sidebar-root.drilling > li:not(.hasChildren) * {
|
||||
pointer-events: none !important;
|
||||
}
|
||||
|
||||
> #bsplus-sidebar-root .sub {
|
||||
pointer-events: none;
|
||||
}
|
||||
@@ -742,13 +749,24 @@ html.bsplus-custom-title-pending #title > :not(#bsplus-title-root),
|
||||
background-image: none !important;
|
||||
}
|
||||
|
||||
/* One-shot enter — not tied to `.active` (SEQTA strips/restores that on every
|
||||
nested click, which would restart the animation). */
|
||||
> #bsplus-sidebar-root .sub.bsplus-sub-enter {
|
||||
animation: bsplus-submenu-enter 0.32s cubic-bezier(0.22, 1, 0.36, 1);
|
||||
> #bsplus-sidebar-root.drilling li.hasChildren > .sub:not(:has(.sub)) {
|
||||
pointer-events: auto !important;
|
||||
background: transparent !important;
|
||||
background-image: none !important;
|
||||
}
|
||||
|
||||
> #bsplus-sidebar-root > li.hasChildren.active > label {
|
||||
> #bsplus-sidebar-root.drilling li.hasChildren > .sub:has(.sub) {
|
||||
pointer-events: none !important;
|
||||
}
|
||||
|
||||
> #bsplus-sidebar-root.drilling li.hasChildren > .sub .sub {
|
||||
pointer-events: auto !important;
|
||||
background: transparent !important;
|
||||
background-image: none !important;
|
||||
}
|
||||
|
||||
> #bsplus-sidebar-root > li.hasChildren.active > label,
|
||||
> #bsplus-sidebar-root.drilling > li.hasChildren > label {
|
||||
pointer-events: none !important;
|
||||
}
|
||||
|
||||
@@ -764,6 +782,14 @@ html.bsplus-custom-title-pending #title > :not(#bsplus-title-root),
|
||||
opacity: 0 !important;
|
||||
}
|
||||
|
||||
> #bsplus-sidebar-root.drilling > li:not(.hasChildren)::before,
|
||||
> #bsplus-sidebar-root.drilling > li:not(.hasChildren)::after {
|
||||
content: none !important;
|
||||
display: none !important;
|
||||
animation: none !important;
|
||||
opacity: 0 !important;
|
||||
}
|
||||
|
||||
#bsplus-sidebar-root .sub .back {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -790,16 +816,6 @@ html.bsplus-custom-title-pending #title > :not(#bsplus-title-root),
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bsplus-submenu-enter {
|
||||
from {
|
||||
opacity: 0.35;
|
||||
transform: translateX(28px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
#menu li > label > svg,
|
||||
#menu section > label > svg {
|
||||
margin: 0 10px 0 4px;
|
||||
|
||||
@@ -15,44 +15,25 @@
|
||||
#menu > ul:has(li.hasChildren.active) > li > svg,
|
||||
#menu > ul ul:has(li.hasChildren.active) > li > label,
|
||||
#menu > ul ul:has(li.hasChildren.active) > li > svg {
|
||||
/* !important beats theme animations (e.g. Beach palm-slide forwards). */
|
||||
transform: translateX(-320px) !important;
|
||||
animation: none !important;
|
||||
}
|
||||
|
||||
/*
|
||||
* Custom sidebar: park sibling chrome while `.drilling` is set.
|
||||
* SEQTA strips/restores `.active` on every nested leaf click; keying only off
|
||||
* `:has(.active)` briefly undoes the translate and the 0.3s transform
|
||||
* transition makes that look like the open animation flashing again.
|
||||
*
|
||||
* Scope carefully — only root siblings (and nested-folder siblings via
|
||||
* `.sub:has(.sub)`), never the visible leaf rows in the current panel.
|
||||
*/
|
||||
#menu.bsplus-custom-sidebar #bsplus-sidebar-root.drilling > li::before,
|
||||
#menu.bsplus-custom-sidebar #bsplus-sidebar-root.drilling > li::after,
|
||||
#menu.bsplus-custom-sidebar #bsplus-sidebar-root.drilling > li > label,
|
||||
#menu.bsplus-custom-sidebar #bsplus-sidebar-root.drilling > li > svg {
|
||||
transform: translateX(-320px) !important;
|
||||
animation: none !important;
|
||||
transition: none !important;
|
||||
#menu ul > li > label,
|
||||
#menu ul > li > svg {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
#menu.bsplus-custom-sidebar #bsplus-sidebar-root.drilling .sub:has(.sub) > ul > li::before,
|
||||
#menu.bsplus-custom-sidebar #bsplus-sidebar-root.drilling .sub:has(.sub) > ul > li::after,
|
||||
#menu.bsplus-custom-sidebar #bsplus-sidebar-root.drilling .sub:has(.sub) > ul > li > label,
|
||||
#menu.bsplus-custom-sidebar #bsplus-sidebar-root.drilling .sub:has(.sub) > ul > li > svg {
|
||||
transform: translateX(-320px) !important;
|
||||
animation: none !important;
|
||||
transition: none !important;
|
||||
#menu .sub {
|
||||
transition: transform 0.3s ease, left 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
#menu.bsplus-custom-sidebar #bsplus-sidebar-root.drilling {
|
||||
overflow: hidden !important;
|
||||
#menu > ul:has(li.hasChildren.active) > li.active {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
#menu li.hasChildren:not(.active) li .sub {
|
||||
display: none; // improves performance
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sub .sub {
|
||||
@@ -64,27 +45,6 @@
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#menu ul > li > label,
|
||||
#menu ul > li > svg {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
#menu.bsplus-custom-sidebar #bsplus-sidebar-root.drilling > li > label,
|
||||
#menu.bsplus-custom-sidebar #bsplus-sidebar-root.drilling > li > svg,
|
||||
#menu.bsplus-custom-sidebar #bsplus-sidebar-root.drilling .sub:has(.sub) > ul > li > label,
|
||||
#menu.bsplus-custom-sidebar #bsplus-sidebar-root.drilling .sub:has(.sub) > ul > li > svg {
|
||||
transition: none !important;
|
||||
}
|
||||
|
||||
#menu .sub {
|
||||
transition: transform 0.3s ease, left 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
#menu > ul:has(li.hasChildren.active) > li.active {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
/* Icon-only collapsed: submenu slides over narrow icons */
|
||||
body.icon-only-sidebar:not(:has(#menu li.hasChildren.active)) #menu > ul:has(li.hasChildren.active) > li::before,
|
||||
body.icon-only-sidebar:not(:has(#menu li.hasChildren.active)) #menu > ul ul:has(li.hasChildren.active) > li::before,
|
||||
body.icon-only-sidebar:not(:has(#menu li.hasChildren.active)) #menu > ul:has(li.hasChildren.active) > li > label,
|
||||
@@ -94,12 +54,92 @@ body.icon-only-sidebar:not(:has(#menu li.hasChildren.active)) #menu > ul ul:has(
|
||||
transform: translateX(-70px);
|
||||
}
|
||||
|
||||
body.icon-only-sidebar #menu.bsplus-custom-sidebar #bsplus-sidebar-root.drilling > li::before,
|
||||
body.icon-only-sidebar #menu.bsplus-custom-sidebar #bsplus-sidebar-root.drilling > li > label,
|
||||
body.icon-only-sidebar #menu.bsplus-custom-sidebar #bsplus-sidebar-root.drilling > li > svg,
|
||||
body.icon-only-sidebar #menu.bsplus-custom-sidebar #bsplus-sidebar-root.drilling .sub:has(.sub) > ul > li::before,
|
||||
body.icon-only-sidebar #menu.bsplus-custom-sidebar #bsplus-sidebar-root.drilling .sub:has(.sub) > ul > li > label,
|
||||
body.icon-only-sidebar #menu.bsplus-custom-sidebar #bsplus-sidebar-root.drilling .sub:has(.sub) > ul > li > svg {
|
||||
transform: translateX(-70px) !important;
|
||||
transition: none !important;
|
||||
/*
|
||||
* Custom sidebar drill slides — use `.drilling` / `.drill-entering` / `.drill-returning`,
|
||||
* not `:has(.active)` (SEQTA strips `.active` on nested clicks).
|
||||
*/
|
||||
#menu.bsplus-custom-sidebar #bsplus-sidebar-root {
|
||||
--bsplus-slide-off: -320px;
|
||||
|
||||
.sub {
|
||||
transition: none !important;
|
||||
}
|
||||
|
||||
&.drilling {
|
||||
overflow: hidden !important;
|
||||
|
||||
&:not(.drill-returning) > li::before,
|
||||
&:not(.drill-returning) > li::after,
|
||||
&:not(.drill-returning) > li > label,
|
||||
&:not(.drill-returning) > li > svg,
|
||||
&:not(.drill-returning) .sub:has(.sub) > ul > li::before,
|
||||
&:not(.drill-returning) .sub:has(.sub) > ul > li::after,
|
||||
&:not(.drill-returning) .sub:has(.sub) > ul > li > label,
|
||||
&:not(.drill-returning) .sub:has(.sub) > ul > li > svg {
|
||||
transform: translateX(var(--bsplus-slide-off)) !important;
|
||||
animation: none !important;
|
||||
}
|
||||
|
||||
&:not(.drill-entering):not(.drill-returning) {
|
||||
> li::before,
|
||||
> li::after,
|
||||
> li > label,
|
||||
> li > svg,
|
||||
.sub:has(.sub) > ul > li::before,
|
||||
.sub:has(.sub) > ul > li::after,
|
||||
.sub:has(.sub) > ul > li > label,
|
||||
.sub:has(.sub) > ul > li > svg {
|
||||
transition: none !important;
|
||||
}
|
||||
|
||||
.sub {
|
||||
transform: translateX(0) !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.sub:has(.sub) > .nav > .back {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.drill-entering .sub.bsplus-sub-enter {
|
||||
animation: bsplus-submenu-enter 0.32s cubic-bezier(0.22, 1, 0.36, 1);
|
||||
}
|
||||
|
||||
&.drill-returning:not(.drilling) > li::before,
|
||||
&.drill-returning:not(.drilling) > li::after,
|
||||
&.drill-returning:not(.drilling) > li > label,
|
||||
&.drill-returning:not(.drilling) > li > svg,
|
||||
&.drilling.drill-returning > li.hasChildren > .sub > ul > li::before,
|
||||
&.drilling.drill-returning > li.hasChildren > .sub > ul > li::after,
|
||||
&.drilling.drill-returning > li.hasChildren > .sub > ul > li > label,
|
||||
&.drilling.drill-returning > li.hasChildren > .sub > ul > li > svg {
|
||||
transition: none !important;
|
||||
animation: bsplus-sidebar-return 0.32s cubic-bezier(0.22, 1, 0.36, 1) both !important;
|
||||
}
|
||||
}
|
||||
|
||||
body.icon-only-sidebar #menu.bsplus-custom-sidebar #bsplus-sidebar-root {
|
||||
--bsplus-slide-off: -70px;
|
||||
}
|
||||
|
||||
@keyframes bsplus-sidebar-return {
|
||||
from {
|
||||
transform: translateX(var(--bsplus-slide-off, -320px));
|
||||
}
|
||||
to {
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bsplus-submenu-enter {
|
||||
from {
|
||||
opacity: 0.35;
|
||||
transform: translateX(28px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,6 +195,8 @@
|
||||
class="logo-link bsplus-sidebar-list"
|
||||
class:noscroll={sidebarState.isDrilling}
|
||||
class:drilling={sidebarState.isDrilling}
|
||||
class:drill-entering={sidebarState.enterFrameKey != null}
|
||||
class:drill-returning={sidebarState.drillReturning}
|
||||
class:compact={sidebarState.compact}
|
||||
class:edit-mode={sidebarState.editMode}
|
||||
class:is-sorting={dragging}
|
||||
@@ -283,7 +285,8 @@
|
||||
class="sub"
|
||||
class:bsplus-sub-enter={sidebarState.enterFrameKey === current.frame.key}
|
||||
onanimationend={(e) => {
|
||||
if (e.target === e.currentTarget) {
|
||||
if (e.target !== e.currentTarget) return;
|
||||
if (sidebarState.enterFrameKey === current.frame.key) {
|
||||
sidebarState.clearEnterFrame(current.frame.key);
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -101,7 +101,7 @@ function scheduleSync() {
|
||||
* never see them. Opening Goals/Folios via SEQTA + our drill UI freezes the tab.
|
||||
*/
|
||||
function onCustomSidebarCaptureClick(event: MouseEvent) {
|
||||
if (!menuEl || sidebarState.editMode) return;
|
||||
if (!menuEl || sidebarState.editMode || sidebarState.drillReturning) return;
|
||||
|
||||
const root = document.getElementById(ROOT_ID);
|
||||
const target = event.target;
|
||||
|
||||
@@ -184,8 +184,9 @@ class SidebarState {
|
||||
activePath = $state("");
|
||||
editMode = $state(false);
|
||||
iconOnly = $state(false);
|
||||
/** Frame key whose `.sub` should play the one-shot enter animation. */
|
||||
/** Folder key playing the one-shot panel enter animation. */
|
||||
enterFrameKey = $state<string | null>(null);
|
||||
drillReturning = $state(false);
|
||||
|
||||
visibleRootItems = $derived(
|
||||
filterVisible(orderItems(this.items, settingsState.menuorder ?? [])),
|
||||
@@ -262,10 +263,11 @@ class SidebarState {
|
||||
}
|
||||
|
||||
openFolder(item: SidebarItem, menu?: HTMLElement) {
|
||||
if (!item.hasChildren) return;
|
||||
// Ignore duplicate opens (double-firing click / label + li).
|
||||
if (!item.hasChildren || this.drillReturning) return;
|
||||
if (this.drillStack.at(-1)?.key === item.key) return;
|
||||
|
||||
this.drillReturning = false;
|
||||
|
||||
const frame: SidebarDrillFrame = {
|
||||
key: item.key,
|
||||
label: item.label,
|
||||
@@ -293,14 +295,23 @@ class SidebarState {
|
||||
}
|
||||
|
||||
goBack() {
|
||||
if (!this.drillStack.length) return;
|
||||
if (!this.drillStack.length || this.drillReturning) return;
|
||||
|
||||
this.enterFrameKey = null;
|
||||
this.drillStack = this.drillStack.slice(0, -1);
|
||||
resetSidebarScroll();
|
||||
|
||||
if (settingsState.animations !== true) return;
|
||||
|
||||
this.drillReturning = true;
|
||||
window.setTimeout(() => {
|
||||
this.drillReturning = false;
|
||||
}, 360);
|
||||
}
|
||||
|
||||
resetDrill() {
|
||||
this.enterFrameKey = null;
|
||||
this.drillReturning = false;
|
||||
this.drillStack = [];
|
||||
resetSidebarScroll();
|
||||
}
|
||||
@@ -350,7 +361,7 @@ class SidebarState {
|
||||
}
|
||||
|
||||
activateItem(item: SidebarItem, menu: HTMLElement) {
|
||||
if (this.editMode) return;
|
||||
if (this.editMode || this.drillReturning) return;
|
||||
|
||||
if (item.hasChildren) {
|
||||
this.openFolder(item, menu);
|
||||
@@ -360,6 +371,13 @@ class SidebarState {
|
||||
this.activeKey = item.key;
|
||||
if (item.path) this.activePath = item.path;
|
||||
|
||||
// Already inside this folder — never replay the one-shot enter animation when
|
||||
// SEQTA rewrites `.active` on the route change.
|
||||
if (this.isDrilling) {
|
||||
this.enterFrameKey = null;
|
||||
restoreCustomMenuActive();
|
||||
}
|
||||
|
||||
const native = findNativeMenuEntry(menu, item);
|
||||
if (native) {
|
||||
// Clear native drill once only — repeating clearNativeDrillActive fights
|
||||
|
||||
Reference in New Issue
Block a user