diff --git a/.env.example b/.env.example index e3b8af5..287d886 100644 --- a/.env.example +++ b/.env.example @@ -10,5 +10,6 @@ MLFLOW_TRACKING_URI=http://localhost:5000 MLFLOW_ARTIFACT_LOCATION=logs/mlflow FASTAPI_HOST=0.0.0.0 FASTAPI_PORT=8000 +REACT_APP_API_URL=http://127.0.0.1:8000 ENV=development DEBUG=True \ No newline at end of file diff --git a/configs/settings.yaml b/configs/settings.yaml deleted file mode 100644 index e69de29..0000000 diff --git a/frontend/src/App.css b/frontend/src/App.css index 605d14d..201bb9f 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -110,12 +110,20 @@ header.header { overflow: hidden; } -/* SIDEBAR */ -aside.sidebar { +/* SIDEBAR CONTAINER (New wrapper for mobile logic) */ +.sidebar-container { width: var(--sidebar); flex-shrink: 0; + height: 100%; background: var(--surface); border-right: 1px solid var(--border); + z-index: 50; + transition: left 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} + +/* SIDEBAR */ +aside.sidebar { + width: 100%; display: flex; flex-direction: column; overflow-y: auto; @@ -522,3 +530,95 @@ aside.sidebar { text-align: right; font-family: 'DM Mono', monospace; } + +/* --- MOBILE RESPONSIVE RULES --- */ + +/* Hide the hamburger menu and overlay on desktop */ +.mobile-menu-toggle { + display: none; +} + +.mobile-overlay { + display: block; + position: absolute; + top: var(--header); /* Start below the fixed header */ + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.4); + z-index: 40; + backdrop-filter: blur(2px); + } + +@media (max-width: 768px) { + header.header { + padding: 0 16px; + } + + /* Show hamburger menu */ + .mobile-menu-toggle { + display: block; + } + + /* Make layout relative for absolute positioning of sidebar */ + .layout { + position: relative; + flex-direction: column; + } + + /* Turn Sidebar into a slide-out drawer */ + .sidebar-container { + position: absolute; + top: var(--header); /* Start below the fixed header */ + bottom: 0; /* Stretch to the bottom */ + height: auto; /* Override the desktop 100% height */ + left: -100%; + box-shadow: 4px 0 24px rgba(0, 0, 0, 0.15); + } + + /* Slide in when 'open' */ + .sidebar-container.open { + left: 0; + } + + /* Stronger shadow in dark mode */ + body.dark-mode .sidebar-container.open { + box-shadow: 4px 0 24px rgba(0, 0, 0, 0.6); + } + + /* Chat window fills screen */ + .chat-window { + width: 100%; + } + + /* Show the darkening overlay */ + .mobile-overlay { + display: block; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.4); + z-index: 40; + backdrop-filter: blur(2px); + } + + /* Adjust message padding and widths */ + .messages { + padding: 16px; + } + + .message-user .bubble { + max-width: 90%; /* Let bubbles be wider on small screens */ + } + + .input-area { + padding: 12px 16px; + } + + /* Hide the "Enter to send" hint on mobile */ + .input-hint { + display: none; + } +} \ No newline at end of file diff --git a/frontend/src/App.js b/frontend/src/App.js index f8947d2..4e3bc1d 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -1,5 +1,5 @@ -import React, {useLayoutEffect, useState} from 'react'; -import { Sun, Moon } from 'lucide-react'; +import React, { useLayoutEffect, useState } from 'react'; +import { Sun, Moon, Menu, X } from 'lucide-react'; import Sidebar from './components/Sidebar'; import ChatWindow from './components/ChatWindow'; import './App.css'; @@ -12,6 +12,7 @@ function App() { const [messages, setMessages] = useState([]); const [loading, setLoading] = useState(false); const [result, setResult] = useState(null); + const [isSidebarOpen, setIsSidebarOpen] = useState(false); const [darkMode, setDarkMode] = useState(() => { const saved = localStorage.getItem('theme'); return saved ? saved === 'dark' : true; @@ -29,9 +30,14 @@ function App() { }); }; + const closeSidebar = () => setIsSidebarOpen(false); + const handleSubmit = async (fhirData = {}) => { if ((!query.trim() && !fhirData.has_fhir) || loading) return; + // Close the sidebar automatically on mobile when a query is sent + closeSidebar(); + const userMessage = { role: 'user', text: query || `FHIR ${fhirData.fhir_resource_type}/${fhirData.fhir_resource_id}` @@ -78,22 +84,39 @@ function App() { return (