Improve mobile conversation drawer layering and empty state (#59) (#60)
Deploy Beta / unit-tests (push) Successful in 11s
Unit Tests / test (push) Successful in 11s
Deploy Beta / deploy-beta (push) Successful in 3m3s

## Summary
- Closes #59
- Mobile conversation drawer is now a fixed sheet with stronger stacking over dashboard content
- Adds explicit close (X) control and empty-state copy when there are no conversations
- Keeps existing close-on-select / New Chat behavior

## Test plan
- [ ] Mobile: open Conversations drawer — sheet + overlay appear above content
- [ ] Tap X or overlay — drawer closes
- [ ] Empty conversation list shows guidance text
- [ ] Select conversation / New Chat closes drawer and chat still works
- [ ] Desktop sidebar layout unchangedReviewed-on: #60
This commit was merged in pull request #60.
This commit is contained in:
2026-07-29 05:04:33 -07:00
parent e6ae9d6b1e
commit ea40700fd3
@@ -2,7 +2,7 @@ import React, { useContext, useEffect, useRef, useState } from "react";
import styled, { ThemeContext } from "styled-components";
import { Formik, Form, Field } from "formik";
import * as Yup from "yup";
import { AttachFile, Delete, Send, Menu } from "@mui/icons-material"; // Keeping icons for now, can replace later if needed
import { AttachFile, Delete, Send, Menu, Close } from "@mui/icons-material"; // Keeping icons for now, can replace later if needed
import { Tooltip } from "@mui/material";
import Markdown from "markdown-to-jsx";
@@ -44,10 +44,15 @@ const Sidebar = styled.div<{ $isOpen: boolean }>`
transition: transform 0.3s ease;
@media (max-width: 768px) {
position: absolute;
position: fixed;
top: 0;
left: 0;
width: min(85vw, 320px);
height: 100vh;
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'};
z-index: 120;
}
`;
@@ -88,7 +93,7 @@ const Overlay = styled.div<{ $isOpen: boolean }>`
height: 100vh;
background: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(2px);
z-index: 15;
z-index: 110;
opacity: ${({ $isOpen }) => $isOpen ? 1 : 0};
pointer-events: ${({ $isOpen }) => $isOpen ? 'auto' : 'none'};
transition: opacity 0.3s ease;
@@ -98,6 +103,36 @@ const Overlay = styled.div<{ $isOpen: boolean }>`
}
`;
const MobileSidebarHeader = styled.div`
display: none;
@media (max-width: 768px) {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 1rem;
color: ${({ theme }) => theme.colors.text};
font-weight: 700;
font-size: 1rem;
}
`;
const MobileSidebarCloseButton = styled.button`
display: none;
@media (max-width: 768px) {
display: flex;
align-items: center;
justify-content: center;
border: none;
background: transparent;
color: ${({ theme }) => theme.colors.text};
cursor: pointer;
border-radius: 999px;
padding: 0.3rem;
}
`;
const MainContent = styled.div`
flex: 1;
height: 100%;
@@ -384,6 +419,12 @@ const AsyncDashboardInner = (): JSX.Element => {
</MobileSidebarToggle>
<Sidebar $isOpen={isSidebarOpen}>
<MobileSidebarHeader>
<span>Conversations</span>
<MobileSidebarCloseButton onClick={() => setIsSidebarOpen(false)} aria-label="Close conversations drawer">
<Close fontSize="small" />
</MobileSidebarCloseButton>
</MobileSidebarHeader>
<NewChatButton onClick={() => {
setSelectedConversation(undefined);
setIsSidebarOpen(false);
@@ -391,7 +432,17 @@ const AsyncDashboardInner = (): JSX.Element => {
+ New Chat
</NewChatButton>
<div style={{ overflowY: 'auto', flex: 1 }}>
{conversations.map((convo) => (
{conversations.length === 0 ? (
<div style={{
color: theme?.darkMode ? 'rgba(255,255,255,0.55)' : 'rgba(0,0,0,0.55)',
fontSize: '0.9rem',
lineHeight: 1.5,
padding: '0.25rem 0.5rem'
}}>
No conversations yet. Start with <strong>+ New Chat</strong>.
</div>
) : (
conversations.map((convo) => (
<ConversationItem
key={convo.id}
$active={convo.id === selectedConversation}
@@ -414,7 +465,8 @@ const AsyncDashboardInner = (): JSX.Element => {
</IconButton>
)}
</ConversationItem>
))}
))
)}
</div>
</Sidebar>