Skip to content

Commit fdcce52

Browse files
authored
many changes to model cards, as well as a hero oversight (#351)
1 parent 8967ac6 commit fdcce52

File tree

6 files changed

+219
-127
lines changed

6 files changed

+219
-127
lines changed

www/src/lib/components/home/features.svelte

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
1919
const animateCards = () => {
2020
cards.forEach((card, index) => {
21-
card.style.transition = 'all 600ms cubic-bezier(0.4, 0, 0.2, 1)';
21+
card.style.transition =
22+
'opacity 600ms cubic-bezier(0.4, 0, 0.2, 1), transform 600ms cubic-bezier(0.4, 0, 0.2, 1)';
2223
card.style.transitionDelay = `${index * 100}ms`;
2324
2425
requestAnimationFrame(() => {
@@ -178,7 +179,7 @@
178179
class="hw-card hw-1 border-border bg-secondary/50 flex flex-col items-center rounded-xl border p-3"
179180
>
180181
<div class="text-primary text-2xl font-bold">NPU</div>
181-
<div class="text-xs whitespace-nowrap text-muted-foreground">Neural Engine</div>
182+
<div class="text-muted-foreground text-xs whitespace-nowrap">Neural Engine</div>
182183
</div>
183184
<div
184185
class="hw-card hw-2 border-border bg-secondary/50 flex flex-col items-center rounded-xl border p-3"
@@ -190,7 +191,7 @@
190191
class="hw-card hw-3 border-border bg-secondary/50 flex flex-col items-center rounded-xl border p-3"
191192
>
192193
<div class="text-2xl font-bold text-violet-500">CPU</div>
193-
<div class="text-xs whitespace-nowrap text-muted-foreground">Processor</div>
194+
<div class="text-muted-foreground text-xs whitespace-nowrap">Processor</div>
194195
</div>
195196
</div>
196197
<style>
@@ -434,10 +435,10 @@
434435
<div class="absolute right-3 bottom-3 overflow-hidden rounded-lg bg-gray-900/90 p-2">
435436
<div class="api-compare font-mono text-[10px] leading-tight">
436437
<div class="api-line api-line-1 text-gray-400 line-through">
437-
base_url=<span class="text-amber-300">"localhost"</span>
438+
base_url=<span class="text-amber-300">"api.openai.com"</span>
438439
</div>
439440
<div class="api-line api-line-2 text-emerald-400">
440-
base_url=<span class="text-amber-300">"localhost:5273"</span>
441+
base_url=<span class="text-amber-300">"localhost"</span>
441442
</div>
442443
</div>
443444
</div>

www/src/lib/components/ui/dialog/dialog-content.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@
2222
<DialogPrimitive.Content
2323
bind:ref
2424
class={cn(
25-
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
25+
'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg',
2626
className
2727
)}
2828
{...restProps}
2929
>
3030
{@render children?.()}
3131
<DialogPrimitive.Close
32-
class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"
32+
class="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-none disabled:pointer-events-none"
3333
>
3434
<X class="size-4" />
3535
<span class="sr-only">Close</span>
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// Template-based dynamic model description generator
2+
// Replaces static API descriptions with context-aware text based on device/framework
3+
4+
import type { GroupedFoundryModel } from '../../routes/models/types';
5+
6+
/**
7+
* Acceleration display names mapping
8+
*/
9+
const ACCELERATION_DISPLAY_NAMES: Record<string, string> = {
10+
qnn: 'Qualcomm AI Engine',
11+
vitis: 'AMD Vitis AI',
12+
openvino: 'Intel OpenVINO',
13+
cuda: 'NVIDIA CUDA',
14+
'trt-rtx': 'NVIDIA TensorRT',
15+
trtrtx: 'NVIDIA TensorRT',
16+
webgpu: 'WebGPU'
17+
};
18+
19+
/**
20+
* Format a list of devices into a human-readable string
21+
* e.g., ['cpu', 'gpu', 'npu'] -> "CPU, GPU, and NPU"
22+
*/
23+
function formatDeviceList(devices: string[]): string {
24+
if (devices.length === 0) return 'various devices';
25+
26+
const formatted = devices.map((d) => d.toUpperCase());
27+
28+
if (formatted.length === 1) {
29+
return formatted[0];
30+
} else if (formatted.length === 2) {
31+
return `${formatted[0]} and ${formatted[1]}`;
32+
} else {
33+
const last = formatted.pop();
34+
return `${formatted.join(', ')}, and ${last}`;
35+
}
36+
}
37+
38+
/**
39+
* Get the display name for an acceleration type
40+
*/
41+
function getAccelerationDisplayName(acceleration: string): string {
42+
return ACCELERATION_DISPLAY_NAMES[acceleration.toLowerCase()] || acceleration;
43+
}
44+
45+
/**
46+
* Get unique accelerations from a grouped model's variants
47+
*/
48+
function getUniqueAccelerations(model: GroupedFoundryModel): string[] {
49+
if (!model.variants || model.variants.length === 0) {
50+
return model.acceleration ? [model.acceleration] : [];
51+
}
52+
53+
const accelerations = new Set<string>();
54+
for (const variant of model.variants) {
55+
if (variant.acceleration) {
56+
accelerations.add(variant.acceleration);
57+
}
58+
}
59+
return Array.from(accelerations);
60+
}
61+
62+
/**
63+
* Generate a dynamic description for a model based on its properties
64+
*/
65+
export function generateModelDescription(model: GroupedFoundryModel): string {
66+
const displayName = model.displayName || model.alias || 'this model';
67+
const devices = model.deviceSupport || [];
68+
const accelerations = getUniqueAccelerations(model);
69+
70+
// Base description
71+
let description = `${displayName} is optimized for local inference`;
72+
73+
// Add device information
74+
if (devices.length > 0) {
75+
description += ` on ${formatDeviceList(devices)}`;
76+
}
77+
78+
description += '.';
79+
80+
// Add acceleration framework information
81+
if (accelerations.length > 0) {
82+
const accelerationNames = accelerations.map(getAccelerationDisplayName);
83+
if (accelerationNames.length === 1) {
84+
description += ` Uses ${accelerationNames[0]} for acceleration.`;
85+
} else if (accelerationNames.length === 2) {
86+
description += ` Available with ${accelerationNames[0]} or ${accelerationNames[1]} acceleration.`;
87+
} else {
88+
const last = accelerationNames.pop();
89+
description += ` Available with ${accelerationNames.join(', ')}, or ${last} acceleration.`;
90+
}
91+
}
92+
93+
return description;
94+
}

www/src/routes/models/components/ModelCard.svelte

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
getAcceleratorColor,
2121
getVariantLabel
2222
} from '$lib/utils/model-helpers';
23+
import { generateModelDescription } from '$lib/utils/model-description';
2324
2425
function getUniqueVariants() {
2526
if (!model.variants || model.variants.length === 0) return [];
@@ -85,13 +86,13 @@
8586
}
8687
8788
$: uniqueVariants = sortVariantsByDevice(getUniqueVariants());
88-
$: displayDescription = cleanDescription(model.description);
89+
$: displayDescription = generateModelDescription(model);
8990
$: genericModelName = getGenericModelName();
9091
</script>
9192

9293
<div use:animate={{ delay: 0, duration: 600, animation: 'fade-in', once: true }} class="flex">
9394
<Card.Root
94-
class="border-border/40 hover:border-primary/50 relative z-0 flex flex-1 cursor-pointer flex-col transition-all duration-300 focus-within:z-20 hover:z-20 hover:-translate-y-1 hover:shadow-xl focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2"
95+
class="border-border/40 hover:border-primary/50 focus:ring-primary relative z-0 flex flex-1 cursor-pointer flex-col transition-all duration-300 focus-within:z-20 hover:z-20 focus:ring-2 focus:ring-offset-2 focus:outline-none"
9596
onclick={() => onCardClick(model)}
9697
onkeydown={(e) => {
9798
if (e.key === 'Enter' || e.key === ' ') {
@@ -124,12 +125,12 @@
124125
</div>
125126
</Card.Header>
126127
<Card.Content class="flex flex-1 flex-col pt-0">
127-
<p class="mb-3 text-sm text-gray-600 dark:text-gray-400">
128+
<p class="mb-3 line-clamp-3 min-h-[3.75rem] text-sm text-gray-600 dark:text-gray-400">
128129
{displayDescription}
129130
</p>
130131

131132
<!-- Badges - Task Type, File Size, License -->
132-
<div class="mb-3 mt-auto flex flex-row flex-wrap items-center gap-1">
133+
<div class="mb-3 flex min-h-[1.5rem] flex-row flex-wrap items-center gap-1">
133134
{#if model.fileSizeBytes}
134135
<Badge variant="secondary" class="flex shrink-0 items-center gap-1 text-xs">
135136
<svg class="size-3" fill="currentColor" viewBox="0 0 20 20">
@@ -187,7 +188,7 @@
187188
</div>
188189

189190
<!-- Copy Run Command Section -->
190-
<div class="border-t border-border/40 pt-3">
191+
<div class="border-border/40 border-t pt-3">
191192
{#if uniqueVariants.length > 0}
192193
<div class="space-y-1.5">
193194
<div class="text-xs font-medium text-gray-600 dark:text-gray-400">

0 commit comments

Comments
 (0)