Detailed changes
@@ -61,6 +61,7 @@ function App() {
const [conversations, setConversations] = useState<Conversation[]>([]);
const [currentConversationId, setCurrentConversationId] = useState<string | null>(null);
const [drawerOpen, setDrawerOpen] = useState(false);
+ const [drawerCollapsed, setDrawerCollapsed] = useState(false);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const initialSlugResolved = useRef(false);
@@ -146,6 +147,10 @@ function App() {
setDrawerOpen(false);
};
+ const toggleDrawerCollapsed = () => {
+ setDrawerCollapsed((prev) => !prev);
+ };
+
const updateConversation = (updatedConversation: Conversation) => {
setConversations((prev) =>
prev.map((conv) =>
@@ -229,7 +234,9 @@ function App() {
{/* Conversations drawer */}
<ConversationDrawer
isOpen={drawerOpen}
+ isCollapsed={drawerCollapsed}
onClose={() => setDrawerOpen(false)}
+ onToggleCollapse={toggleDrawerCollapsed}
conversations={conversations}
currentConversationId={currentConversationId}
onSelectConversation={selectConversation}
@@ -249,6 +256,8 @@ function App() {
onConversationUpdate={updateConversation}
onFirstMessage={handleFirstMessage}
mostRecentCwd={mostRecentCwd}
+ isDrawerCollapsed={drawerCollapsed}
+ onToggleDrawerCollapse={toggleDrawerCollapsed}
/>
</div>
@@ -354,6 +354,8 @@ interface ChatInterfaceProps {
onConversationUpdate?: (conversation: Conversation) => void;
onFirstMessage?: (message: string, model: string, cwd?: string) => Promise<void>;
mostRecentCwd?: string | null;
+ isDrawerCollapsed?: boolean;
+ onToggleDrawerCollapse?: () => void;
}
function ChatInterface({
@@ -364,6 +366,8 @@ function ChatInterface({
onConversationUpdate,
onFirstMessage,
mostRecentCwd,
+ isDrawerCollapsed,
+ onToggleDrawerCollapse,
}: ChatInterfaceProps) {
const [messages, setMessages] = useState<Message[]>([]);
const [loading, setLoading] = useState(true);
@@ -1041,6 +1045,25 @@ function ChatInterface({
</svg>
</button>
+ {/* Expand drawer button - desktop only when collapsed */}
+ {isDrawerCollapsed && onToggleDrawerCollapse && (
+ <button
+ onClick={onToggleDrawerCollapse}
+ className="btn-icon show-on-desktop-only"
+ aria-label="Expand sidebar"
+ title="Expand sidebar"
+ >
+ <svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
+ <path
+ strokeLinecap="round"
+ strokeLinejoin="round"
+ strokeWidth={2}
+ d="M13 5l7 7-7 7M5 5l7 7-7 7"
+ />
+ </svg>
+ </button>
+ )}
+
<h1 className="header-title" title={currentConversation?.slug || "Shelley"}>
{getDisplayTitle()}
</h1>
@@ -4,7 +4,9 @@ import { api } from "../services/api";
interface ConversationDrawerProps {
isOpen: boolean;
+ isCollapsed: boolean;
onClose: () => void;
+ onToggleCollapse: () => void;
conversations: Conversation[];
currentConversationId: string | null;
onSelectConversation: (id: string) => void;
@@ -16,7 +18,9 @@ interface ConversationDrawerProps {
function ConversationDrawer({
isOpen,
+ isCollapsed,
onClose,
+ onToggleCollapse,
conversations,
currentConversationId,
onSelectConversation,
@@ -189,7 +193,7 @@ function ConversationDrawer({
return (
<>
{/* Drawer */}
- <div className={`drawer ${isOpen ? "open" : ""}`}>
+ <div className={`drawer ${isOpen ? "open" : ""} ${isCollapsed ? "collapsed" : ""}`}>
{/* Header */}
<div className="drawer-header">
<h2 className="drawer-title">{showArchived ? "Archived" : "Conversations"}</h2>
@@ -225,6 +229,22 @@ function ConversationDrawer({
/>
</svg>
</button>
+ {/* Collapse button - desktop only */}
+ <button
+ onClick={onToggleCollapse}
+ className="btn-icon show-on-desktop-only"
+ aria-label="Collapse sidebar"
+ title="Collapse sidebar"
+ >
+ <svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
+ <path
+ strokeLinecap="round"
+ strokeLinejoin="round"
+ strokeWidth={2}
+ d="M11 19l-7-7 7-7m8 14l-7-7 7-7"
+ />
+ </svg>
+ </button>
</div>
</div>
@@ -2226,15 +2226,30 @@ svg {
transform: translateX(0) !important;
}
+ .drawer.collapsed {
+ display: none;
+ }
+
.hide-on-desktop {
display: none !important;
}
+ .show-on-desktop-only {
+ display: flex !important;
+ }
+
.backdrop {
display: none !important;
}
}
+/* Hide desktop-only elements on mobile */
+@media (max-width: 767px) {
+ .show-on-desktop-only {
+ display: none !important;
+ }
+}
+
/* Rotation animation for running tools */
@keyframes rotate {
from {