Mobile ui

This commit is contained in:
2026-02-14 22:22:05 -08:00
parent a5650e8a1b
commit d6c832dac3

View File

@@ -1,5 +1,5 @@
import { useEffect, useMemo, useRef, useState } from "preact/hooks"; import { useEffect, useMemo, useRef, useState } from "preact/hooks";
import { Check, ChevronDown, Globe2, LogOut, MessageSquare, Plus, Search, SendHorizontal, Trash2 } from "lucide-preact"; import { Check, ChevronDown, Globe2, Menu, MessageSquare, Plus, Search, SendHorizontal, Trash2 } from "lucide-preact";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea"; import { Textarea } from "@/components/ui/textarea";
import { Separator } from "@/components/ui/separator"; import { Separator } from "@/components/ui/separator";
@@ -301,6 +301,7 @@ export default function App() {
const searchRunAbortRef = useRef<AbortController | null>(null); const searchRunAbortRef = useRef<AbortController | null>(null);
const searchRunCounterRef = useRef(0); const searchRunCounterRef = useRef(0);
const [contextMenu, setContextMenu] = useState<ContextMenuState | null>(null); const [contextMenu, setContextMenu] = useState<ContextMenuState | null>(null);
const [isMobileSidebarOpen, setIsMobileSidebarOpen] = useState(false);
useEffect(() => { useEffect(() => {
if (typeof document === "undefined") return; if (typeof document === "undefined") return;
@@ -549,6 +550,7 @@ export default function App() {
setSelectedItem(null); setSelectedItem(null);
setSelectedChat(null); setSelectedChat(null);
setSelectedSearch(null); setSelectedSearch(null);
setIsMobileSidebarOpen(false);
}; };
const handleCreateSearch = () => { const handleCreateSearch = () => {
@@ -558,6 +560,7 @@ export default function App() {
setSelectedItem(null); setSelectedItem(null);
setSelectedChat(null); setSelectedChat(null);
setSelectedSearch(null); setSelectedSearch(null);
setIsMobileSidebarOpen(false);
}; };
const openContextMenu = (event: MouseEvent, item: SidebarSelection) => { const openContextMenu = (event: MouseEvent, item: SidebarSelection) => {
@@ -956,7 +959,21 @@ export default function App() {
return ( return (
<div className="h-full"> <div className="h-full">
<div className="flex h-full w-full overflow-hidden bg-background"> <div className="flex h-full w-full overflow-hidden bg-background">
<aside className="flex w-80 shrink-0 flex-col border-r bg-[hsl(272_34%_14%)]"> {isMobileSidebarOpen ? (
<button
type="button"
className="fixed inset-0 z-30 bg-black/45 md:hidden"
onClick={() => setIsMobileSidebarOpen(false)}
aria-label="Close sidebar"
/>
) : null}
<aside
className={cn(
"fixed inset-y-0 left-0 z-40 flex w-[85vw] max-w-80 shrink-0 flex-col border-r bg-[hsl(272_34%_14%)] transition-transform md:static md:z-auto md:w-80 md:max-w-none",
isMobileSidebarOpen ? "translate-x-0" : "-translate-x-full md:translate-x-0"
)}
>
<div className="grid grid-cols-2 gap-2 p-3"> <div className="grid grid-cols-2 gap-2 p-3">
<Button className="justify-start gap-2" onClick={handleCreateChat}> <Button className="justify-start gap-2" onClick={handleCreateChat}>
<Plus className="h-4 w-4" /> <Plus className="h-4 w-4" />
@@ -992,6 +1009,7 @@ export default function App() {
setContextMenu(null); setContextMenu(null);
setDraftKind(null); setDraftKind(null);
setSelectedItem({ kind: item.kind, id: item.id }); setSelectedItem({ kind: item.kind, id: item.id });
setIsMobileSidebarOpen(false);
}} }}
onContextMenu={(event) => openContextMenu(event, { kind: item.kind, id: item.id })} onContextMenu={(event) => openContextMenu(event, { kind: item.kind, id: item.id })}
type="button" type="button"
@@ -1014,6 +1032,18 @@ export default function App() {
<main className="flex min-w-0 flex-1 flex-col"> <main className="flex min-w-0 flex-1 flex-col">
<header className="flex flex-wrap items-center justify-between gap-3 border-b px-4 py-3"> <header className="flex flex-wrap items-center justify-between gap-3 border-b px-4 py-3">
<div className="flex items-start gap-2">
<Button
type="button"
size="icon"
variant="ghost"
className="-ml-1 h-8 w-8 md:hidden"
onClick={() => setIsMobileSidebarOpen(true)}
aria-label="Open sidebar"
>
<Menu className="h-4 w-4" />
</Button>
<div> <div>
<h1 className="text-sm font-semibold md:text-base">{selectedTitle}</h1> <h1 className="text-sm font-semibold md:text-base">{selectedTitle}</h1>
<p className="text-xs text-muted-foreground"> <p className="text-xs text-muted-foreground">
@@ -1021,6 +1051,7 @@ export default function App() {
{isSearchMode ? " • Exa Search" : ""} {isSearchMode ? " • Exa Search" : ""}
</p> </p>
</div> </div>
</div>
<div className="flex w-full max-w-xl items-center gap-2 md:w-auto"> <div className="flex w-full max-w-xl items-center gap-2 md:w-auto">
{!isSearchMode ? ( {!isSearchMode ? (
<> <>