Skip to content

Commit 0aee869

Browse files
committed
Make the API keys dialog more minimalist and intui...
1 parent 6e98a01 commit 0aee869

File tree

1 file changed

+69
-49
lines changed

1 file changed

+69
-49
lines changed

components/api-keys-dialog.tsx

Lines changed: 69 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { Button } from '@/components/ui/button'
66
import { Input } from '@/components/ui/input'
77
import { Label } from '@/components/ui/label'
88
import { toast } from 'sonner'
9-
import { Eye, EyeOff, Trash2, Check } from 'lucide-react'
9+
import { Eye, EyeOff, Trash2, CheckCircle2 } from 'lucide-react'
1010

1111
interface 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

Comments
 (0)