style(ext): improve config panel

This commit is contained in:
Simon
2026-02-02 19:51:48 +08:00
parent 9ba95e96b6
commit b8999fdb7c
2 changed files with 61 additions and 15 deletions

View File

@@ -82,7 +82,12 @@ export default function App() {
</div> </div>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<StatusDot status={status} /> <StatusDot status={status} />
<Button variant="ghost" size="icon-sm" onClick={() => setShowConfig(true)}> <Button
variant="ghost"
size="icon-sm"
onClick={() => setShowConfig(true)}
className="cursor-pointer"
>
<Settings className="size-3.5" /> <Settings className="size-3.5" />
</Button> </Button>
</div> </div>
@@ -142,7 +147,7 @@ export default function App() {
variant="default" variant="default"
onClick={() => handleSubmit()} onClick={() => handleSubmit()}
disabled={!inputValue.trim()} disabled={!inputValue.trim()}
className="size-7" className="size-7 cursor-pointer"
> >
<Send className="size-3" /> <Send className="size-3" />
</InputGroupButton> </InputGroupButton>

View File

@@ -1,5 +1,5 @@
import type { LLMConfig } from '@page-agent/llms' import type { LLMConfig } from '@page-agent/llms'
import { Copy, Loader2 } from 'lucide-react' import { Copy, CornerUpLeft, Eye, EyeOff, Loader2 } from 'lucide-react'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { DEMO_API_KEY, DEMO_BASE_URL, DEMO_MODEL } from '@/agent/constants' import { DEMO_API_KEY, DEMO_BASE_URL, DEMO_MODEL } from '@/agent/constants'
@@ -19,6 +19,8 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) {
const [saving, setSaving] = useState(false) const [saving, setSaving] = useState(false)
const [userAuthToken, setUserAuthToken] = useState<string>('') const [userAuthToken, setUserAuthToken] = useState<string>('')
const [copied, setCopied] = useState(false) const [copied, setCopied] = useState(false)
const [showToken, setShowToken] = useState(false)
const [showApiKey, setShowApiKey] = useState(false)
// Update local state when config prop changes // Update local state when config prop changes
useEffect(() => { useEffect(() => {
@@ -69,8 +71,18 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) {
} }
return ( return (
<div className="flex flex-col gap-4 p-4"> <div className="flex flex-col gap-4 p-4 relative">
<h2 className="text-base font-semibold">Settings</h2> <div className="flex items-center justify-between">
<h2 className="text-base font-semibold">Settings</h2>
<Button
variant="ghost"
size="icon-sm"
onClick={onClose}
className="absolute top-2 right-3 cursor-pointer"
>
<CornerUpLeft className="size-3.5" />
</Button>
</div>
{/* User Auth Token Section */} {/* User Auth Token Section */}
<div className="flex flex-col gap-1.5 p-3 bg-muted/50 rounded-md border"> <div className="flex flex-col gap-1.5 p-3 bg-muted/50 rounded-md border">
@@ -81,9 +93,24 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) {
<div className="flex gap-2 items-center"> <div className="flex gap-2 items-center">
<Input <Input
readOnly readOnly
value={userAuthToken || 'Loading...'} value={
userAuthToken
? showToken
? userAuthToken
: `${userAuthToken.slice(0, 4)}${''.repeat(userAuthToken.length - 8)}${userAuthToken.slice(-4)}`
: 'Loading...'
}
className="text-xs h-8 font-mono bg-background" className="text-xs h-8 font-mono bg-background"
/> />
<Button
variant="outline"
size="icon"
className="h-8 w-8 shrink-0 cursor-pointer"
onClick={() => setShowToken(!showToken)}
disabled={!userAuthToken}
>
{showToken ? <EyeOff className="size-3" /> : <Eye className="size-3" />}
</Button>
<Button <Button
variant="outline" variant="outline"
size="icon" size="icon"
@@ -118,20 +145,34 @@ export function ConfigPanel({ config, onSave, onClose }: ConfigPanelProps) {
<div className="flex flex-col gap-1.5"> <div className="flex flex-col gap-1.5">
<label className="text-xs text-muted-foreground">API Key</label> <label className="text-xs text-muted-foreground">API Key</label>
<Input <div className="flex gap-2 items-center">
type="password" <Input
placeholder="sk-..." type={showApiKey ? 'text' : 'password'}
value={apiKey} placeholder="sk-..."
onChange={(e) => setApiKey(e.target.value)} value={apiKey}
className="text-xs h-8" onChange={(e) => setApiKey(e.target.value)}
/> className="text-xs h-8"
/>
<Button
variant="outline"
size="icon"
className="h-8 w-8 shrink-0 cursor-pointer"
onClick={() => setShowApiKey(!showApiKey)}
>
{showApiKey ? <EyeOff className="size-3" /> : <Eye className="size-3" />}
</Button>
</div>
</div> </div>
<div className="flex gap-2 mt-2"> <div className="flex gap-2 mt-2">
<Button variant="outline" onClick={onClose} className="flex-1 h-8 text-xs"> <Button variant="outline" onClick={onClose} className="flex-1 h-8 text-xs cursor-pointer">
Cancel Cancel
</Button> </Button>
<Button onClick={handleSave} disabled={saving} className="flex-1 h-8 text-xs"> <Button
onClick={handleSave}
disabled={saving}
className="flex-1 h-8 text-xs cursor-pointer"
>
{saving ? <Loader2 className="size-3 animate-spin" /> : 'Save'} {saving ? <Loader2 className="size-3 animate-spin" /> : 'Save'}
</Button> </Button>
</div> </div>