Skip to content

Commit d272459

Browse files
jsell-rhclaude
andcommitted
fix(ambient-ui): sidebar z-index overlap, URL state, mobile layout
- Main content area clips overflow so sticky header can't bleed into sidebar - Sidebar gets z-20 to always render above main content - Sidebar session ID persisted in URL (?chat=<id>) — survives reload - Active tab persisted in URL (?tab=logs) — survives reload - Sidebar goes full-screen on mobile widths (max-md breakpoint) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent ed9ecd5 commit d272459

4 files changed

Lines changed: 29 additions & 5 deletions

File tree

components/ambient-ui/src/app/(dashboard)/[projectId]/fleet/[sessionId]/page.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client'
22

3-
import { useParams } from 'next/navigation'
3+
import { useParams, useSearchParams } from 'next/navigation'
44
import { Skeleton } from '@/components/ui/skeleton'
55
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
66
import { useSession } from '@/queries/use-sessions'
@@ -11,8 +11,16 @@ import { ChatTab } from './_components/chat-tab'
1111

1212
export default function SessionDetailPage() {
1313
const { sessionId } = useParams<{ projectId: string; sessionId: string }>()
14+
const searchParams = useSearchParams()
15+
const activeTab = searchParams.get('tab') ?? 'phase'
1416
const { data: session, isLoading, error } = useSession(sessionId)
1517

18+
const handleTabChange = (value: string) => {
19+
const url = new URL(window.location.href)
20+
url.searchParams.set('tab', value)
21+
window.history.replaceState({}, '', url.toString())
22+
}
23+
1624
if (error) {
1725
return (
1826
<p className="text-sm text-destructive">
@@ -33,7 +41,7 @@ export default function SessionDetailPage() {
3341
return (
3442
<div className="space-y-6">
3543
<SessionHeader session={session} />
36-
<Tabs defaultValue="phase">
44+
<Tabs defaultValue={activeTab} onValueChange={handleTabChange}>
3745
<TabsList className="w-full *:flex-1">
3846
<TabsTrigger value="phase">Phase</TabsTrigger>
3947
<TabsTrigger value="logs">Logs</TabsTrigger>

components/ambient-ui/src/app/(dashboard)/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export default function DashboardLayout({
3636
<ChatSidebarProvider>
3737
<SidebarProvider>
3838
<AppSidebar projectId={projectId} />
39-
<SidebarInset className="min-w-0 flex-1">
39+
<SidebarInset className="min-w-0 flex-1 overflow-x-clip">
4040
<NavHeader
4141
projectId={projectId}
4242
projectName={project?.name ?? null}

components/ambient-ui/src/components/chat-sidebar-context.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ import {
55
useContext,
66
useState,
77
useCallback,
8+
useEffect,
89
useMemo,
910
type ReactNode,
1011
} from 'react'
12+
import { useSearchParams, useRouter, usePathname } from 'next/navigation'
1113

1214
type ChatSidebarState = {
1315
openSessionId: string | null
@@ -18,15 +20,29 @@ type ChatSidebarState = {
1820

1921
const ChatSidebarContext = createContext<ChatSidebarState | null>(null)
2022

23+
function updateChatParam(sessionId: string | null) {
24+
const url = new URL(window.location.href)
25+
if (sessionId) {
26+
url.searchParams.set('chat', sessionId)
27+
} else {
28+
url.searchParams.delete('chat')
29+
}
30+
window.history.replaceState({}, '', url.toString())
31+
}
32+
2133
export function ChatSidebarProvider({ children }: { children: ReactNode }) {
22-
const [openSessionId, setOpenSessionId] = useState<string | null>(null)
34+
const searchParams = useSearchParams()
35+
const initialChat = searchParams.get('chat')
36+
const [openSessionId, setOpenSessionId] = useState<string | null>(initialChat)
2337

2438
const openSidebar = useCallback((sessionId: string) => {
2539
setOpenSessionId(sessionId)
40+
updateChatParam(sessionId)
2641
}, [])
2742

2843
const closeSidebar = useCallback(() => {
2944
setOpenSessionId(null)
45+
updateChatParam(null)
3046
}, [])
3147

3248
const value = useMemo<ChatSidebarState>(

components/ambient-ui/src/components/chat-sidebar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ export function ChatSidebar() {
151151

152152
return (
153153
<aside
154-
className="flex-shrink-0 border-l bg-background flex flex-col relative h-screen sticky top-0"
154+
className="flex-shrink-0 border-l bg-background flex flex-col relative h-screen sticky top-0 z-20 max-md:!w-screen max-md:fixed max-md:inset-0 max-md:border-l-0"
155155
style={{ width }}
156156
aria-label={`Chat sidebar for session ${sessionName}`}
157157
role="complementary"

0 commit comments

Comments
 (0)