Skip to content

Commit 9c6f77a

Browse files
committed
Redesign model cards UI on models page
Refactored the models list to use a grid layout with updated card styles, improved avatar and icon presentation, and enhanced visual feedback for active and default models. The new design provides a cleaner, more modern look and better usability, especially for distinguishing model features and actions.
1 parent 94f3169 commit 9c6f77a

File tree

1 file changed

+67
-72
lines changed

1 file changed

+67
-72
lines changed

src/routes/models/+page.svelte

Lines changed: 67 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@
4747
{/if}
4848
</svelte:head>
4949

50-
<div class="scrollbar-custom h-full overflow-y-auto py-12 max-sm:pt-8 md:py-24">
50+
<div
51+
class="scrollbar-custom h-full overflow-y-auto bg-gray-50 py-12 max-sm:pt-8 dark:bg-gray-950 md:py-24"
52+
>
5153
<div class="pt-42 mx-auto flex flex-col px-5 xl:w-[60rem] 2xl:w-[64rem]">
5254
<div class="flex items-center">
5355
<h1 class="text-2xl font-bold">Models</h1>
@@ -83,102 +85,95 @@
8385
/>
8486

8587
<div class="mt-6 min-h-[50vh]">
86-
<div
87-
class="overflow-hidden rounded-2xl border border-gray-200/60 bg-white shadow-sm dark:border-gray-800 dark:bg-gray-900"
88-
>
88+
<div class="grid grid-cols-1 gap-6 p-1 md:grid-cols-2">
8989
{#each filteredModels as model, index (model.id)}
9090
{@const isActive = model.id === $settings.activeModel}
91-
{@const isLast = index === filteredModels.length - 1}
9291
<a
9392
href="{base}/models/{model.id}"
9493
aria-label="Model card for {model.displayName}"
95-
class="group flex cursor-pointer items-center gap-4 p-4
94+
class="group relative rounded-3xl border p-6 shadow-[0_2px_8px_rgba(0,0,0,0.04)] transition-all duration-300
9695
{isActive
97-
? 'bg-gray-50 dark:bg-gray-800'
98-
: 'bg-white hover:bg-gray-50 dark:bg-gray-900 dark:hover:bg-gray-800'}
99-
{isLast ? '' : 'border-b border-gray-100 dark:border-gray-800'}"
96+
? 'border-gray-900/10 bg-white shadow-lg ring-1 ring-black/5 dark:border-gray-700 dark:bg-gray-900 dark:ring-white/10'
97+
: 'border-transparent bg-white hover:-translate-y-1 hover:border-gray-200 hover:shadow-xl dark:bg-gray-900 dark:hover:border-gray-800'}"
10098
>
101-
<!-- Avatar -->
102-
<div class="flex-shrink-0">
103-
{#if model.logoUrl}
104-
<img
105-
alt={model.displayName}
106-
class="h-10 w-10 rounded-lg border border-gray-100 bg-gray-50 object-cover dark:border-gray-700 dark:bg-gray-100"
107-
src={model.logoUrl}
108-
/>
109-
{:else}
110-
<div
111-
class="h-10 w-10 rounded-lg border border-gray-100 bg-gray-200 dark:border-gray-700 dark:bg-gray-700"
112-
aria-hidden="true"
113-
></div>
114-
{/if}
115-
</div>
116-
117-
<!-- Content -->
118-
<div class="min-w-0 flex-1">
119-
<div class="flex items-center gap-2">
120-
<h3
121-
class="truncate font-medium text-gray-900 dark:text-gray-200"
122-
class:font-bold={isActive}
123-
class:dark:text-white={isActive}
124-
>
125-
{model.displayName}
126-
</h3>
127-
{#if index === 0 && model.isRouter && !isActive}
128-
<span
129-
class="rounded border border-gray-200 px-1.5 py-0.5 text-[10px] font-semibold uppercase text-gray-500 dark:border-gray-700 dark:text-gray-400"
130-
>
131-
Default
132-
</span>
99+
<!-- Header: Avatar + Icons -->
100+
<div class="mb-4 flex items-start justify-between">
101+
<!-- Avatar -->
102+
<div class="relative">
103+
{#if model.logoUrl}
104+
<img
105+
alt={model.displayName}
106+
class="h-12 w-12 rounded-2xl border border-gray-100 bg-white object-cover shadow-sm dark:border-gray-800 dark:bg-gray-800"
107+
src={model.logoUrl}
108+
/>
109+
{:else}
110+
<div
111+
class="h-12 w-12 rounded-2xl border border-gray-100 bg-gray-200 shadow-sm dark:border-gray-800 dark:bg-gray-700"
112+
aria-hidden="true"
113+
></div>
133114
{/if}
134115
</div>
135-
<p class="truncate pr-4 text-[13px] text-gray-500 dark:text-gray-400">
136-
{model.isRouter
137-
? "Routes your messages to the best model for your request."
138-
: model.description || "-"}
139-
</p>
140-
</div>
141116

142-
<!-- Icons and badges -->
143-
<div class="flex flex-shrink-0 items-center gap-1.5">
144-
<button
145-
type="button"
146-
title="Model settings"
147-
aria-label="Model settings for {model.displayName}"
148-
class="rounded-md border border-gray-200 p-1.5 text-gray-500 hover:bg-gray-100 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700"
149-
onclick={(e) => {
150-
e.preventDefault();
151-
e.stopPropagation();
152-
goto(`${base}/settings/${model.id}`);
153-
}}
154-
>
155-
<LucideSettings class="h-3.5 w-3.5" />
156-
</button>
157-
<div class="flex items-center gap-1.5">
117+
<!-- Icons -->
118+
<div class="flex items-center gap-2">
158119
{#if $settings.toolsOverrides?.[model.id] ?? (model as { supportsTools?: boolean }).supportsTools}
159120
<div
160121
title="This model supports tool calling (functions)."
161-
class="rounded-md bg-purple-50 p-1.5 text-purple-600 dark:bg-purple-900/20 dark:text-purple-400"
122+
class="flex h-8 w-8 items-center justify-center rounded-full bg-purple-50 text-purple-600 transition-colors dark:bg-purple-900/20 dark:text-purple-400"
162123
>
163124
<LucideHammer class="h-3.5 w-3.5" />
164125
</div>
165126
{/if}
166127
{#if $settings.multimodalOverrides?.[model.id] ?? model.multimodal}
167128
<div
168129
title="This model is multimodal and supports image inputs natively."
169-
class="rounded-md bg-blue-50 p-1.5 text-blue-600 dark:bg-blue-900/20 dark:text-blue-400"
130+
class="flex h-8 w-8 items-center justify-center rounded-full bg-blue-50 text-blue-600 transition-colors dark:bg-blue-900/20 dark:text-blue-400"
170131
>
171132
<LucideImage class="h-3.5 w-3.5" />
172133
</div>
173134
{/if}
174-
</div>
175-
{#if isActive}
176-
<span
177-
class="rounded-full bg-black px-2.5 py-1 text-xs font-bold text-white shadow-md dark:bg-white dark:text-black"
135+
<button
136+
type="button"
137+
title="Model settings"
138+
aria-label="Model settings for {model.displayName}"
139+
class="flex h-8 w-8 items-center justify-center rounded-full bg-gray-50 text-gray-400 transition-colors hover:bg-gray-100 hover:text-gray-600 dark:bg-gray-800 dark:hover:bg-gray-700 dark:hover:text-gray-200"
140+
onclick={(e) => {
141+
e.preventDefault();
142+
e.stopPropagation();
143+
goto(`${base}/settings/${model.id}`);
144+
}}
178145
>
179-
Active
180-
</span>
181-
{/if}
146+
<LucideSettings class="h-3.5 w-3.5" />
147+
</button>
148+
{#if isActive}
149+
<span
150+
class="ml-2 rounded-full bg-black px-2.5 py-1 text-xs font-bold text-white shadow-lg dark:bg-white dark:text-black"
151+
>
152+
Active
153+
</span>
154+
{/if}
155+
</div>
156+
</div>
157+
158+
<!-- Content -->
159+
<div>
160+
<div class="mb-1 flex items-center gap-2">
161+
<h3 class="text-lg font-semibold tracking-tight text-gray-900 dark:text-gray-100">
162+
{model.displayName}
163+
</h3>
164+
{#if index === 0 && model.isRouter && !isActive}
165+
<span
166+
class="rounded-full border border-gray-200 px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider text-gray-500 dark:border-gray-700 dark:text-gray-400"
167+
>
168+
Default
169+
</span>
170+
{/if}
171+
</div>
172+
<p class="line-clamp-2 text-sm leading-relaxed text-gray-500 dark:text-gray-400">
173+
{model.isRouter
174+
? "Routes your messages to the best model for your request."
175+
: model.description || "-"}
176+
</p>
182177
</div>
183178
</a>
184179
{/each}

0 commit comments

Comments
 (0)