11import React , { useState , useCallback , useEffect , useMemo } from "react"
2- import { GitBranch , Check } from "lucide-react"
2+ import { GitBranch , Check , ChevronDown , Plus } from "lucide-react"
33
44import type { Worktree , WorktreeListResponse } from "@roo-code/types"
55
66import { cn } from "@/lib/utils"
77import { useRooPortal } from "@/components/ui/hooks/useRooPortal"
8- import { Popover , PopoverContent , PopoverTrigger , StandardTooltip } from "@/components/ui"
8+ import { Popover , PopoverContent , PopoverTrigger , StandardTooltip , Button } from "@/components/ui"
99import { useAppTranslation } from "@/i18n/TranslationContext"
1010import { vscode } from "@/utils/vscode"
1111
12+ import { CreateWorktreeModal } from "../worktrees/CreateWorktreeModal"
1213import { IconButton } from "./IconButton"
1314
1415interface WorktreeSelectorProps {
@@ -20,6 +21,7 @@ export const WorktreeSelector = ({ disabled = false }: WorktreeSelectorProps) =>
2021 const [ open , setOpen ] = useState ( false )
2122 const [ worktrees , setWorktrees ] = useState < Worktree [ ] > ( [ ] )
2223 const [ isGitRepo , setIsGitRepo ] = useState ( true )
24+ const [ showCreateModal , setShowCreateModal ] = useState ( false )
2325 const portalContainer = useRooPortal ( "roo-portal" )
2426
2527 // Find current worktree
@@ -75,12 +77,11 @@ export const WorktreeSelector = ({ disabled = false }: WorktreeSelectorProps) =>
7577 } , [ ] )
7678
7779 // Don't render if not a git repo or only one worktree
78- if ( ! isGitRepo || worktrees . length <= 1 ) {
80+ if ( ! isGitRepo ) {
7981 return null
8082 }
8183
8284 const title = t ( "worktrees:selector.tooltip" )
83- const instructionText = t ( "worktrees:selector.description" )
8485
8586 return (
8687 < Popover open = { open } onOpenChange = { setOpen } data-testid = "worktree-selector-root" >
@@ -89,15 +90,17 @@ export const WorktreeSelector = ({ disabled = false }: WorktreeSelectorProps) =>
8990 disabled = { disabled }
9091 data-testid = "worktree-selector-trigger"
9192 className = { cn (
92- "inline-flex items-center relative whitespace-nowrap px-1.5 py-1 text-xs " ,
93- "bg-transparent border border-[rgba(255,255,255,0.08)] rounded-md text-vscode-foreground" ,
93+ "inline-flex gap-1 mx-2 mb-1 items-center relative whitespace-nowrap px-3 py-2 " ,
94+ "bg-transparent rounded-full text-vscode-foreground text-left " ,
9495 "transition-all duration-150 focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder focus-visible:ring-inset" ,
9596 disabled
9697 ? "opacity-50 cursor-not-allowed"
9798 : "opacity-90 hover:opacity-100 hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)] cursor-pointer" ,
9899 ) } >
99- < GitBranch className = "w-3 h-3 mr-1" />
100+ < span className = "font-semibold mr-2" > { t ( "worktrees:selector.worktree" ) } :</ span >
101+ < GitBranch className = "w-3 h-3" />
100102 < span className = "truncate" > { currentWorktree ?. branch || t ( "worktrees:noBranch" ) } </ span >
103+ < ChevronDown className = "size-3" />
101104 </ PopoverTrigger >
102105 </ StandardTooltip >
103106 < PopoverContent
@@ -106,9 +109,19 @@ export const WorktreeSelector = ({ disabled = false }: WorktreeSelectorProps) =>
106109 container = { portalContainer }
107110 className = "p-0 overflow-hidden min-w-80 max-w-9/10" >
108111 < div className = "flex flex-col w-full" >
109- { /* Info blurb */ }
110- < div className = "p-3 border-b border-vscode-dropdown-border" >
111- < p className = "m-0 text-xs text-vscode-descriptionForeground" > { instructionText } </ p >
112+ { /* Bottom bar with settings cog and title */ }
113+ < div className = "px-3 pb-4" >
114+ < div className = "flex flex-row items-center justify-between" >
115+ < h4 className = "" > { t ( "worktrees:selector.title" ) } </ h4 >
116+ < IconButton
117+ iconClass = "codicon-settings-gear"
118+ title = { t ( "worktrees:selector.settings" ) }
119+ onClick = { handleSettingsClick }
120+ />
121+ </ div >
122+ < p className = "m-0 text-xs text-vscode-descriptionForeground" >
123+ { t ( "worktrees:selector.description" ) }
124+ </ p >
112125 </ div >
113126
114127 { /* Worktree list */ }
@@ -146,28 +159,35 @@ export const WorktreeSelector = ({ disabled = false }: WorktreeSelectorProps) =>
146159 } ) }
147160 </ div >
148161
149- { /* Bottom bar with settings cog and title */ }
150- < div className = "flex flex-row items-center justify-between px-2 py-2 border-t border-vscode-dropdown-border" >
151- < div className = "flex flex-row gap-1" >
152- < IconButton
153- iconClass = "codicon-settings-gear"
154- title = { t ( "worktrees:selector.settings" ) }
155- onClick = { handleSettingsClick }
156- />
157- </ div >
158-
159- { /* Info icon and title on the right */ }
160- < div className = "flex items-center gap-1 pr-1" >
161- < StandardTooltip content = { t ( "worktrees:selector.info" ) } >
162- < span className = "codicon codicon-info text-xs text-vscode-descriptionForeground opacity-70 hover:opacity-100 cursor-help" />
163- </ StandardTooltip >
164- < h4 className = "m-0 font-medium text-sm text-vscode-descriptionForeground" >
165- { t ( "worktrees:selector.title" ) }
166- </ h4 >
167- </ div >
162+ { /* New worktree button */ }
163+ < div className = "px-3 py-2 border-t border-vscode-panel-border" >
164+ < Button
165+ variant = "ghost"
166+ size = "sm"
167+ className = "w-full justify-start"
168+ onClick = { ( ) => {
169+ setShowCreateModal ( true )
170+ setOpen ( false )
171+ } } >
172+ < Plus className = "w-3 h-3 mr-2" />
173+ { t ( "worktrees:newWorktree" ) }
174+ </ Button >
168175 </ div >
169176 </ div >
170177 </ PopoverContent >
178+
179+ { /* Create Worktree Modal */ }
180+ { showCreateModal && (
181+ < CreateWorktreeModal
182+ open = { showCreateModal }
183+ onClose = { ( ) => setShowCreateModal ( false ) }
184+ openAfterCreate = { true }
185+ onSuccess = { ( ) => {
186+ setShowCreateModal ( false )
187+ fetchWorktrees ( )
188+ } }
189+ />
190+ ) }
171191 </ Popover >
172192 )
173193}
0 commit comments