@@ -28,7 +28,15 @@ import {
2828 normalizeModelSlug ,
2929 resolveModelSlugForProvider ,
3030} from "@t3tools/shared/model" ;
31- import { useCallback , useEffect , useLayoutEffect , useMemo , useRef , useState } from "react" ;
31+ import {
32+ useCallback ,
33+ useEffect ,
34+ useLayoutEffect ,
35+ useMemo ,
36+ useRef ,
37+ useState ,
38+ type ReactNode ,
39+ } from "react" ;
3240import { useMutation , useQuery , useQueryClient } from "@tanstack/react-query" ;
3341import { useDebouncedValue } from "@tanstack/react-pacer" ;
3442import { useNavigate , useSearch } from "@tanstack/react-router" ;
@@ -85,6 +93,11 @@ import {
8593import { basenameOfPath } from "../vscode-icons" ;
8694import { useTheme } from "../hooks/useTheme" ;
8795import { useTurnDiffSummaries } from "../hooks/useTurnDiffSummaries" ;
96+ import { useMediaQuery } from "../hooks/useMediaQuery" ;
97+ import {
98+ RIGHT_PANEL_INLINE_LAYOUT_MEDIA_QUERY ,
99+ RIGHT_PANEL_SHEET_CLASS_NAME ,
100+ } from "../rightPanelLayout" ;
88101import BranchToolbar from "./BranchToolbar" ;
89102import { resolveShortcutCommand , shortcutLabelForCommand } from "../keybindings" ;
90103import PlanSidebar from "./PlanSidebar" ;
@@ -169,6 +182,7 @@ import {
169182 SendPhase ,
170183} from "./ChatView.logic" ;
171184import { useLocalStorage } from "~/hooks/useLocalStorage" ;
185+ import { Sheet , SheetPopup } from "./ui/sheet" ;
172186
173187const ATTACHMENT_PREVIEW_HANDOFF_TTL_MS = 5000 ;
174188const IMAGE_SIZE_LIMIT_LABEL = `${ Math . round ( PROVIDER_SEND_TURN_MAX_IMAGE_BYTES / ( 1024 * 1024 ) ) } MB` ;
@@ -216,6 +230,28 @@ interface ChatViewProps {
216230 threadId : ThreadId ;
217231}
218232
233+ function PlanSidebarSheet ( props : { children : ReactNode ; open : boolean ; onClose : ( ) => void } ) {
234+ return (
235+ < Sheet
236+ open = { props . open }
237+ onOpenChange = { ( open ) => {
238+ if ( ! open ) {
239+ props . onClose ( ) ;
240+ }
241+ } }
242+ >
243+ < SheetPopup
244+ side = "right"
245+ showCloseButton = { false }
246+ keepMounted
247+ className = { RIGHT_PANEL_SHEET_CLASS_NAME }
248+ >
249+ { props . children }
250+ </ SheetPopup >
251+ </ Sheet >
252+ ) ;
253+ }
254+
219255export default function ChatView ( { threadId } : ChatViewProps ) {
220256 const threads = useStore ( ( store ) => store . threads ) ;
221257 const projects = useStore ( ( store ) => store . projects ) ;
@@ -316,6 +352,7 @@ export default function ChatView({ threadId }: ChatViewProps) {
316352 useState < Record < string , number > > ( { } ) ;
317353 const [ expandedWorkGroups , setExpandedWorkGroups ] = useState < Record < string , boolean > > ( { } ) ;
318354 const [ planSidebarOpen , setPlanSidebarOpen ] = useState ( false ) ;
355+ const shouldUsePlanSidebarSheet = useMediaQuery ( RIGHT_PANEL_INLINE_LAYOUT_MEDIA_QUERY ) ;
319356 const [ isComposerFooterCompact , setIsComposerFooterCompact ] = useState ( false ) ;
320357 // Tracks whether the user explicitly dismissed the sidebar for the active turn.
321358 const planSidebarDismissedForTurnRef = useRef < string | null > ( null ) ;
@@ -1563,6 +1600,13 @@ export default function ChatView({ threadId }: ChatViewProps) {
15631600 return ! open ;
15641601 } ) ;
15651602 } , [ activePlan ?. turnId , activeProposedPlan ?. turnId ] ) ;
1603+ const closePlanSidebar = useCallback ( ( ) => {
1604+ setPlanSidebarOpen ( false ) ;
1605+ const turnKey = activePlan ?. turnId ?? activeProposedPlan ?. turnId ?? null ;
1606+ if ( turnKey ) {
1607+ planSidebarDismissedForTurnRef . current = turnKey ;
1608+ }
1609+ } , [ activePlan ?. turnId , activeProposedPlan ?. turnId ] ) ;
15661610
15671611 const persistThreadSettingsForNextTurn = useCallback (
15681612 async ( input : {
@@ -4016,26 +4060,34 @@ export default function ChatView({ threadId }: ChatViewProps) {
40164060 { /* end chat column */ }
40174061
40184062 { /* Plan sidebar */ }
4019- { planSidebarOpen ? (
4063+ { planSidebarOpen && ! shouldUsePlanSidebarSheet ? (
40204064 < PlanSidebar
40214065 activePlan = { activePlan }
40224066 activeProposedPlan = { activeProposedPlan }
40234067 markdownCwd = { gitCwd ?? undefined }
40244068 workspaceRoot = { activeProject ?. cwd ?? undefined }
40254069 timestampFormat = { timestampFormat }
4026- onClose = { ( ) => {
4027- setPlanSidebarOpen ( false ) ;
4028- // Track that the user explicitly dismissed for this turn so auto-open won't fight them.
4029- const turnKey = activePlan ?. turnId ?? activeProposedPlan ?. turnId ?? null ;
4030- if ( turnKey ) {
4031- planSidebarDismissedForTurnRef . current = turnKey ;
4032- }
4033- } }
4070+ mode = "sidebar"
4071+ onClose = { closePlanSidebar }
40344072 />
40354073 ) : null }
40364074 </ div >
40374075 { /* end horizontal flex container */ }
40384076
4077+ { shouldUsePlanSidebarSheet && planSidebarOpen ? (
4078+ < PlanSidebarSheet open onClose = { closePlanSidebar } >
4079+ < PlanSidebar
4080+ activePlan = { activePlan }
4081+ activeProposedPlan = { activeProposedPlan }
4082+ markdownCwd = { gitCwd ?? undefined }
4083+ workspaceRoot = { activeProject ?. cwd ?? undefined }
4084+ timestampFormat = { timestampFormat }
4085+ mode = "sheet"
4086+ onClose = { closePlanSidebar }
4087+ />
4088+ </ PlanSidebarSheet >
4089+ ) : null }
4090+
40394091 { ( ( ) => {
40404092 if ( ! terminalState . terminalOpen || ! activeProject ) {
40414093 return null ;
0 commit comments