diff --git a/frontend/src/components/Sidebar/ActiveWorkspaces/index.jsx b/frontend/src/components/Sidebar/ActiveWorkspaces/index.jsx index 4e423a6dd91cd3b671e263c66ec5c6629264f004..fe14bf9f2ca6b58f8396c9a4de22c15bbc9a1aff 100644 --- a/frontend/src/components/Sidebar/ActiveWorkspaces/index.jsx +++ b/frontend/src/components/Sidebar/ActiveWorkspaces/index.jsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect, useCallback } from "react"; import * as Skeleton from "react-loading-skeleton"; import "react-loading-skeleton/dist/skeleton.css"; import Workspace from "../../../models/workspace"; @@ -14,9 +14,10 @@ import useUser from "../../../hooks/useUser"; export default function ActiveWorkspaces() { const { slug } = useParams(); const [loading, setLoading] = useState(true); - const [settingHover, setSettingHover] = useState(false); + const [settingHover, setSettingHover] = useState({}); const [workspaces, setWorkspaces] = useState([]); const [selectedWs, setSelectedWs] = useState(null); + const [hoverStates, setHoverStates] = useState({}); const { showing, showModal, hideModal } = useManageWorkspaceModal(); const { user } = useUser(); @@ -29,6 +30,22 @@ export default function ActiveWorkspaces() { getWorkspaces(); }, []); + const handleMouseEnter = useCallback((workspaceId) => { + setHoverStates((prev) => ({ ...prev, [workspaceId]: true })); + }, []); + + const handleMouseLeave = useCallback((workspaceId) => { + setHoverStates((prev) => ({ ...prev, [workspaceId]: false })); + }, []); + + const handleGearMouseEnter = useCallback((workspaceId) => { + setSettingHover((prev) => ({ ...prev, [workspaceId]: true })); + }, []); + + const handleGearMouseLeave = useCallback((workspaceId) => { + setSettingHover((prev) => ({ ...prev, [workspaceId]: false })); + }, []); + if (loading) { return ( <> @@ -48,10 +65,14 @@ export default function ActiveWorkspaces() { <> {workspaces.map((workspace) => { const isActive = workspace.slug === slug; + const isHovered = hoverStates[workspace.id]; + const isGearHovered = settingHover[workspace.id]; return ( <div key={workspace.id} className="flex gap-x-2 items-center justify-between" + onMouseEnter={() => handleMouseEnter(workspace.id)} + onMouseLeave={() => handleMouseLeave(workspace.id)} > <a href={isActive ? null : paths.workspace.chat(workspace.slug)} @@ -82,17 +103,21 @@ export default function ActiveWorkspaces() { </p> </div> <button - onMouseEnter={() => setSettingHover(true)} - onMouseLeave={() => setSettingHover(false)} - onClick={() => { + type="button" + onClick={(e) => { + e.preventDefault(); setSelectedWs(workspace); showModal(); }} + onMouseEnter={() => handleGearMouseEnter(workspace.id)} + onMouseLeave={() => handleGearMouseLeave(workspace.id)} className="rounded-md flex items-center justify-center text-white ml-auto" > <GearSix - weight={settingHover ? "fill" : "regular"} - hidden={!isActive || user?.role === "default"} + weight={isGearHovered ? "fill" : "regular"} + hidden={ + (!isActive && !isHovered) || user?.role === "default" + } className="h-[20px] w-[20px] transition-all duration-300" /> </button> diff --git a/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/index.jsx b/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/index.jsx index 036bb03895a4e3d24fcadde4f06dffd1514bfe8d..1de2504b7232c24f5a47338ea607f8ccacf65112 100644 --- a/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/index.jsx +++ b/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/index.jsx @@ -26,7 +26,7 @@ export default function ChatHistory({ history = [], workspace }) { const debouncedScroll = debounce(handleScroll, 100); useEffect(() => { - if(!chatHistoryRef.current) return null; + if (!chatHistoryRef.current) return null; const chatHistoryElement = chatHistoryRef.current; chatHistoryElement.addEventListener("scroll", debouncedScroll);