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:
ZhenandDelynn Assistant authored and GitHub committed 2026-05-01 16:34:07 +07:00
1 parent 9ca388972c
commit 0da61d8f7b
29 files changed
+561 -464

No files matched your search

+22 -22
View File
@@ -125,16 +125,16 @@ export default function CombosPage() {
}
return (
<div className="flex flex-col gap-6">
<div className="flex min-w-0 flex-col gap-6 px-1 sm:px-0">
{/* Header */}
<div className="flex items-center justify-between">
<div>
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div className="min-w-0">
<h1 className="text-2xl font-semibold">Combos</h1>
<p className="text-sm text-text-muted mt-1">
Create model combos with fallback support
</p>
</div>
<Button icon="add" onClick={() => setShowCreateModal(true)}>
<Button icon="add" onClick={() => setShowCreateModal(true)} className="w-full sm:w-auto">
Create Combo
</Button>
</div>
@@ -148,7 +148,7 @@ export default function CombosPage() {
</div>
<p className="text-text-main font-medium mb-1">No combos yet</p>
<p className="text-sm text-text-muted mb-4">Create model combos with fallback support</p>
<Button icon="add" onClick={() => setShowCreateModal(true)}>
<Button icon="add" onClick={() => setShowCreateModal(true)} className="w-full sm:w-auto">
Create Combo
</Button>
</div>
@@ -195,19 +195,19 @@ export default function CombosPage() {
function ComboCard({ combo, copied, onCopy, onEdit, onDelete, roundRobinEnabled, onToggleRoundRobin }) {
return (
<Card padding="sm" className="group">
<div className="flex items-center justify-between">
<div className="flex items-center gap-3 flex-1 min-w-0">
<div className="flex min-w-0 flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div className="flex min-w-0 flex-1 items-start gap-3 sm:items-center">
<div className="size-8 rounded-lg bg-primary/10 flex items-center justify-center shrink-0">
<span className="material-symbols-outlined text-primary text-[18px]">layers</span>
</div>
<div className="min-w-0 flex-1">
<code className="text-sm font-medium font-mono truncate">{combo.name}</code>
<div className="flex items-center gap-1 mt-0.5 flex-wrap">
<code className="block truncate font-mono text-sm font-medium">{combo.name}</code>
<div className="mt-1 flex min-w-0 flex-wrap items-center gap-1">
{combo.models.length === 0 ? (
<span className="text-xs text-text-muted italic">No models</span>
) : (
combo.models.slice(0, 3).map((model, index) => (
<code key={index} className="text-[10px] font-mono bg-black/5 dark:bg-white/5 px-1.5 py-0.5 rounded text-text-muted">
<code key={index} className="max-w-full truncate rounded bg-black/5 px-1.5 py-0.5 font-mono text-[10px] text-text-muted dark:bg-white/5 sm:max-w-[220px]">
{model}
</code>
))
@@ -220,9 +220,9 @@ function ComboCard({ combo, copied, onCopy, onEdit, onDelete, roundRobinEnabled,
</div>
{/* Actions */}
<div className="flex items-center gap-3 shrink-0">
<div className="flex w-full flex-col gap-2 sm:w-auto sm:flex-row sm:items-center sm:gap-3 sm:shrink-0">
{/* Round Robin Toggle — always visible */}
<div className="flex items-center gap-1.5">
<div className="flex items-center justify-between gap-1.5 rounded-lg bg-black/[0.02] px-2 py-1.5 dark:bg-white/[0.02] sm:justify-start sm:bg-transparent sm:px-0 sm:py-0 sm:dark:bg-transparent">
<span className="text-xs text-text-muted font-medium">Round Robin</span>
<Toggle
size="sm"
@@ -231,10 +231,10 @@ function ComboCard({ combo, copied, onCopy, onEdit, onDelete, roundRobinEnabled,
/>
</div>
<div className="flex gap-1">
<div className="grid grid-cols-3 gap-1 sm:flex">
<button
onClick={(e) => { e.stopPropagation(); onCopy(combo.name, `combo-${combo.id}`); }}
className="flex flex-col items-center px-2 py-1 rounded hover:bg-black/5 dark:hover:bg-white/5 text-text-muted hover:text-primary transition-colors"
className="flex flex-col items-center rounded px-2 py-1 text-text-muted transition-colors hover:bg-black/5 hover:text-primary dark:hover:bg-white/5"
title="Copy combo name"
>
<span className="material-symbols-outlined text-[18px]">
@@ -244,7 +244,7 @@ function ComboCard({ combo, copied, onCopy, onEdit, onDelete, roundRobinEnabled,
</button>
<button
onClick={onEdit}
className="flex flex-col items-center px-2 py-1 rounded hover:bg-black/5 dark:hover:bg-white/5 text-text-muted hover:text-primary transition-colors"
className="flex flex-col items-center rounded px-2 py-1 text-text-muted transition-colors hover:bg-black/5 hover:text-primary dark:hover:bg-white/5"
title="Edit"
>
<span className="material-symbols-outlined text-[18px]">edit</span>
@@ -252,7 +252,7 @@ function ComboCard({ combo, copied, onCopy, onEdit, onDelete, roundRobinEnabled,
</button>
<button
onClick={onDelete}
className="flex flex-col items-center px-2 py-1 rounded hover:bg-red-500/10 text-red-500 transition-colors"
className="flex flex-col items-center rounded px-2 py-1 text-red-500 transition-colors hover:bg-red-500/10"
title="Delete"
>
<span className="material-symbols-outlined text-[18px]">delete</span>
@@ -283,7 +283,7 @@ function ModelItem({ index, model, isFirst, isLast, onEdit, onMoveUp, onMoveDown
};
return (
<div className="group flex items-center gap-1.5 px-2 py-1 rounded-md bg-black/[0.02] dark:bg-white/[0.02] hover:bg-black/[0.04] dark:hover:bg-white/[0.04] transition-colors">
<div className="group flex min-w-0 items-center gap-1.5 rounded-md bg-black/[0.02] px-2 py-1 transition-colors hover:bg-black/[0.04] dark:bg-white/[0.02] dark:hover:bg-white/[0.04]">
{/* Index badge */}
<span className="text-[10px] font-medium text-text-muted w-3 text-center shrink-0">{index + 1}</span>
@@ -295,11 +295,11 @@ function ModelItem({ index, model, isFirst, isLast, onEdit, onMoveUp, onMoveDown
onChange={(e) => setDraft(e.target.value)}
onBlur={commit}
onKeyDown={handleKeyDown}
className="flex-1 min-w-0 px-1.5 py-0.5 text-xs font-mono bg-white dark:bg-black/20 border border-primary/40 rounded outline-none text-text-main"
className="min-w-0 flex-1 rounded border border-primary/40 bg-white px-1.5 py-0.5 font-mono text-xs text-text-main outline-none dark:bg-black/20"
/>
) : (
<div
className="flex-1 min-w-0 px-1.5 py-0.5 text-xs font-mono text-text-main truncate cursor-text hover:bg-black/5 dark:hover:bg-white/5 rounded"
className="min-w-0 flex-1 cursor-text truncate rounded px-1.5 py-0.5 font-mono text-xs text-text-main hover:bg-black/5 dark:hover:bg-white/5"
onClick={() => setEditing(true)}
title="Click to edit"
>
@@ -308,7 +308,7 @@ function ModelItem({ index, model, isFirst, isLast, onEdit, onMoveUp, onMoveDown
)}
{/* Priority arrows */}
<div className="flex items-center gap-0.5">
<div className="flex shrink-0 items-center gap-0.5">
<button
onClick={onMoveUp}
disabled={isFirst}
@@ -448,7 +448,7 @@ function ComboFormModal({ isOpen, combo, onClose, onSave, activeProviders, kindF
<p className="text-xs text-text-muted">No models added yet</p>
</div>
) : (
<div className="flex flex-col gap-1 max-h-[350px] overflow-y-auto">
<div className="flex max-h-[55vh] min-w-0 flex-col gap-1 overflow-y-auto sm:max-h-[350px]">
{models.map((model, index) => (
<ModelItem
key={index}
@@ -480,7 +480,7 @@ function ComboFormModal({ isOpen, combo, onClose, onSave, activeProviders, kindF
</div>
{/* Actions */}
<div className="flex gap-2 pt-1">
<div className="flex flex-col gap-2 pt-1 sm:flex-row">
<Button onClick={onClose} variant="ghost" fullWidth size="sm">
Cancel
</Button>