From a38e9b9cb96f56970c1fe7a5eb7218f7e0005e60 Mon Sep 17 00:00:00 2001 From: Bohdan Triapitsyn Date: Wed, 20 May 2026 20:43:13 +0300 Subject: [PATCH] feat(ui): animate sidebar open/close MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sidebars now slide open/closed with a 200ms cubic-bezier(0.22, 1, 0.36, 1) transition on width. Inline transitionProperty/Duration/TimingFunction are used directly on the aside so the change is browser-driven rather than relying on Tailwind arbitrary classes that didn't reliably trigger the width transition. Inner sidebar content is pinned to the open width with shrink-0 so it stays full-size while the outer aside collapses around it, eliminating the vertical jitter that came from content reflowing when its container shrank. The chat-frame keeps a constant 1px border and 10px radius on all four sides — only the left/right border color toggles between border/50 and transparent — so no layout reflow happens when sidebars open. Mask-corner overlays are always mounted and animate their left/right offset and opacity in lockstep with the sidebars instead of mounting/unmounting. --- .../ui/src/components/layout/MainLayout.tsx | 106 +++++++++--------- .../ui/src/components/layout/RightSidebar.tsx | 27 +++-- packages/ui/src/components/layout/Sidebar.tsx | 28 +++-- 3 files changed, 84 insertions(+), 77 deletions(-) diff --git a/packages/ui/src/components/layout/MainLayout.tsx b/packages/ui/src/components/layout/MainLayout.tsx index 7b39875d..40889c77 100644 --- a/packages/ui/src/components/layout/MainLayout.tsx +++ b/packages/ui/src/components/layout/MainLayout.tsx @@ -606,58 +606,54 @@ export const MainLayout: React.FC = () => {
- {isSidebarOpen ? ( - <> -
-
- - ) : null} - {isRightSidebarOpen ? ( - <> -
-
- - ) : null} +
+
+
+
{
diff --git a/packages/ui/src/components/layout/RightSidebar.tsx b/packages/ui/src/components/layout/RightSidebar.tsx index 44c59f68..d671c6ac 100644 --- a/packages/ui/src/components/layout/RightSidebar.tsx +++ b/packages/ui/src/components/layout/RightSidebar.tsx @@ -34,12 +34,13 @@ export const RightSidebar: React.FC = ({ isOpen, children, cl return; } - sidebar.style.setProperty('--oc-right-sidebar-width', `${nextWidth}px`); + sidebar.style.width = `${nextWidth}px`; + sidebar.style.minWidth = `${nextWidth}px`; + sidebar.style.maxWidth = `${nextWidth}px`; }, []); - const appliedWidth = isOpen - ? Math.min(RIGHT_SIDEBAR_MAX_WIDTH, Math.max(RIGHT_SIDEBAR_MIN_WIDTH, rightSidebarWidth || RIGHT_SIDEBAR_CONTENT_WIDTH)) - : 0; + const openWidth = Math.min(RIGHT_SIDEBAR_MAX_WIDTH, Math.max(RIGHT_SIDEBAR_MIN_WIDTH, rightSidebarWidth || RIGHT_SIDEBAR_CONTENT_WIDTH)); + const appliedWidth = isOpen ? openWidth : 0; const handlePointerDown = (event: React.PointerEvent) => { if (!isOpen) { @@ -101,22 +102,25 @@ export const RightSidebar: React.FC = ({ isOpen, children, cl } }, [isResizing]); + const currentWidth = isResizing ? (resizingWidthRef.current ?? appliedWidth) : appliedWidth; + return (