mirror of
https://github.com/Mintplex-Labs/anything-llm.git
synced 2025-03-16 07:02:22 +00:00
Add support for hiding sidebar (#2809)
* Add support for hiding sidebar Support cmd/ctrl + shift +s for quick hide/show * patch sidebar padding on collapse * update Key for sidebar setting
This commit is contained in:
parent
426e2360b3
commit
e4a556d551
4 changed files with 162 additions and 41 deletions
|
@ -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`}
|
||||
></div>
|
||||
{/* 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`}
|
||||
></div>
|
||||
)}
|
||||
|
|
105
frontend/src/components/Sidebar/SidebarToggle/index.jsx
Normal file
105
frontend/src/components/Sidebar/SidebarToggle/index.jsx
Normal file
|
@ -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 (
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
className={`hidden md:block border-none bg-transparent outline-none ring-0 transition-left duration-500 ${showSidebar ? "left-[247px]" : "absolute top-[20px] left-[30px] z-10"}`}
|
||||
onClick={() => setShowSidebar((prev) => !prev)}
|
||||
data-tooltip-id="sidebar-toggle"
|
||||
data-tooltip-content={
|
||||
showSidebar
|
||||
? `Hide Sidebar (${shortcut})`
|
||||
: `Show Sidebar (${shortcut})`
|
||||
}
|
||||
aria-label={
|
||||
showSidebar
|
||||
? `Hide Sidebar (${shortcut})`
|
||||
: `Show Sidebar (${shortcut})`
|
||||
}
|
||||
>
|
||||
<SidebarSimple
|
||||
className="text-theme-text-secondary hover:text-theme-text-primary"
|
||||
size={24}
|
||||
/>
|
||||
</button>
|
||||
<Tooltip
|
||||
id="sidebar-toggle"
|
||||
place="top"
|
||||
delayShow={300}
|
||||
className="tooltip !text-xs z-99"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -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 (
|
||||
<div>
|
||||
<Link
|
||||
to={paths.home()}
|
||||
className="flex shrink-0 max-w-[55%] items-center justify-start mx-[38px] my-[18px]"
|
||||
aria-label="Home"
|
||||
>
|
||||
<img
|
||||
src={logo}
|
||||
alt="Logo"
|
||||
className="rounded max-h-[24px] object-contain"
|
||||
/>
|
||||
</Link>
|
||||
<>
|
||||
<div
|
||||
ref={sidebarRef}
|
||||
className="relative m-[16px] rounded-[16px] bg-theme-bg-sidebar border-[2px] border-theme-sidebar-border light:border-none min-w-[250px] p-[10px] h-[calc(100%-76px)]"
|
||||
style={{
|
||||
width: showSidebar ? "292px" : "0px",
|
||||
paddingLeft: showSidebar ? "0px" : "16px",
|
||||
}}
|
||||
className="transition-all duration-500"
|
||||
>
|
||||
<div className="flex flex-col h-full overflow-x-hidden">
|
||||
<div className="flex-grow flex flex-col min-w-[235px]">
|
||||
<div className="relative h-[calc(100%-60px)] flex flex-col w-full justify-between pt-[10px] overflow-y-scroll no-scroll">
|
||||
<div className="flex flex-col gap-y-2 pb-[60px] overflow-y-scroll no-scroll">
|
||||
<div className="flex gap-x-2 items-center justify-between">
|
||||
{(!user || user?.role !== "default") && (
|
||||
<button
|
||||
onClick={showNewWsModal}
|
||||
className="light:bg-[#C2E7FE] light:hover:bg-[#7CD4FD] flex flex-grow w-[75%] h-[44px] gap-x-2 py-[5px] px-2.5 mb-2 bg-white rounded-[8px] text-sidebar justify-center items-center hover:bg-opacity-80 transition-all duration-300"
|
||||
>
|
||||
<Plus size={18} weight="bold" />
|
||||
<p className="text-sidebar text-sm font-semibold">
|
||||
{t("new-workspace.title")}
|
||||
</p>
|
||||
</button>
|
||||
)}
|
||||
<div className="flex shrink-0 w-full justify-center my-[18px]">
|
||||
<div className="flex justify-between w-[250px] min-w-[250px]">
|
||||
<Link to={paths.home()} aria-label="Home">
|
||||
<img
|
||||
src={logo}
|
||||
alt="Logo"
|
||||
className={`rounded max-h-[24px] object-contain transition-opacity duration-500 ${showSidebar ? "opacity-100" : "opacity-0"}`}
|
||||
/>
|
||||
</Link>
|
||||
{canToggleSidebar && (
|
||||
<ToggleSidebarButton
|
||||
showSidebar={showSidebar}
|
||||
setShowSidebar={setShowSidebar}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
ref={sidebarRef}
|
||||
className="relative m-[16px] rounded-[16px] bg-theme-bg-sidebar border-[2px] border-theme-sidebar-border light:border-none min-w-[250px] p-[10px] h-[calc(100%-76px)]"
|
||||
>
|
||||
<div className="flex flex-col h-full overflow-x-hidden">
|
||||
<div className="flex-grow flex flex-col min-w-[235px]">
|
||||
<div className="relative h-[calc(100%-60px)] flex flex-col w-full justify-between pt-[10px] overflow-y-scroll no-scroll">
|
||||
<div className="flex flex-col gap-y-2 pb-[60px] overflow-y-scroll no-scroll">
|
||||
<div className="flex gap-x-2 items-center justify-between">
|
||||
{(!user || user?.role !== "default") && (
|
||||
<button
|
||||
onClick={showNewWsModal}
|
||||
className="light:bg-[#C2E7FE] light:hover:bg-[#7CD4FD] flex flex-grow w-[75%] h-[44px] gap-x-2 py-[5px] px-2.5 mb-2 bg-white rounded-[8px] text-sidebar justify-center items-center hover:bg-opacity-80 transition-all duration-300"
|
||||
>
|
||||
<Plus size={18} weight="bold" />
|
||||
<p className="text-sidebar text-sm font-semibold">
|
||||
{t("new-workspace.title")}
|
||||
</p>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<ActiveWorkspaces />
|
||||
</div>
|
||||
<ActiveWorkspaces />
|
||||
</div>
|
||||
</div>
|
||||
<div className="absolute bottom-0 left-0 right-0 pt-4 pb-3 rounded-b-[16px] bg-theme-bg-sidebar bg-opacity-80 backdrop-filter backdrop-blur-md z-10">
|
||||
<Footer />
|
||||
<div className="absolute bottom-0 left-0 right-0 pt-4 pb-3 rounded-b-[16px] bg-theme-bg-sidebar bg-opacity-80 backdrop-filter backdrop-blur-md z-1">
|
||||
<Footer />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{showingNewWsModal && <NewWorkspaceModal hideModal={hideNewWsModal} />}
|
||||
</div>
|
||||
{showingNewWsModal && <NewWorkspaceModal hideModal={hideNewWsModal} />}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -264,7 +264,7 @@ export default function ChatContainer({ workspace, knownHistory = [] }) {
|
|||
return (
|
||||
<div
|
||||
style={{ height: isMobile ? "100%" : "calc(100% - 32px)" }}
|
||||
className="transition-all duration-500 relative md:ml-[2px] md:mr-[16px] md:my-[16px] md:rounded-[16px] bg-theme-bg-secondary w-full h-full overflow-y-scroll no-scroll"
|
||||
className="transition-all duration-500 relative md:ml-[2px] md:mr-[16px] md:my-[16px] md:rounded-[16px] bg-theme-bg-secondary w-full h-full overflow-y-scroll no-scroll z-[2]"
|
||||
>
|
||||
{isMobile && <SidebarMobileHeader />}
|
||||
<DnDFileUploaderWrapper>
|
||||
|
|
Loading…
Add table
Reference in a new issue