mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-08-28 09:11:06 +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;
|
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 {
|
> #bsplus-sidebar-root .sub {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
@@ -742,13 +749,24 @@ html.bsplus-custom-title-pending #title > :not(#bsplus-title-root),
|
|||||||
background-image: none !important;
|
background-image: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* One-shot enter — not tied to `.active` (SEQTA strips/restores that on every
|
> #bsplus-sidebar-root.drilling li.hasChildren > .sub:not(:has(.sub)) {
|
||||||
nested click, which would restart the animation). */
|
pointer-events: auto !important;
|
||||||
> #bsplus-sidebar-root .sub.bsplus-sub-enter {
|
background: transparent !important;
|
||||||
animation: bsplus-submenu-enter 0.32s cubic-bezier(0.22, 1, 0.36, 1);
|
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;
|
pointer-events: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -764,6 +782,14 @@ html.bsplus-custom-title-pending #title > :not(#bsplus-title-root),
|
|||||||
opacity: 0 !important;
|
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 {
|
#bsplus-sidebar-root .sub .back {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
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 li > label > svg,
|
||||||
#menu section > label > svg {
|
#menu section > label > svg {
|
||||||
margin: 0 10px 0 4px;
|
margin: 0 10px 0 4px;
|
||||||
|
|||||||
@@ -15,44 +15,25 @@
|
|||||||
#menu > ul:has(li.hasChildren.active) > li > svg,
|
#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 > label,
|
||||||
#menu > ul ul:has(li.hasChildren.active) > li > svg {
|
#menu > ul ul:has(li.hasChildren.active) > li > svg {
|
||||||
/* !important beats theme animations (e.g. Beach palm-slide forwards). */
|
|
||||||
transform: translateX(-320px) !important;
|
transform: translateX(-320px) !important;
|
||||||
animation: none !important;
|
animation: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
#menu ul > li > label,
|
||||||
* Custom sidebar: park sibling chrome while `.drilling` is set.
|
#menu ul > li > svg {
|
||||||
* SEQTA strips/restores `.active` on every nested leaf click; keying only off
|
transition: transform 0.3s ease;
|
||||||
* `: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.bsplus-custom-sidebar #bsplus-sidebar-root.drilling .sub:has(.sub) > ul > li::before,
|
#menu .sub {
|
||||||
#menu.bsplus-custom-sidebar #bsplus-sidebar-root.drilling .sub:has(.sub) > ul > li::after,
|
transition: transform 0.3s ease, left 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
#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.bsplus-custom-sidebar #bsplus-sidebar-root.drilling {
|
#menu > ul:has(li.hasChildren.active) > li.active {
|
||||||
overflow: hidden !important;
|
background: transparent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#menu li.hasChildren:not(.active) li .sub {
|
#menu li.hasChildren:not(.active) li .sub {
|
||||||
display: none; // improves performance
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sub .sub {
|
.sub .sub {
|
||||||
@@ -64,27 +45,6 @@
|
|||||||
display: none !important;
|
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: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 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,
|
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);
|
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,
|
* Custom sidebar drill slides — use `.drilling` / `.drill-entering` / `.drill-returning`,
|
||||||
body.icon-only-sidebar #menu.bsplus-custom-sidebar #bsplus-sidebar-root.drilling > li > svg,
|
* not `:has(.active)` (SEQTA strips `.active` on nested clicks).
|
||||||
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,
|
#menu.bsplus-custom-sidebar #bsplus-sidebar-root {
|
||||||
body.icon-only-sidebar #menu.bsplus-custom-sidebar #bsplus-sidebar-root.drilling .sub:has(.sub) > ul > li > svg {
|
--bsplus-slide-off: -320px;
|
||||||
transform: translateX(-70px) !important;
|
|
||||||
transition: none !important;
|
.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="logo-link bsplus-sidebar-list"
|
||||||
class:noscroll={sidebarState.isDrilling}
|
class:noscroll={sidebarState.isDrilling}
|
||||||
class:drilling={sidebarState.isDrilling}
|
class:drilling={sidebarState.isDrilling}
|
||||||
|
class:drill-entering={sidebarState.enterFrameKey != null}
|
||||||
|
class:drill-returning={sidebarState.drillReturning}
|
||||||
class:compact={sidebarState.compact}
|
class:compact={sidebarState.compact}
|
||||||
class:edit-mode={sidebarState.editMode}
|
class:edit-mode={sidebarState.editMode}
|
||||||
class:is-sorting={dragging}
|
class:is-sorting={dragging}
|
||||||
@@ -283,7 +285,8 @@
|
|||||||
class="sub"
|
class="sub"
|
||||||
class:bsplus-sub-enter={sidebarState.enterFrameKey === current.frame.key}
|
class:bsplus-sub-enter={sidebarState.enterFrameKey === current.frame.key}
|
||||||
onanimationend={(e) => {
|
onanimationend={(e) => {
|
||||||
if (e.target === e.currentTarget) {
|
if (e.target !== e.currentTarget) return;
|
||||||
|
if (sidebarState.enterFrameKey === current.frame.key) {
|
||||||
sidebarState.clearEnterFrame(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.
|
* never see them. Opening Goals/Folios via SEQTA + our drill UI freezes the tab.
|
||||||
*/
|
*/
|
||||||
function onCustomSidebarCaptureClick(event: MouseEvent) {
|
function onCustomSidebarCaptureClick(event: MouseEvent) {
|
||||||
if (!menuEl || sidebarState.editMode) return;
|
if (!menuEl || sidebarState.editMode || sidebarState.drillReturning) return;
|
||||||
|
|
||||||
const root = document.getElementById(ROOT_ID);
|
const root = document.getElementById(ROOT_ID);
|
||||||
const target = event.target;
|
const target = event.target;
|
||||||
|
|||||||
@@ -184,8 +184,9 @@ class SidebarState {
|
|||||||
activePath = $state("");
|
activePath = $state("");
|
||||||
editMode = $state(false);
|
editMode = $state(false);
|
||||||
iconOnly = $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);
|
enterFrameKey = $state<string | null>(null);
|
||||||
|
drillReturning = $state(false);
|
||||||
|
|
||||||
visibleRootItems = $derived(
|
visibleRootItems = $derived(
|
||||||
filterVisible(orderItems(this.items, settingsState.menuorder ?? [])),
|
filterVisible(orderItems(this.items, settingsState.menuorder ?? [])),
|
||||||
@@ -262,10 +263,11 @@ class SidebarState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
openFolder(item: SidebarItem, menu?: HTMLElement) {
|
openFolder(item: SidebarItem, menu?: HTMLElement) {
|
||||||
if (!item.hasChildren) return;
|
if (!item.hasChildren || this.drillReturning) return;
|
||||||
// Ignore duplicate opens (double-firing click / label + li).
|
|
||||||
if (this.drillStack.at(-1)?.key === item.key) return;
|
if (this.drillStack.at(-1)?.key === item.key) return;
|
||||||
|
|
||||||
|
this.drillReturning = false;
|
||||||
|
|
||||||
const frame: SidebarDrillFrame = {
|
const frame: SidebarDrillFrame = {
|
||||||
key: item.key,
|
key: item.key,
|
||||||
label: item.label,
|
label: item.label,
|
||||||
@@ -293,14 +295,23 @@ class SidebarState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
goBack() {
|
goBack() {
|
||||||
if (!this.drillStack.length) return;
|
if (!this.drillStack.length || this.drillReturning) return;
|
||||||
|
|
||||||
this.enterFrameKey = null;
|
this.enterFrameKey = null;
|
||||||
this.drillStack = this.drillStack.slice(0, -1);
|
this.drillStack = this.drillStack.slice(0, -1);
|
||||||
resetSidebarScroll();
|
resetSidebarScroll();
|
||||||
|
|
||||||
|
if (settingsState.animations !== true) return;
|
||||||
|
|
||||||
|
this.drillReturning = true;
|
||||||
|
window.setTimeout(() => {
|
||||||
|
this.drillReturning = false;
|
||||||
|
}, 360);
|
||||||
}
|
}
|
||||||
|
|
||||||
resetDrill() {
|
resetDrill() {
|
||||||
this.enterFrameKey = null;
|
this.enterFrameKey = null;
|
||||||
|
this.drillReturning = false;
|
||||||
this.drillStack = [];
|
this.drillStack = [];
|
||||||
resetSidebarScroll();
|
resetSidebarScroll();
|
||||||
}
|
}
|
||||||
@@ -350,7 +361,7 @@ class SidebarState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
activateItem(item: SidebarItem, menu: HTMLElement) {
|
activateItem(item: SidebarItem, menu: HTMLElement) {
|
||||||
if (this.editMode) return;
|
if (this.editMode || this.drillReturning) return;
|
||||||
|
|
||||||
if (item.hasChildren) {
|
if (item.hasChildren) {
|
||||||
this.openFolder(item, menu);
|
this.openFolder(item, menu);
|
||||||
@@ -360,6 +371,13 @@ class SidebarState {
|
|||||||
this.activeKey = item.key;
|
this.activeKey = item.key;
|
||||||
if (item.path) this.activePath = item.path;
|
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);
|
const native = findNativeMenuEntry(menu, item);
|
||||||
if (native) {
|
if (native) {
|
||||||
// Clear native drill once only — repeating clearNativeDrillActive fights
|
// Clear native drill once only — repeating clearNativeDrillActive fights
|
||||||
|
|||||||
Reference in New Issue
Block a user