diff --git a/llm-fe/src/llm-fe/pages/AsyncDashboard2/AsyncDashboard2.tsx b/llm-fe/src/llm-fe/pages/AsyncDashboard2/AsyncDashboard2.tsx index 8c9aa1c..c27209f 100644 --- a/llm-fe/src/llm-fe/pages/AsyncDashboard2/AsyncDashboard2.tsx +++ b/llm-fe/src/llm-fe/pages/AsyncDashboard2/AsyncDashboard2.tsx @@ -2,7 +2,7 @@ import React, { useContext, useEffect, useRef, useState } from "react"; import styled, { ThemeContext } from "styled-components"; import { Formik, Form, Field, ErrorMessage } from "formik"; import * as Yup from "yup"; -import { AttachFile, Delete, Send } from "@mui/icons-material"; // Keeping icons for now, can replace later if needed +import { AttachFile, Delete, Send, Menu } from "@mui/icons-material"; // Keeping icons for now, can replace later if needed import { Tooltip } from "@mui/material"; import Markdown from "markdown-to-jsx"; @@ -36,7 +36,7 @@ const PageContainer = styled.div` /* background-color: ${({ theme }) => theme.colors.background}; Removed to show particles */ `; -const Sidebar = styled.div` +const Sidebar = styled.div<{ $isOpen: boolean }>` width: 280px; height: 100%; background: ${({ theme }) => theme.darkMode ? 'rgba(0, 0, 0, 0.6)' : 'rgba(255, 255, 255, 0.6)'}; @@ -46,12 +46,61 @@ const Sidebar = styled.div` flex-direction: column; padding: 1rem; padding-top: 5rem; // Account for header - z-index: 10; + z-index: 20; transition: transform 0.3s ease; @media (max-width: 768px) { position: absolute; - transform: translateX(-100%); + transform: ${({ $isOpen }) => $isOpen ? 'translateX(0)' : 'translateX(-100%)'}; + background: ${({ theme }) => theme.darkMode ? 'rgba(0, 0, 0, 0.95)' : 'rgba(255, 255, 255, 0.95)'}; + box-shadow: ${({ $isOpen }) => $isOpen ? '0 0 20px rgba(0,0,0,0.5)' : 'none'}; + } +`; + +const MobileSidebarToggle = styled.button` + display: none; + position: absolute; + top: 5.5rem; /* Below header */ + left: 1rem; + z-index: 15; + padding: 0.5rem 1rem; + background: ${({ theme }) => theme.main}; + color: white; + border: none; + border-radius: 2rem; + font-weight: 600; + box-shadow: 0 4px 12px rgba(0,0,0,0.2); + cursor: pointer; + transition: all 0.2s ease; + + &:hover { + transform: translateY(-2px); + box-shadow: 0 6px 16px rgba(0,0,0,0.3); + } + + @media (max-width: 768px) { + display: flex; + align-items: center; + gap: 0.5rem; + } +`; + +const Overlay = styled.div<{ $isOpen: boolean }>` + display: none; + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + background: rgba(0, 0, 0, 0.5); + backdrop-filter: blur(2px); + z-index: 15; + opacity: ${({ $isOpen }) => $isOpen ? 1 : 0}; + pointer-events: ${({ $isOpen }) => $isOpen ? 'auto' : 'none'}; + transition: opacity 0.3s ease; + + @media (max-width: 768px) { + display: block; } `; @@ -266,6 +315,7 @@ const AsyncDashboardInner = ({ }): JSX.Element => { const conversationRef = useRef(conversationDetails); const theme = useContext(ThemeContext); const textareaRef = useRef(null); + const [isSidebarOpen, setIsSidebarOpen] = useState(false); async function GetAnnouncements() { const response: AxiosResponse = @@ -326,8 +376,18 @@ const AsyncDashboardInner = ({ }): JSX.Element => { - - setSelectedConversation(undefined)}> + setIsSidebarOpen(false)} /> + + setIsSidebarOpen(true)}> + + Conversations + + + + { + setSelectedConversation(undefined); + setIsSidebarOpen(false); + }}> + New Chat
@@ -335,7 +395,10 @@ const AsyncDashboardInner = ({ }): JSX.Element => { setSelectedConversation(convo.id)} + onClick={() => { + setSelectedConversation(convo.id); + setIsSidebarOpen(false); + }} > {convo.title || "New Conversation"} {convo.id === selectedConversation && (