feat(mobile): viewport hook + sidebar drawer + hamburger headers
- useViewport: matchMedia-based hook (no resize polling). Breakpoints mobile <768 / tablet 768-1023 / desktop >=1024. SSR-safe. - useSidebarDrawer: Context provider with open/setOpen/toggle + auto-close on useLocation().pathname change. - App.tsx: wraps SidebarDrawerProvider around AppShell, renders a MobileBackdrop (z-30) when the drawer is open on mobile. - ProjectSidebar: aside is fixed/translate-x-full off-screen on mobile, slides in (z-40, 200ms transform) when drawerOpen. Inline column on desktop, unchanged. - Session.tsx + Project.tsx: hamburger (Menu icon, >=44x44 min) on mobile opens the drawer. Headers gain paddingTop: max(0.75rem, env(safe-area-inset-top)) for notch devices. Home.tsx left alone (sidebar content duplicates the home page). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Link, useNavigate, useParams } from 'react-router-dom';
|
||||
import { ChevronRight } from 'lucide-react';
|
||||
import { ChevronRight, Menu } from 'lucide-react';
|
||||
import { api } from '@/api/client';
|
||||
import type { Project, Session as SessionType } from '@/api/types';
|
||||
import { sessionEvents } from '@/hooks/sessionEvents';
|
||||
import { useActivePane } from '@/hooks/useActivePane';
|
||||
import { useSidebarDrawer } from '@/hooks/useSidebarDrawer';
|
||||
import { useViewport } from '@/hooks/useViewport';
|
||||
import { Workspace } from '@/components/Workspace';
|
||||
import { ModelPicker } from '@/components/ModelPicker';
|
||||
|
||||
@@ -16,6 +18,8 @@ export function Session() {
|
||||
const [name, setName] = useState('');
|
||||
const [editingName, setEditingName] = useState(false);
|
||||
const active = useActivePane();
|
||||
const { setOpen: setDrawerOpen } = useSidebarDrawer();
|
||||
const { isMobile } = useViewport();
|
||||
|
||||
useEffect(() => {
|
||||
if (!id) return;
|
||||
@@ -83,7 +87,17 @@ export function Session() {
|
||||
|
||||
return (
|
||||
<div className="flex-1 flex flex-col min-h-0">
|
||||
<header className="border-b px-4 py-2 flex items-center gap-1.5 shrink-0 text-sm">
|
||||
<header className="border-b px-4 py-2 flex items-center gap-1.5 shrink-0 text-sm" style={{ paddingTop: 'max(0.5rem, env(safe-area-inset-top))' }}>
|
||||
{isMobile && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setDrawerOpen(true)}
|
||||
className="inline-flex items-center justify-center -ml-1 mr-1 min-w-[44px] min-h-[44px] rounded text-muted-foreground hover:bg-muted hover:text-foreground"
|
||||
aria-label="Open sidebar"
|
||||
>
|
||||
<Menu className="size-5" />
|
||||
</button>
|
||||
)}
|
||||
<Link to="/" className="text-muted-foreground hover:text-foreground">
|
||||
Projects
|
||||
</Link>
|
||||
|
||||
Reference in New Issue
Block a user