Improve dashboard responsive layouts (#805)

* Improve dashboard responsive layouts

* Improve proxy pools mobile layout

* Improve CLI tool card input responsiveness

---------

Co-authored-by: Delynn Assistant <zhen@dkzhen.org>
This commit is contained in:
Zhen
2026-05-01 16:34:07 +07:00
committed by GitHub
co-authored by Delynn Assistant
parent 9ca388972c
commit 0da61d8f7b
29 changed files with 561 additions and 464 deletions
@@ -189,13 +189,13 @@ export default function OpenCodeToolCard({ tool, isExpanded, onToggle, baseUrl,
return (
<Card padding="xs" className="overflow-hidden">
<div className="flex items-center justify-between hover:cursor-pointer" onClick={onToggle}>
<div className="flex items-center gap-3">
<div className="flex items-start justify-between gap-3 hover:cursor-pointer sm:items-center" onClick={onToggle}>
<div className="flex min-w-0 items-center gap-3">
<div className="size-8 flex items-center justify-center shrink-0">
<Image src="/providers/opencode.png" alt={tool.name} width={32} height={32} className="size-8 object-contain rounded-lg" sizes="32px" onError={(e) => { e.target.style.display = "none"; }} />
</div>
<div className="min-w-0">
<div className="flex items-center gap-2">
<div className="flex min-w-0 flex-wrap items-center gap-2">
<h3 className="font-medium text-sm">{tool.name}</h3>
{configStatus === "configured" && <span className="px-1.5 py-0.5 text-[10px] font-medium bg-green-500/10 text-green-600 dark:text-green-400 rounded-full">Connected</span>}
{configStatus === "not_configured" && <span className="px-1.5 py-0.5 text-[10px] font-medium bg-yellow-500/10 text-yellow-600 dark:text-yellow-400 rounded-full">Not configured</span>}
@@ -257,25 +257,25 @@ export default function OpenCodeToolCard({ tool, isExpanded, onToggle, baseUrl,
<div className="flex flex-col gap-2">
{/* Current base URL */}
{status?.config?.provider?.["9router"]?.options?.baseURL && (
<div className="flex items-center gap-2">
<span className="w-32 shrink-0 text-sm font-semibold text-text-main text-right">Current</span>
<span className="material-symbols-outlined text-text-muted text-[14px]">arrow_forward</span>
<span className="flex-1 px-2 py-1.5 text-xs text-text-muted truncate">
<div className="grid gap-1.5 sm:grid-cols-[8rem_auto_1fr_auto] sm:items-center sm:gap-2">
<span className="text-xs font-semibold text-text-main sm:text-right sm:text-sm">Current</span>
<span className="material-symbols-outlined hidden text-text-muted text-[14px] sm:inline">arrow_forward</span>
<span className="min-w-0 truncate rounded bg-surface/40 px-2 py-2 text-xs text-text-muted sm:py-1.5">
{status.config.provider["9router"].options.baseURL}
</span>
</div>
)}
{/* Base URL */}
<div className="flex items-center gap-2">
<span className="w-32 shrink-0 text-sm font-semibold text-text-main text-right">Base URL</span>
<span className="material-symbols-outlined text-text-muted text-[14px]">arrow_forward</span>
<div className="grid gap-1.5 sm:grid-cols-[8rem_auto_1fr_auto] sm:items-center sm:gap-2">
<span className="text-xs font-semibold text-text-main sm:text-right sm:text-sm">Base URL</span>
<span className="material-symbols-outlined hidden text-text-muted text-[14px] sm:inline">arrow_forward</span>
<input
type="text"
value={getDisplayUrl()}
onChange={(e) => setCustomBaseUrl(e.target.value)}
placeholder="https://.../v1"
className="flex-1 px-2 py-1.5 bg-surface rounded border border-border text-xs focus:outline-none focus:ring-1 focus:ring-primary/50"
className="min-w-0 px-2 py-2 bg-surface rounded border border-border text-xs focus:outline-none focus:ring-1 focus:ring-primary/50 sm:py-1.5"
/>
{customBaseUrl && customBaseUrl !== `${baseUrl}/v1` && (
<button onClick={() => setCustomBaseUrl("")} className="p-1 text-text-muted hover:text-primary rounded transition-colors" title="Reset to default">
@@ -285,22 +285,22 @@ export default function OpenCodeToolCard({ tool, isExpanded, onToggle, baseUrl,
</div>
{/* API Key */}
<div className="flex items-center gap-2">
<span className="w-32 shrink-0 text-sm font-semibold text-text-main text-right">API Key</span>
<span className="material-symbols-outlined text-text-muted text-[14px]">arrow_forward</span>
<div className="grid gap-1.5 sm:grid-cols-[8rem_auto_1fr_auto] sm:items-center sm:gap-2">
<span className="text-xs font-semibold text-text-main sm:text-right sm:text-sm">API Key</span>
<span className="material-symbols-outlined hidden text-text-muted text-[14px] sm:inline">arrow_forward</span>
{apiKeys.length > 0 ? (
<select value={selectedApiKey} onChange={(e) => setSelectedApiKey(e.target.value)} className="flex-1 px-2 py-1.5 bg-surface rounded text-xs border border-border focus:outline-none focus:ring-1 focus:ring-primary/50">
<select value={selectedApiKey} onChange={(e) => setSelectedApiKey(e.target.value)} className="min-w-0 px-2 py-2 bg-surface rounded text-xs border border-border focus:outline-none focus:ring-1 focus:ring-primary/50 sm:py-1.5">
{apiKeys.map((key) => <option key={key.id} value={key.key}>{key.key}</option>)}
</select>
) : (
<span className="flex-1 text-xs text-text-muted px-2 py-1.5">
<span className="min-w-0 rounded bg-surface/40 px-2 py-2 text-xs text-text-muted sm:py-1.5">
{cloudEnabled ? "No API keys - Create one in Keys page" : "sk_9router (default)"}
</span>
)}
</div>
{/* Models */}
<div className="flex items-start gap-2">
<div className="grid gap-1.5 sm:grid-cols-[8rem_auto_1fr] sm:items-start sm:gap-2">
<span className="w-32 shrink-0 text-sm font-semibold text-text-main text-right pt-1">Models</span>
<span className="material-symbols-outlined text-text-muted text-[14px] mt-1.5">arrow_forward</span>
<div className="flex-1 flex flex-col gap-2">
@@ -364,7 +364,7 @@ export default function OpenCodeToolCard({ tool, isExpanded, onToggle, baseUrl,
))
)}
</div>
<div className="flex items-center gap-2">
<div className="grid gap-1.5 sm:grid-cols-[8rem_auto_1fr_auto] sm:items-center sm:gap-2">
<button onClick={() => setModalOpen(true)} disabled={!activeProviders?.length} className={`px-2 py-1 rounded border text-xs transition-colors ${activeProviders?.length ? "bg-surface border-border text-text-main hover:border-primary cursor-pointer" : "opacity-50 cursor-not-allowed border-border"}`}>Add Model</button>
<span className="text-xs text-text-muted">
{selectedModels.length > 0 && activeModel ? (
@@ -380,20 +380,20 @@ export default function OpenCodeToolCard({ tool, isExpanded, onToggle, baseUrl,
</div>
{/* Subagent Model */}
<div className="flex items-center gap-2">
<span className="w-32 shrink-0 text-sm font-semibold text-text-main text-right">Subagent Model</span>
<span className="material-symbols-outlined text-text-muted text-[14px]">arrow_forward</span>
<div className="grid gap-1.5 sm:grid-cols-[8rem_auto_1fr_auto] sm:items-center sm:gap-2">
<span className="text-xs font-semibold text-text-main sm:text-right sm:text-sm">Subagent Model</span>
<span className="material-symbols-outlined hidden text-text-muted text-[14px] sm:inline">arrow_forward</span>
<input
type="text"
value={subagentModel}
onChange={(e) => setSubagentModel(e.target.value)}
placeholder={selectedModel || "provider/model-id (defaults to main model)"}
className="flex-1 px-2 py-1.5 bg-surface rounded border border-border text-xs focus:outline-none focus:ring-1 focus:ring-primary/50"
className="min-w-0 px-2 py-2 bg-surface rounded border border-border text-xs focus:outline-none focus:ring-1 focus:ring-primary/50 sm:py-1.5"
/>
<button
onClick={() => setSubagentModalOpen(true)}
disabled={!activeProviders?.length}
className={`px-2 py-1.5 rounded border text-xs transition-colors shrink-0 whitespace-nowrap ${activeProviders?.length ? "bg-surface border-border text-text-main hover:border-primary cursor-pointer" : "opacity-50 cursor-not-allowed border-border"}`}
className={`rounded border px-2 py-2 text-xs transition-colors sm:py-1.5 whitespace-nowrap sm:shrink-0 ${activeProviders?.length ? "bg-surface border-border text-text-main hover:border-primary cursor-pointer" : "opacity-50 cursor-not-allowed border-border"}`}
>
Select Model
</button>
@@ -416,7 +416,7 @@ export default function OpenCodeToolCard({ tool, isExpanded, onToggle, baseUrl,
</div>
)}
<div className="flex items-center gap-2">
<div className="grid grid-cols-1 gap-2 sm:flex sm:items-center">
<Button variant="primary" size="sm" onClick={handleApply} disabled={selectedModels.length === 0} loading={applying}>
<span className="material-symbols-outlined text-[14px] mr-1">save</span>Apply
</Button>