diff --git a/frontend/src/components/Sidebar/ActiveWorkspaces/ThreadContainer/ThreadItem/index.jsx b/frontend/src/components/Sidebar/ActiveWorkspaces/ThreadContainer/ThreadItem/index.jsx index 4947de08ff5..4c12b05b51c 100644 --- a/frontend/src/components/Sidebar/ActiveWorkspaces/ThreadContainer/ThreadItem/index.jsx +++ b/frontend/src/components/Sidebar/ActiveWorkspaces/ThreadContainer/ThreadItem/index.jsx @@ -41,8 +41,8 @@ export default function ThreadItem({ style={{ width: THREAD_CALLOUT_DETAIL_WIDTH / 2 }} className={`${ isActive - ? "border-l-2 border-b-2 border-white light:border-theme-sidebar-border z-30" - : "border-l border-b border-[#6F6F71] light:border-theme-sidebar-border z-10" + ? "border-l-2 border-b-2 border-white light:border-theme-sidebar-border z-[2]" + : "border-l border-b border-[#6F6F71] light:border-theme-sidebar-border z-[1]" } h-[50%] absolute top-0 left-2 rounded-bl-lg`} > {/* Downstroke border for next item */} @@ -51,8 +51,8 @@ export default function ThreadItem({ style={{ width: THREAD_CALLOUT_DETAIL_WIDTH / 2 }} className={`${ idx <= activeIdx && !isActive - ? "border-l-2 border-white light:border-theme-sidebar-border z-20" - : "border-l border-[#6F6F71] light:border-theme-sidebar-border z-10" + ? "border-l-2 border-white light:border-theme-sidebar-border z-[2]" + : "border-l border-[#6F6F71] light:border-theme-sidebar-border z-[1]" } h-[100%] absolute top-0 left-2`} > )} diff --git a/frontend/src/components/Sidebar/SidebarToggle/index.jsx b/frontend/src/components/Sidebar/SidebarToggle/index.jsx new file mode 100644 index 00000000000..a0f47b6b4f1 --- /dev/null +++ b/frontend/src/components/Sidebar/SidebarToggle/index.jsx @@ -0,0 +1,105 @@ +import React, { useEffect, useState } from "react"; +import { SidebarSimple } from "@phosphor-icons/react"; +import paths from "@/utils/paths"; +import { Tooltip } from "react-tooltip"; +const SIDEBAR_TOGGLE_STORAGE_KEY = "anythingllm_sidebar_toggle"; + +/** + * Returns the previous state of the sidebar from localStorage. + * If the sidebar was closed, returns false. + * If the sidebar was open, returns true. + * If the sidebar state is not set, returns true. + * @returns {boolean} + */ +function previousSidebarState() { + const previousState = window.localStorage.getItem(SIDEBAR_TOGGLE_STORAGE_KEY); + if (previousState === "closed") return false; + return true; +} + +export function useSidebarToggle() { + const [showSidebar, setShowSidebar] = useState(previousSidebarState()); + const [canToggleSidebar, setCanToggleSidebar] = useState(true); + + useEffect(() => { + function checkPath() { + const currentPath = window.location.pathname; + const isVisible = + currentPath === paths.home() || + /^\/workspace\/[^\/]+$/.test(currentPath) || + /^\/workspace\/[^\/]+\/t\/[^\/]+$/.test(currentPath); + setCanToggleSidebar(isVisible); + } + checkPath(); + }, [window.location.pathname]); + + useEffect(() => { + function toggleSidebar(e) { + if (!canToggleSidebar) return; + if ( + (e.ctrlKey || e.metaKey) && + e.shiftKey && + e.key.toLowerCase() === "s" + ) { + setShowSidebar((prev) => { + const newState = !prev; + window.localStorage.setItem( + SIDEBAR_TOGGLE_STORAGE_KEY, + newState ? "open" : "closed" + ); + return newState; + }); + } + } + window.addEventListener("keydown", toggleSidebar); + return () => { + window.removeEventListener("keydown", toggleSidebar); + }; + }, []); + + useEffect(() => { + window.localStorage.setItem( + SIDEBAR_TOGGLE_STORAGE_KEY, + showSidebar ? "open" : "closed" + ); + }, [showSidebar]); + + return { showSidebar, setShowSidebar, canToggleSidebar }; +} + +export function ToggleSidebarButton({ showSidebar, setShowSidebar }) { + const isMac = navigator.userAgent.includes("Mac"); + const shortcut = isMac ? "⌘ + Shift + S" : "Ctrl + Shift + S"; + + return ( + <> + + + + ); +} diff --git a/frontend/src/components/Sidebar/index.jsx b/frontend/src/components/Sidebar/index.jsx index cec1604c0ba..04a7fe43471 100644 --- a/frontend/src/components/Sidebar/index.jsx +++ b/frontend/src/components/Sidebar/index.jsx @@ -11,11 +11,13 @@ import SettingsButton from "../SettingsButton"; import { Link } from "react-router-dom"; import paths from "@/utils/paths"; import { useTranslation } from "react-i18next"; +import { useSidebarToggle, ToggleSidebarButton } from "./SidebarToggle"; export default function Sidebar() { const { user } = useUser(); const { logo } = useLogo(); const sidebarRef = useRef(null); + const { showSidebar, setShowSidebar, canToggleSidebar } = useSidebarToggle(); const { showing: showingNewWsModal, showModal: showNewWsModal, @@ -24,50 +26,64 @@ export default function Sidebar() { const { t } = useTranslation(); return ( -
- - Logo - + <>
-
-
-
-
-
- {(!user || user?.role !== "default") && ( - - )} +
+
+ + Logo + + {canToggleSidebar && ( + + )} +
+
+
+
+
+
+
+
+ {(!user || user?.role !== "default") && ( + + )} +
+
-
-
-
-
+
+
+
+ {showingNewWsModal && }
- {showingNewWsModal && } -
+ ); } diff --git a/frontend/src/components/WorkspaceChat/ChatContainer/index.jsx b/frontend/src/components/WorkspaceChat/ChatContainer/index.jsx index ad109e74e55..b0ffcbfc88f 100644 --- a/frontend/src/components/WorkspaceChat/ChatContainer/index.jsx +++ b/frontend/src/components/WorkspaceChat/ChatContainer/index.jsx @@ -264,7 +264,7 @@ export default function ChatContainer({ workspace, knownHistory = [] }) { return (
{isMobile && }