1- import { HTMLAttributes , useState , useCallback , useEffect , useId } from "react"
1+ import { HTMLAttributes , useState , useCallback , useEffect } from "react"
22import { useAppTranslation } from "@/i18n/TranslationContext"
33import { vscode } from "@/utils/vscode"
4- import { VSCodeCheckbox , VSCodeLink , VSCodeButton } from "@vscode/webview-ui-toolkit/react"
4+ import { VSCodeCheckbox , VSCodeLink } from "@vscode/webview-ui-toolkit/react"
55import { Trans } from "react-i18next"
66import { buildDocLink } from "@src/utils/docLinks"
77import { useEvent , useMount } from "react-use"
8+ import { Terminal } from "lucide-react"
89
910import { type ExtensionMessage , type TerminalOutputPreviewSize } from "@roo-code/types"
1011
1112import { cn } from "@/lib/utils"
12- import { Select , SelectContent , SelectItem , SelectTrigger , SelectValue , Slider } from "@/components/ui"
13+ import { Select , SelectContent , SelectItem , SelectTrigger , SelectValue , Slider , Button } from "@/components/ui"
1314
1415import { SetCachedStateField } from "./types"
1516import { SectionHeader } from "./SectionHeader"
@@ -44,7 +45,7 @@ type TerminalSettingsProps = HTMLAttributes<HTMLDivElement> & {
4445
4546// Sentinel value that maps to `undefined` (use VS Code's default shell).
4647// The Select component cannot accept empty-string item values.
47- const DEFAULT_PROFILE_VALUE = "__default__ "
48+ export const DEFAULT_PROFILE_VALUE = "__zoo_code_follow_vscode_sentinel__ "
4849
4950export const TerminalSettings = ( {
5051 terminalOutputPreviewSize,
@@ -67,10 +68,6 @@ export const TerminalSettings = ({
6768 const [ inheritEnv , setInheritEnv ] = useState < boolean > ( true )
6869 const [ profileNames , setProfileNames ] = useState < string [ ] > ( [ ] )
6970 const [ isProfilesLoaded , setIsProfilesLoaded ] = useState ( false )
70- const profileModeId = useId ( )
71- const defaultProfileId = `${ profileModeId } -default`
72- const overrideProfileId = `${ profileModeId } -override`
73- const isProfileOverrideSelected = ! ! terminalProfile && ( ! isProfilesLoaded || profileNames . includes ( terminalProfile ) )
7471 const isVSCodeTerminalEnabled = terminalShellIntegrationDisabled === false
7572
7673 useMount ( ( ) => {
@@ -166,111 +163,7 @@ export const TerminalSettings = ({
166163 </ div >
167164 </ div >
168165 < div className = "flex flex-col gap-3 pl-3 border-l-2 border-vscode-button-background" >
169- { /* Profile override — only applies when VS Code integrated terminal is active
170- (shell integration enabled). Hidden in Execa/inline mode since getProfileShell()
171- is not wired there. */ }
172- { isVSCodeTerminalEnabled && (
173- < SearchableSetting
174- settingId = "terminal-profile"
175- section = "terminal"
176- label = { t ( "settings:terminal.profile.label" ) } >
177- < label className = "block font-medium mb-1" > { t ( "settings:terminal.profile.label" ) } </ label >
178-
179- { /* Level 1: Default (recommended) */ }
180- < div className = "flex items-center gap-2 mb-2" >
181- < input
182- type = "radio"
183- id = { defaultProfileId }
184- name = { profileModeId }
185- checked = { ! isProfileOverrideSelected }
186- onChange = { ( ) => setCachedStateField ( "terminalProfile" , undefined ) }
187- data-testid = "terminal-profile-default-radio"
188- />
189- < label htmlFor = { defaultProfileId } className = "cursor-pointer" >
190- { t ( "settings:terminal.profile.default" ) }
191- </ label >
192- < VSCodeButton
193- appearance = "secondary"
194- onClick = { ( ) => {
195- onTerminalProfilePickerOpened ?.( )
196- vscode . postMessage ( { type : "openTerminalProfilePicker" } )
197- } }
198- data-testid = "terminal-profile-configure-button" >
199- { t ( "settings:terminal.profile.configureButton" ) }
200- </ VSCodeButton >
201- </ div >
202-
203- { /* Level 2: Override */ }
204- < div className = "flex items-center gap-2 mb-2" >
205- < input
206- type = "radio"
207- id = { overrideProfileId }
208- name = { profileModeId }
209- checked = { isProfileOverrideSelected }
210- disabled = { profileNames . length === 0 }
211- onChange = { ( ) => {
212- if ( ! terminalProfile && profileNames . length > 0 ) {
213- setCachedStateField ( "terminalProfile" , profileNames [ 0 ] )
214- }
215- } }
216- data-testid = "terminal-profile-override-radio"
217- />
218- < label
219- htmlFor = { overrideProfileId }
220- className = {
221- profileNames . length === 0
222- ? "cursor-not-allowed text-vscode-disabledForeground"
223- : "cursor-pointer"
224- } >
225- { t ( "settings:terminal.profile.overrideLabel" ) }
226- </ label >
227- { profileNames . length === 0 && (
228- < span
229- className = "text-vscode-descriptionForeground text-xs"
230- data-testid = "terminal-profile-no-profiles-hint" >
231- { t ( "settings:terminal.profile.noProfiles" ) }
232- </ span >
233- ) }
234- </ div >
235-
236- { isProfileOverrideSelected && profileNames . length > 0 && (
237- < Select
238- value = { terminalProfile || DEFAULT_PROFILE_VALUE }
239- data-testid = "terminal-profile-dropdown"
240- onValueChange = { ( value ) =>
241- setCachedStateField (
242- "terminalProfile" ,
243- value === DEFAULT_PROFILE_VALUE ? undefined : value ,
244- )
245- } >
246- < SelectTrigger className = "w-full ml-6" >
247- < SelectValue placeholder = { t ( "settings:common.select" ) } />
248- </ SelectTrigger >
249- < SelectContent >
250- { profileNames . map ( ( name ) => (
251- < SelectItem key = { name } value = { name } >
252- { name }
253- </ SelectItem >
254- ) ) }
255- </ SelectContent >
256- </ Select >
257- ) }
258-
259- < div className = "text-vscode-descriptionForeground text-sm mt-1" >
260- < Trans i18nKey = "settings:terminal.profile.description" >
261- < VSCodeLink
262- href = { buildDocLink (
263- "features/shell-integration" ,
264- "settings_terminal_profile" ,
265- ) }
266- style = { { display : "inline" } } >
267- { " " }
268- </ VSCodeLink >
269- </ Trans >
270- </ div >
271- </ SearchableSetting >
272- ) }
273-
166+ { /* "Use Inline Terminal" checkbox — ALWAYS at the top */ }
274167 < SearchableSetting
275168 settingId = "terminal-shell-integration-disabled"
276169 section = "terminal"
@@ -300,6 +193,76 @@ export const TerminalSettings = ({
300193
301194 { isVSCodeTerminalEnabled && (
302195 < >
196+ { /* Profile override — unified dropdown, now below checkbox */ }
197+ < SearchableSetting
198+ settingId = "terminal-profile"
199+ section = "terminal"
200+ label = { t ( "settings:terminal.profile.label" ) } >
201+ < label className = "block font-medium mb-1" >
202+ { t ( "settings:terminal.profile.label" ) }
203+ </ label >
204+
205+ < Select
206+ value = { terminalProfile ?? DEFAULT_PROFILE_VALUE }
207+ onValueChange = { ( value ) =>
208+ setCachedStateField (
209+ "terminalProfile" ,
210+ value === DEFAULT_PROFILE_VALUE ? undefined : value ,
211+ )
212+ } >
213+ < SelectTrigger className = "w-full" data-testid = "terminal-profile-dropdown" >
214+ < SelectValue placeholder = { t ( "settings:common.select" ) } />
215+ </ SelectTrigger >
216+ < SelectContent >
217+ < SelectItem value = { DEFAULT_PROFILE_VALUE } >
218+ { t ( "settings:terminal.profile.followVscode" ) }
219+ </ SelectItem >
220+ { profileNames . map ( ( name ) => (
221+ < SelectItem key = { name } value = { name } >
222+ { name }
223+ </ SelectItem >
224+ ) ) }
225+ </ SelectContent >
226+ </ Select >
227+
228+ { ! terminalProfile && (
229+ < div className = "mt-2 flex flex-col" >
230+ < Button
231+ variant = "secondary"
232+ className = "py-1"
233+ onClick = { ( ) => {
234+ onTerminalProfilePickerOpened ?.( )
235+ vscode . postMessage ( { type : "openTerminalProfilePicker" } )
236+ } }
237+ data-testid = "terminal-profile-configure-button" >
238+ < Terminal />
239+ { t ( "settings:terminal.profile.configureButton" ) }
240+ </ Button >
241+ </ div >
242+ ) }
243+
244+ { isProfilesLoaded && profileNames . length === 0 && (
245+ < div
246+ className = "text-vscode-descriptionForeground text-xs mt-1"
247+ data-testid = "terminal-profile-no-profiles-hint" >
248+ { t ( "settings:terminal.profile.noProfiles" ) }
249+ </ div >
250+ ) }
251+
252+ < div className = "text-vscode-descriptionForeground text-sm mt-1" >
253+ < Trans i18nKey = "settings:terminal.profile.description" >
254+ < VSCodeLink
255+ href = { buildDocLink (
256+ "features/shell-integration" ,
257+ "settings_terminal_profile" ,
258+ ) }
259+ style = { { display : "inline" } } >
260+ { " " }
261+ </ VSCodeLink >
262+ </ Trans >
263+ </ div >
264+ </ SearchableSetting >
265+
303266 < SearchableSetting
304267 settingId = "terminal-inherit-env"
305268 section = "terminal"
0 commit comments