diff --git a/packages/bruno-app/src/components/Icons/IconSidebarToggle/index.js b/packages/bruno-app/src/components/Icons/IconSidebarToggle/index.js new file mode 100644 index 000000000..bad3221fb --- /dev/null +++ b/packages/bruno-app/src/components/Icons/IconSidebarToggle/index.js @@ -0,0 +1,28 @@ +import React from 'react'; + +const IconSidebarToggle = ({ collapsed = false, size = 16, strokeWidth = 1.5, className = '', ...rest }) => { + return ( + + + + + {!collapsed && ( + + )} + + ); +}; + +export default IconSidebarToggle; \ No newline at end of file diff --git a/packages/bruno-app/src/components/RequestTabs/index.js b/packages/bruno-app/src/components/RequestTabs/index.js index d50d528b3..fcba790a6 100644 --- a/packages/bruno-app/src/components/RequestTabs/index.js +++ b/packages/bruno-app/src/components/RequestTabs/index.js @@ -18,6 +18,7 @@ const RequestTabs = () => { const activeTabUid = useSelector((state) => state.tabs.activeTabUid); const collections = useSelector((state) => state.collections.collections); const leftSidebarWidth = useSelector((state) => state.app.leftSidebarWidth); + const sidebarCollapsed = useSelector((state) => state.app.sidebarCollapsed); const screenWidth = useSelector((state) => state.app.screenWidth); const getTabClassname = (tab, index) => { @@ -49,7 +50,8 @@ const RequestTabs = () => { const activeCollection = find(collections, (c) => c.uid === activeTab.collectionUid); const collectionRequestTabs = filter(tabs, (t) => t.collectionUid === activeTab.collectionUid); - const maxTablistWidth = screenWidth - leftSidebarWidth - 150; + const effectiveSidebarWidth = sidebarCollapsed ? 0 : leftSidebarWidth; + const maxTablistWidth = screenWidth - effectiveSidebarWidth - 150; const tabsWidth = collectionRequestTabs.length * 150 + 34; // 34: (+)icon const showChevrons = maxTablistWidth < tabsWidth; diff --git a/packages/bruno-app/src/components/Sidebar/CreateCollection/index.js b/packages/bruno-app/src/components/Sidebar/CreateCollection/index.js index 7b331c42c..3eb6707e0 100644 --- a/packages/bruno-app/src/components/Sidebar/CreateCollection/index.js +++ b/packages/bruno-app/src/components/Sidebar/CreateCollection/index.js @@ -13,6 +13,7 @@ import { IconArrowBackUp, IconEdit } from '@tabler/icons'; import Help from 'components/Help'; import { multiLineMsg } from "utils/common"; import { formatIpcError } from "utils/common/error"; +import { toggleSidebarCollapse } from 'providers/ReduxStore/slices/app'; const CreateCollection = ({ onClose }) => { const inputRef = useRef(); @@ -45,6 +46,7 @@ const CreateCollection = ({ onClose }) => { dispatch(createCollection(values.collectionName, values.collectionFolderName, values.collectionLocation)) .then(() => { toast.success('Collection created!'); + dispatch(toggleSidebarCollapse()); onClose(); }) .catch((e) => toast.error(multiLineMsg('An error occurred while creating the collection', formatIpcError(e)))); diff --git a/packages/bruno-app/src/components/Sidebar/StyledWrapper.js b/packages/bruno-app/src/components/Sidebar/StyledWrapper.js index e64c7a3f4..8bbe696fe 100644 --- a/packages/bruno-app/src/components/Sidebar/StyledWrapper.js +++ b/packages/bruno-app/src/components/Sidebar/StyledWrapper.js @@ -5,6 +5,7 @@ const Wrapper = styled.div` aside { background-color: ${(props) => props.theme.sidebar.bg}; + overflow: hidden; .collection-title { line-height: 1.5; @@ -50,6 +51,7 @@ const Wrapper = styled.div` background-color: transparent; width: 6px; right: -3px; + transition: opacity 0.2s ease; &:hover div.drag-request-border { width: 2px; diff --git a/packages/bruno-app/src/components/Sidebar/index.js b/packages/bruno-app/src/components/Sidebar/index.js index 1ba71b1ab..fd0423bcd 100644 --- a/packages/bruno-app/src/components/Sidebar/index.js +++ b/packages/bruno-app/src/components/Sidebar/index.js @@ -1,36 +1,37 @@ import TitleBar from './TitleBar'; import Collections from './Collections'; import StyledWrapper from './StyledWrapper'; -import { useApp } from 'providers/App'; -import { useState, useEffect } from 'react'; +import { useState, useEffect, useRef } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { updateLeftSidebarWidth, updateIsDragging } from 'providers/ReduxStore/slices/app'; -import { useTheme } from 'providers/Theme'; const MIN_LEFT_SIDEBAR_WIDTH = 221; const MAX_LEFT_SIDEBAR_WIDTH = 600; const Sidebar = () => { const leftSidebarWidth = useSelector((state) => state.app.leftSidebarWidth); - const { version } = useApp(); + const sidebarCollapsed = useSelector((state) => state.app.sidebarCollapsed); const [asideWidth, setAsideWidth] = useState(leftSidebarWidth); - - const { storedTheme } = useTheme(); + const lastWidthRef = useRef(leftSidebarWidth); const dispatch = useDispatch(); const [dragging, setDragging] = useState(false); + const currentWidth = sidebarCollapsed ? 0 : asideWidth; + + // Clamp helper keeps width in allowed range + const clamp = (value, min, max) => Math.min(max, Math.max(min, value)); + const handleMouseMove = (e) => { - if (dragging) { - e.preventDefault(); - let width = e.clientX + 2; - if (width < MIN_LEFT_SIDEBAR_WIDTH || width > MAX_LEFT_SIDEBAR_WIDTH) { - return; - } - setAsideWidth(width); - } + if (!dragging || sidebarCollapsed) return; + e.preventDefault(); + const nextWidth = clamp(e.clientX + 2, MIN_LEFT_SIDEBAR_WIDTH, MAX_LEFT_SIDEBAR_WIDTH); + if (Math.abs(nextWidth - lastWidthRef.current) < 3) return; + lastWidthRef.current = nextWidth; + setAsideWidth(nextWidth); }; + const handleMouseUp = (e) => { if (dragging) { e.preventDefault(); @@ -49,6 +50,9 @@ const Sidebar = () => { }; const handleDragbarMouseDown = (e) => { e.preventDefault(); + if (sidebarCollapsed) { + return; + } setDragging(true); dispatch( updateIsDragging({ @@ -73,7 +77,7 @@ const Sidebar = () => { return ( -