@@ -6,7 +6,7 @@ import { Button } from '@/components/ui/button'
66import { Input } from '@/components/ui/input'
77import { Label } from '@/components/ui/label'
88import { toast } from 'sonner'
9- import { Eye , EyeOff , Trash2 , Check } from 'lucide-react'
9+ import { Eye , EyeOff , Trash2 , CheckCircle2 } from 'lucide-react'
1010
1111interface ApiKeysDialogProps {
1212 open : boolean
@@ -134,61 +134,81 @@ export function ApiKeysDialog({ open, onOpenChange }: ApiKeysDialogProps) {
134134 < Dialog open = { open } onOpenChange = { onOpenChange } >
135135 < DialogContent className = "max-w-2xl" >
136136 < DialogHeader >
137- < DialogTitle > Manage API Keys</ DialogTitle >
137+ < DialogTitle > API Keys</ DialogTitle >
138138 < DialogDescription >
139- Add your own API keys for AI agents. If not provided, system keys will be used.
139+ Configure your own API keys. System defaults will be used if not provided .
140140 </ DialogDescription >
141141 </ DialogHeader >
142142
143- < div className = "space-y-6 py-4" >
143+ < div className = "space-y-4 py-4" >
144144 { PROVIDERS . map ( ( provider ) => (
145- < div key = { provider . id } className = "space-y-2" >
146- < div className = "flex items-center justify-between" >
147- < Label htmlFor = { provider . id } className = "font-medium" >
148- { provider . name }
149- </ Label >
150- { savedKeys . has ( provider . id ) && (
151- < div className = "flex items-center gap-2" >
152- < span className = "text-xs text-green-600 flex items-center gap-1" >
153- < Check className = "h-3 w-3" />
154- Saved
155- </ span >
156- < Button
157- variant = "ghost"
158- size = "sm"
159- onClick = { ( ) => handleDelete ( provider . id ) }
160- disabled = { loading }
161- className = "h-7 w-7 p-0 text-red-600 hover:text-red-700"
162- title = "Delete API key"
163- >
164- < Trash2 className = "h-3 w-3" />
165- </ Button >
145+ < div
146+ key = { provider . id }
147+ className = "group relative rounded-lg border bg-card p-4 transition-colors hover:bg-accent/30"
148+ >
149+ < div className = "flex items-start gap-3" >
150+ < div className = "flex-1 min-w-0 space-y-3" >
151+ < div className = "flex items-center justify-between" >
152+ < Label htmlFor = { provider . id } className = "text-sm font-medium" >
153+ { provider . name }
154+ </ Label >
155+ { savedKeys . has ( provider . id ) && (
156+ < div className = "flex items-center gap-1.5 text-xs text-emerald-600 dark:text-emerald-500" >
157+ < CheckCircle2 className = "h-3.5 w-3.5" />
158+ < span > Configured</ span >
159+ </ div >
160+ ) }
161+ </ div >
162+
163+ < div className = "flex gap-2" >
164+ < div className = "relative flex-1" >
165+ < Input
166+ id = { provider . id }
167+ type = { showKeys [ provider . id ] ? 'text' : 'password' }
168+ placeholder = { savedKeys . has ( provider . id ) ? '••••••••••••••••' : provider . placeholder }
169+ value = { apiKeys [ provider . id ] }
170+ onChange = { ( e ) => setApiKeys ( ( prev ) => ( { ...prev , [ provider . id ] : e . target . value } ) ) }
171+ disabled = { loading }
172+ className = "pr-9 h-8 text-sm"
173+ />
174+ < button
175+ onClick = { ( ) => toggleShowKey ( provider . id ) }
176+ className = "absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors"
177+ type = "button"
178+ disabled = { loading }
179+ >
180+ { showKeys [ provider . id ] ? (
181+ < EyeOff className = "h-3.5 w-3.5" />
182+ ) : (
183+ < Eye className = "h-3.5 w-3.5" />
184+ ) }
185+ </ button >
186+ </ div >
187+
188+ < div className = "flex gap-1.5" >
189+ < Button
190+ size = "sm"
191+ onClick = { ( ) => handleSave ( provider . id ) }
192+ disabled = { loading || ! apiKeys [ provider . id ] . trim ( ) }
193+ className = "h-8 px-3 text-xs"
194+ >
195+ Save
196+ </ Button >
197+ { savedKeys . has ( provider . id ) && (
198+ < Button
199+ variant = "ghost"
200+ size = "sm"
201+ onClick = { ( ) => handleDelete ( provider . id ) }
202+ disabled = { loading }
203+ className = "h-8 w-8 p-0 text-muted-foreground hover:text-destructive transition-colors"
204+ title = "Remove API key"
205+ >
206+ < Trash2 className = "h-3.5 w-3.5" />
207+ </ Button >
208+ ) }
209+ </ div >
166210 </ div >
167- ) }
168- </ div >
169- < div className = "flex gap-2" >
170- < div className = "relative flex-1" >
171- < Input
172- id = { provider . id }
173- type = { showKeys [ provider . id ] ? 'text' : 'password' }
174- placeholder = { provider . placeholder }
175- value = { apiKeys [ provider . id ] }
176- onChange = { ( e ) => setApiKeys ( ( prev ) => ( { ...prev , [ provider . id ] : e . target . value } ) ) }
177- disabled = { loading }
178- />
179- < Button
180- variant = "ghost"
181- size = "sm"
182- onClick = { ( ) => toggleShowKey ( provider . id ) }
183- className = "absolute right-1 top-1/2 -translate-y-1/2 h-7 w-7 p-0"
184- type = "button"
185- >
186- { showKeys [ provider . id ] ? < EyeOff className = "h-4 w-4" /> : < Eye className = "h-4 w-4" /> }
187- </ Button >
188211 </ div >
189- < Button onClick = { ( ) => handleSave ( provider . id ) } disabled = { loading || ! apiKeys [ provider . id ] . trim ( ) } >
190- Save
191- </ Button >
192212 </ div >
193213 </ div >
194214 ) ) }
0 commit comments