From 5b126c834abd39a79b40f4a4419abcddbc1f4dfa Mon Sep 17 00:00:00 2001 From: everyoneexe Date: Mon, 29 Sep 2025 02:11:44 +0300 Subject: [PATCH] Fix primary sidebar animations when secondary sidebar is open - Add missing initExplorerHandler() call in updateHandler.ts - Fix Smooth-Mode.scss selectors to work with both sidebars - Add comprehensive sidebarHandler.ts for all panel states - Add terminal toggle animations with slide effects - Add extension panel toggle animations - Support all sidebar combinations (both-sidebars-open, etc.) - Enhanced CSS timing functions for smooth UX --- package-lock.json | 12 +- src/custom/handlers/sidebarHandler.ts | 261 ++++++++++++++++++++++++++ src/custom/updateHandler.ts | 4 + src/scss/Misc/Smooth-Mode.scss | 102 +++++++++- 4 files changed, 374 insertions(+), 5 deletions(-) create mode 100644 src/custom/handlers/sidebarHandler.ts diff --git a/package-lock.json b/package-lock.json index 83b9fd0..1099aee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -345,7 +345,8 @@ "node_modules/@types/node": { "version": "16.18.34", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.34.tgz", - "integrity": "sha512-VmVm7gXwhkUimRfBwVI1CHhwp86jDWR04B5FGebMMyxV90SlCmFujwUHrxTD4oO+SOYU86SoxvhgeRQJY7iXFg==" + "integrity": "sha512-VmVm7gXwhkUimRfBwVI1CHhwp86jDWR04B5FGebMMyxV90SlCmFujwUHrxTD4oO+SOYU86SoxvhgeRQJY7iXFg==", + "peer": true }, "node_modules/@types/semver": { "version": "7.5.0", @@ -409,6 +410,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.9.tgz", "integrity": "sha512-FsPkRvBtcLQ/eVK1ivDiNYBjn3TGJdXy2fhXX+rc7czWl4ARwnpArwbihSOHI2Peg9WbtGHrbThfBUkZZGTtvQ==", "dev": true, + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "5.59.9", "@typescript-eslint/types": "5.59.9", @@ -797,6 +799,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -838,6 +841,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1032,6 +1036,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", @@ -1388,6 +1393,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.42.0.tgz", "integrity": "sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A==", "dev": true, + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", @@ -3166,6 +3172,7 @@ "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -3354,6 +3361,7 @@ "version": "5.1.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz", "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3433,6 +3441,7 @@ "integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.6", @@ -3479,6 +3488,7 @@ "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.3.tgz", "integrity": "sha512-MTuk7NUMvEHQUSXCpvUrF1q2p0FJS40dPFfqQvG3jTWcgv/8plBNz2Kv2HXZiLGPnfmSAA5uCtCILO1JBmmkfw==", "dev": true, + "peer": true, "dependencies": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^2.1.1", diff --git a/src/custom/handlers/sidebarHandler.ts b/src/custom/handlers/sidebarHandler.ts new file mode 100644 index 0000000..819086c --- /dev/null +++ b/src/custom/handlers/sidebarHandler.ts @@ -0,0 +1,261 @@ +import { waitForElement } from "./util"; + +/** + * The function that handles all the sidebar animations + * Ensures smooth animations work properly when both primary and secondary sidebars are open + */ +export function initSidebarHandler() { + let primarySidebarState = false; + let secondarySidebarState = false; + let terminalPanelState = false; + let extensionsPanelState = false; + + // Observer for primary sidebar (left side - explorer, source control, etc.) + const observePrimarySidebar = () => { + waitForElement('.part.sidebar.left', (primarySidebar) => { + const primaryObserver = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + if (mutation.type === 'attributes' && mutation.attributeName === 'style') { + const target = mutation.target as HTMLElement; + const currentlyVisible = !target.style.display || target.style.display !== 'none'; + + if (currentlyVisible !== primarySidebarState) { + primarySidebarState = currentlyVisible; + updatePanelClasses(); + } + } + }); + }); + + primaryObserver.observe(primarySidebar, { + attributes: true, + attributeFilter: ['style', 'class'] + }); + }); + }; + + // Observer for secondary sidebar (right side - outline, etc.) + const observeSecondarySidebar = () => { + waitForElement('.part.sidebar.right', (secondarySidebar) => { + const secondaryObserver = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + if (mutation.type === 'attributes' && mutation.attributeName === 'style') { + const target = mutation.target as HTMLElement; + const currentlyVisible = !target.style.display || target.style.display !== 'none'; + + if (currentlyVisible !== secondarySidebarState) { + secondarySidebarState = currentlyVisible; + updatePanelClasses(); + } + } + }); + }); + + secondaryObserver.observe(secondarySidebar, { + attributes: true, + attributeFilter: ['style', 'class'] + }); + }); + }; + + // Observer for terminal panel (bottom panel) + const observeTerminalPanel = () => { + waitForElement('.part.panel', (terminalPanel) => { + const terminalObserver = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + if (mutation.type === 'attributes' && mutation.attributeName === 'style') { + const target = mutation.target as HTMLElement; + const currentlyVisible = !target.style.display || target.style.display !== 'none'; + + if (currentlyVisible !== terminalPanelState) { + terminalPanelState = currentlyVisible; + updatePanelClasses(); + } + } + }); + }); + + terminalObserver.observe(terminalPanel, { + attributes: true, + attributeFilter: ['style', 'class'] + }); + }); + }; + + // Observer for extensions panel (auxiliary bar) + const observeExtensionsPanel = () => { + waitForElement('.part.auxiliarybar', (extensionsPanel) => { + const extensionsObserver = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + if (mutation.type === 'attributes' && mutation.attributeName === 'style') { + const target = mutation.target as HTMLElement; + const currentlyVisible = !target.style.display || target.style.display !== 'none'; + + if (currentlyVisible !== extensionsPanelState) { + extensionsPanelState = currentlyVisible; + updatePanelClasses(); + } + } + }); + }); + + extensionsObserver.observe(extensionsPanel, { + attributes: true, + attributeFilter: ['style', 'class'] + }); + }); + }; + + // Update workbench classes based on all panel states + const updatePanelClasses = () => { + waitForElement('.monaco-workbench', (workbench) => { + // Remove existing panel state classes + workbench.classList.remove( + 'primary-sidebar-open', + 'secondary-sidebar-open', + 'both-sidebars-open', + 'no-sidebars-open', + 'terminal-panel-open', + 'extensions-panel-open', + 'all-panels-open' + ); + + // Add appropriate classes based on current state + if (primarySidebarState && secondarySidebarState) { + workbench.classList.add('both-sidebars-open'); + } else if (primarySidebarState) { + workbench.classList.add('primary-sidebar-open'); + } else if (secondarySidebarState) { + workbench.classList.add('secondary-sidebar-open'); + } else { + workbench.classList.add('no-sidebars-open'); + } + + // Add panel-specific classes + if (terminalPanelState) { + workbench.classList.add('terminal-panel-open'); + } + + if (extensionsPanelState) { + workbench.classList.add('extensions-panel-open'); + } + + // Add combined class if multiple panels are open + const openPanelCount = [primarySidebarState, secondarySidebarState, terminalPanelState, extensionsPanelState].filter(Boolean).length; + if (openPanelCount >= 2) { + workbench.classList.add('all-panels-open'); + } + }); + }; + + // Enhanced animation support for smooth transitions + const enhancePanelAnimations = () => { + waitForElement('.monaco-workbench', (workbench) => { + // Add CSS custom properties for enhanced control + const style = document.createElement('style'); + style.textContent = ` + /* Enhanced sidebar and panel animation support */ + .monaco-workbench.both-sidebars-open .part.sidebar, + .monaco-workbench.all-panels-open .part.sidebar, + .monaco-workbench.all-panels-open .part.panel, + .monaco-workbench.all-panels-open .part.auxiliarybar { + transition-timing-function: cubic-bezier(0.25, 0.8, 0.25, 1) !important; + } + + .monaco-workbench.both-sidebars-open .split-view-view, + .monaco-workbench.all-panels-open .split-view-view { + transition-delay: 0ms !important; + } + + /* Ensure animations work for all panels */ + .monaco-workbench .part.sidebar.left[style*="width"], + .monaco-workbench .part.sidebar.right[style*="width"], + .monaco-workbench .part.panel[style*="height"], + .monaco-workbench .part.auxiliarybar[style*="width"] { + transition-property: width, height, transform, opacity !important; + transition-duration: var(--smooth-windows-duration, 300ms) !important; + transition-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1) !important; + } + + /* Enhanced support for activitybar and terminal */ + .monaco-workbench .part.activitybar[style*="width"], + .monaco-workbench .terminal-outer-container[style*="height"], + .monaco-workbench .integrated-terminal[style*="height"] { + transition-property: width, height, transform, opacity !important; + transition-duration: var(--smooth-windows-duration, 300ms) !important; + transition-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1) !important; + } + + /* Smooth terminal toggle animations */ + .monaco-workbench.terminal-panel-open .part.panel { + animation: panelSlideIn var(--smooth-windows-duration, 300ms) cubic-bezier(0.4, 0.0, 0.2, 1); + } + + /* Smooth extensions panel toggle animations */ + .monaco-workbench.extensions-panel-open .part.auxiliarybar { + animation: sidebarSlideIn var(--smooth-windows-duration, 300ms) cubic-bezier(0.4, 0.0, 0.2, 1); + } + + @keyframes panelSlideIn { + from { + height: 0; + opacity: 0; + transform: translateY(20px); + } + to { + height: auto; + opacity: 1; + transform: translateY(0); + } + } + + @keyframes sidebarSlideIn { + from { + width: 0; + opacity: 0; + transform: translateX(20px); + } + to { + width: auto; + opacity: 1; + transform: translateX(0); + } + } + `; + document.head.appendChild(style); + }); + }; + + // Initialize all observers + observePrimarySidebar(); + observeSecondarySidebar(); + observeTerminalPanel(); + observeExtensionsPanel(); + enhancePanelAnimations(); + + // Initial state check + setTimeout(() => { + const primarySidebar = document.querySelector('.part.sidebar.left') as HTMLElement; + const secondarySidebar = document.querySelector('.part.sidebar.right') as HTMLElement; + const terminalPanel = document.querySelector('.part.panel') as HTMLElement; + const extensionsPanel = document.querySelector('.part.auxiliarybar') as HTMLElement; + + if (primarySidebar) { + primarySidebarState = !primarySidebar.style.display || primarySidebar.style.display !== 'none'; + } + + if (secondarySidebar) { + secondarySidebarState = !secondarySidebar.style.display || secondarySidebar.style.display !== 'none'; + } + + if (terminalPanel) { + terminalPanelState = !terminalPanel.style.display || terminalPanel.style.display !== 'none'; + } + + if (extensionsPanel) { + extensionsPanelState = !extensionsPanel.style.display || extensionsPanel.style.display !== 'none'; + } + + updatePanelClasses(); + }, 100); +} \ No newline at end of file diff --git a/src/custom/updateHandler.ts b/src/custom/updateHandler.ts index 09b8d4a..1662fe0 100644 --- a/src/custom/updateHandler.ts +++ b/src/custom/updateHandler.ts @@ -1,6 +1,8 @@ import { CursorAnimation } from "./bonus/cursorAnimation"; import { addFocusHandler } from "./handlers/focusHandler"; import { initTabsHandler } from "./handlers/tabsHandler"; +import { initExplorerHandler } from "./handlers/explorerHandler"; +import { initSidebarHandler } from "./handlers/sidebarHandler"; import { Messenger } from "./messenger"; import { createCustomCSS, updateCustomCSS } from "./style"; @@ -43,4 +45,6 @@ console.log("VSCode-Animations: Successfully Installed!"); // Adding util js functions to the page to help with animations initTabsHandler(); + initExplorerHandler(); + initSidebarHandler(); })(); diff --git a/src/scss/Misc/Smooth-Mode.scss b/src/scss/Misc/Smooth-Mode.scss index c790197..ccc9e0d 100644 --- a/src/scss/Misc/Smooth-Mode.scss +++ b/src/scss/Misc/Smooth-Mode.scss @@ -3,10 +3,7 @@ } //Selects when not resizing or previewing -.monaco-workbench:not( - .monaco-workbench:has(.monaco-sash.active), - .monaco-workbench:has(iframe) - ) { +.monaco-workbench:not(.monaco-workbench:has(.monaco-sash.active)) { .monaco-workbench, .split-view-view, .editor-actions, @@ -27,3 +24,100 @@ } } } + +// Specific support for sidebar animations in all states +.monaco-workbench:not(.monaco-workbench:has(.monaco-sash.active)) { + .part.sidebar.left, + .part.sidebar.right, + .part.activitybar, + .part.panel, + .part.auxiliarybar { + &[style*="width"], + &[style*="height"], + &[style*="transform"], + &[style*="left"], + &[style*="right"], + &[style*="bottom"] { + transition-property: width, height, transform, left, right, bottom, opacity !important; + transition-duration: var(--smooth-windows-duration) !important; + transition-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1) !important; + } + } + + // Terminal panel specific animations + .part.panel { + &[style*="height"] { + transition-timing-function: cubic-bezier(0.25, 0.8, 0.25, 1) !important; + } + + .composite.panel { + &[style*="height"], + &[style*="transform"] { + transition-property: height, transform, opacity !important; + transition-duration: var(--smooth-windows-duration) !important; + transition-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1) !important; + } + } + } + + // Extensions panel and auxiliary bar animations + .part.auxiliarybar { + &[style*="width"] { + transition-timing-function: cubic-bezier(0.25, 0.8, 0.25, 1) !important; + } + } + + // Enhanced support when both sidebars are open + &.both-sidebars-open { + .part.sidebar, + .part.activitybar, + .part.panel, + .part.auxiliarybar { + &[style*="width"], + &[style*="height"] { + transition-timing-function: cubic-bezier(0.25, 0.8, 0.25, 1) !important; + transition-delay: 0ms !important; + } + } + + .split-view-view { + &[style*="width"], + &[style*="height"], + &[style*="left"], + &[style*="bottom"] { + transition-delay: 0ms !important; + transition-timing-function: cubic-bezier(0.25, 0.8, 0.25, 1) !important; + } + } + } + + // Enhanced support for all containers + .sidebar-container, + .composite-bar-container, + .activitybar-container, + .composite.viewlet, + .composite.panel, + .panel-container, + .auxiliarybar-container { + &[style*="width"], + &[style*="height"], + &[style*="transform"] { + transition-property: width, height, transform, opacity !important; + transition-duration: var(--smooth-windows-duration) !important; + transition-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1) !important; + } + } + + // Terminal and output panel content + .terminal-outer-container, + .terminal-wrapper, + .integrated-terminal, + .output-view { + &[style*="height"], + &[style*="transform"] { + transition-property: height, transform, opacity !important; + transition-duration: var(--smooth-windows-duration) !important; + transition-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1) !important; + } + } +}