1- import { VSCodeButton , VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
21import { memo , useEffect , useRef , useState } from "react"
3- import { useAppTranslation } from "@/i18n/TranslationContext"
2+ import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
3+
44import { ApiConfigMeta } from "../../../../src/shared/ExtensionMessage"
5- import { Dropdown } from "vscrui"
6- import type { DropdownOption } from "vscrui"
7- import { Dialog , DialogContent , DialogTitle } from "../ui/dialog"
8- import { Button , Input } from "../ui"
5+
6+ import { useAppTranslation } from "@/i18n/TranslationContext"
7+ import {
8+ Button ,
9+ Input ,
10+ Dialog ,
11+ DialogContent ,
12+ DialogTitle ,
13+ Select ,
14+ SelectTrigger ,
15+ SelectValue ,
16+ SelectContent ,
17+ SelectItem ,
18+ } from "@/components/ui"
919
1020interface ApiConfigManagerProps {
1121 currentApiConfigName ?: string
@@ -25,6 +35,7 @@ const ApiConfigManager = ({
2535 onUpsertConfig,
2636} : ApiConfigManagerProps ) => {
2737 const { t } = useAppTranslation ( )
38+
2839 const [ isRenaming , setIsRenaming ] = useState ( false )
2940 const [ isCreating , setIsCreating ] = useState ( false )
3041 const [ inputValue , setInputValue ] = useState ( "" )
@@ -39,12 +50,12 @@ const ApiConfigManager = ({
3950
4051 const nameExists = listApiConfigMeta ?. some ( ( config ) => config . name . toLowerCase ( ) === trimmed . toLowerCase ( ) )
4152
42- // For new profiles, any existing name is invalid
53+ // For new profiles, any existing name is invalid.
4354 if ( isNewProfile && nameExists ) {
4455 return t ( "settings:providers.nameExists" )
4556 }
4657
47- // For rename, only block if trying to rename to a different existing profile
58+ // For rename, only block if trying to rename to a different existing profile.
4859 if ( ! isNewProfile && nameExists && trimmed . toLowerCase ( ) !== currentApiConfigName ?. toLowerCase ( ) ) {
4960 return t ( "settings:providers.nameExists" )
5061 }
@@ -64,23 +75,23 @@ const ApiConfigManager = ({
6475 setError ( null )
6576 }
6677
67- // Focus input when entering rename mode
78+ // Focus input when entering rename mode.
6879 useEffect ( ( ) => {
6980 if ( isRenaming ) {
7081 const timeoutId = setTimeout ( ( ) => inputRef . current ?. focus ( ) , 0 )
7182 return ( ) => clearTimeout ( timeoutId )
7283 }
7384 } , [ isRenaming ] )
7485
75- // Focus input when opening new dialog
86+ // Focus input when opening new dialog.
7687 useEffect ( ( ) => {
7788 if ( isCreating ) {
7889 const timeoutId = setTimeout ( ( ) => newProfileInputRef . current ?. focus ( ) , 0 )
7990 return ( ) => clearTimeout ( timeoutId )
8091 }
8192 } , [ isCreating ] )
8293
83- // Reset state when current profile changes
94+ // Reset state when current profile changes.
8495 useEffect ( ( ) => {
8596 resetCreateState ( )
8697 resetRenameState ( )
@@ -137,23 +148,19 @@ const ApiConfigManager = ({
137148 const handleDelete = ( ) => {
138149 if ( ! currentApiConfigName || ! listApiConfigMeta || listApiConfigMeta . length <= 1 ) return
139150
140- // Let the extension handle both deletion and selection
151+ // Let the extension handle both deletion and selection.
141152 onDeleteConfig ( currentApiConfigName )
142153 }
143154
144155 const isOnlyProfile = listApiConfigMeta ?. length === 1
145156
146157 return (
147158 < div className = "flex flex-col gap-1" >
148- < label htmlFor = "config-profile" >
149- < span className = "font-medium" > { t ( "settings:providers.configProfile" ) } </ span >
150- </ label >
159+ < label className = "block font-medium mb-1" > { t ( "settings:providers.configProfile" ) } </ label >
151160
152161 { isRenaming ? (
153- < div
154- data-testid = "rename-form"
155- style = { { display : "flex" , gap : "4px" , alignItems : "center" , flexDirection : "column" } } >
156- < div style = { { display : "flex" , gap : "4px" , alignItems : "center" , width : "100%" } } >
162+ < div data-testid = "rename-form" >
163+ < div className = "flex items-center gap-1" >
157164 < VSCodeTextField
158165 ref = { inputRef }
159166 value = { inputValue }
@@ -163,128 +170,91 @@ const ApiConfigManager = ({
163170 setError ( null )
164171 } }
165172 placeholder = { t ( "settings:providers.enterNewName" ) }
166- style = { { flexGrow : 1 } }
167- onKeyDown = { ( e : unknown ) => {
168- const event = e as { key : string }
169- if ( event . key === "Enter" && inputValue . trim ( ) ) {
173+ onKeyDown = { ( { key } ) => {
174+ if ( key === "Enter" && inputValue . trim ( ) ) {
170175 handleSave ( )
171- } else if ( event . key === "Escape" ) {
176+ } else if ( key === "Escape" ) {
172177 handleCancel ( )
173178 }
174179 } }
180+ className = "grow"
175181 />
176- < VSCodeButton
177- appearance = "icon"
182+ < Button
183+ variant = "ghost"
184+ size = "icon"
178185 disabled = { ! inputValue . trim ( ) }
179186 onClick = { handleSave }
180187 title = { t ( "settings:common.save" ) }
181- data-testid = "save-rename-button"
182- style = { {
183- padding : 0 ,
184- margin : 0 ,
185- height : "28px" ,
186- width : "28px" ,
187- minWidth : "28px" ,
188- } } >
188+ data-testid = "save-rename-button" >
189189 < span className = "codicon codicon-check" />
190- </ VSCodeButton >
191- < VSCodeButton
192- appearance = "icon"
190+ </ Button >
191+ < Button
192+ variant = "ghost"
193+ size = "icon"
193194 onClick = { handleCancel }
194195 title = { t ( "settings:common.cancel" ) }
195- data-testid = "cancel-rename-button"
196- style = { {
197- padding : 0 ,
198- margin : 0 ,
199- height : "28px" ,
200- width : "28px" ,
201- minWidth : "28px" ,
202- } } >
196+ data-testid = "cancel-rename-button" >
203197 < span className = "codicon codicon-close" />
204- </ VSCodeButton >
198+ </ Button >
205199 </ div >
206200 { error && (
207- < p className = "text-red-500 text-sm mt-2 " data-testid = "error-message" >
201+ < div className = "text-vscode-descriptionForeground text-sm mt-1 " data-testid = "error-message" >
208202 { error }
209- </ p >
203+ </ div >
210204 ) }
211205 </ div >
212206 ) : (
213207 < >
214- < div style = { { display : "flex" , gap : "4px" , alignItems : " center" } } >
215- < Dropdown
216- id = "config-profile"
217- value = { currentApiConfigName }
218- onChange = { ( value : unknown ) => {
219- onSelectConfig ( ( value as DropdownOption ) . value )
220- } }
221- role = "combobox"
222- options = { listApiConfigMeta . map ( ( config ) => ( {
223- value : config . name ,
224- label : config . name ,
225- } ) ) }
226- className = "w-full"
227- />
228- < VSCodeButton
229- appearance = "icon"
208+ < div className = "flex items- center gap-1" >
209+ < Select value = { currentApiConfigName } onValueChange = { onSelectConfig } >
210+ < SelectTrigger className = "grow" >
211+ < SelectValue placeholder = { t ( "settings:common.select" ) } />
212+ </ SelectTrigger >
213+ < SelectContent >
214+ { listApiConfigMeta . map ( ( config ) => (
215+ < SelectItem key = { config . name } value = { config . name } >
216+ { config . name }
217+ </ SelectItem >
218+ ) ) }
219+ </ SelectContent >
220+ </ Select >
221+ < Button
222+ variant = "ghost"
223+ size = "icon"
230224 onClick = { handleAdd }
231225 title = { t ( "settings:providers.addProfile" ) }
232- data-testid = "add-profile-button"
233- style = { {
234- padding : 0 ,
235- margin : 0 ,
236- height : "28px" ,
237- width : "28px" ,
238- minWidth : "28px" ,
239- } } >
226+ data-testid = "add-profile-button" >
240227 < span className = "codicon codicon-add" />
241- </ VSCodeButton >
228+ </ Button >
242229 { currentApiConfigName && (
243230 < >
244- < VSCodeButton
245- appearance = "icon"
231+ < Button
232+ variant = "ghost"
233+ size = "icon"
246234 onClick = { handleStartRename }
247235 title = { t ( "settings:providers.renameProfile" ) }
248- data-testid = "rename-profile-button"
249- style = { {
250- padding : 0 ,
251- margin : 0 ,
252- height : "28px" ,
253- width : "28px" ,
254- minWidth : "28px" ,
255- } } >
236+ data-testid = "rename-profile-button" >
256237 < span className = "codicon codicon-edit" />
257- </ VSCodeButton >
258- < VSCodeButton
259- appearance = "icon"
238+ </ Button >
239+ < Button
240+ variant = "ghost"
241+ size = "icon"
260242 onClick = { handleDelete }
261243 title = {
262244 isOnlyProfile
263245 ? t ( "settings:providers.cannotDeleteOnlyProfile" )
264246 : t ( "settings:providers.deleteProfile" )
265247 }
266248 data-testid = "delete-profile-button"
267- disabled = { isOnlyProfile }
268- style = { {
269- padding : 0 ,
270- margin : 0 ,
271- height : "28px" ,
272- width : "28px" ,
273- minWidth : "28px" ,
274- } } >
249+ disabled = { isOnlyProfile } >
275250 < span className = "codicon codicon-trash" />
276- </ VSCodeButton >
251+ </ Button >
277252 </ >
278253 ) }
279254 </ div >
280- < p
281- style = { {
282- fontSize : "12px" ,
283- margin : "5px 0 12px" ,
284- color : "var(--vscode-descriptionForeground)" ,
285- } } >
255+ < div className = "text-vscode-descriptionForeground text-sm mt-1" >
286256 { t ( "settings:providers.description" ) }
287- </ p >
257+ </ div >
288258 </ >
289259 ) }
290260
0 commit comments