Merge pull request #6840 from eesoymilk/fix/sidebar-toggle-animation

fix(sidebar): animate the sidebar toggle instead of snapping
This commit is contained in:
Alexandre Teixeira
2026-10-28 18:15:15 +00:00
committed by GitHub
3 changed files with 106 additions and 65 deletions
+18 -3
View File
@@ -170,6 +170,15 @@ export function initSidebarLayout(Storage, opts) {
syncRailSide();
}
// Move the closed drawer to the other edge without transitioning its
// transform across the screen, so it then slides in from the edge it opens on.
function _setSidebarSideInstantly(sidebar, right) {
sidebar.style.setProperty('transition', 'none', 'important');
sidebar.classList.toggle('right-side', right);
void sidebar.offsetWidth;
sidebar.style.removeProperty('transition');
}
// Deliberate "open the sidebar" used by the mobile swipe gesture (wired at
// module scope). It MUST set _userToggledSidebar so the auto-collapse
// MutationObserver doesn't immediately re-hide it (the swipe was opening it,
@@ -189,7 +198,7 @@ export function initSidebarLayout(Storage, opts) {
if (side === 'left' || side === 'right') {
const wantRight = side === 'right';
if (sidebar.classList.contains('right-side') !== wantRight) {
sidebar.classList.toggle('right-side', wantRight);
_setSidebarSideInstantly(sidebar, wantRight);
// Swipe-selected sides are temporary on compact/mobile layouts. Do
// not overwrite the user's desktop sidebar preference.
if (window.innerWidth >= 768) {
@@ -227,7 +236,7 @@ export function initSidebarLayout(Storage, opts) {
// Mobile: the hamburger always opens the sidebar from the RIGHT.
// (Not persisted — keeps the desktop side preference untouched.)
if (!sidebar.classList.contains('right-side')) {
sidebar.classList.add('right-side');
_setSidebarSideInstantly(sidebar, true);
if (documentModule && documentModule.swapSide) { try { documentModule.swapSide(); } catch (_) {} }
}
// Opening sidebar — blur keyboard first, then open after layout settles
@@ -312,14 +321,20 @@ export function initSidebarLayout(Storage, opts) {
_wasAutoCollapsed = true;
syncRailSide();
} else if (window.innerWidth >= AUTO_COLLAPSE_WIDTH && isHidden && _wasAutoCollapsed) {
// Only restore if chat won't be too narrow
// Only restore if chat won't be too narrow. Suppress the width
// transition and sync the mode classes (ody-sidebar-mini also forces
// width 0) so the reflow measures the sidebar at its full width.
sidebar.style.transition = 'none';
sidebar.classList.remove('hidden');
syncRailSide();
void document.body.offsetWidth; // reflow
if (chatContainer && chatContainer.offsetWidth < MIN_CHAT_WIDTH) {
sidebar.classList.add('hidden');
} else {
_wasAutoCollapsed = false;
}
void document.body.offsetWidth;
sidebar.style.transition = '';
syncRailSide();
}
}