[object Object]

← back to Exo

feat: add info button to model picker variant rows (#1589)

dc89ba662a5757c2f2878edb79ed52c1f3f97550 · 2026-02-23 09:53:36 -0800 · Alex Cheema

## Motivation

When a model has multiple quantization variants (e.g., 4-bit, 8-bit),
expanding the group shows each variant's quantization and size — but
there's no way to see which specific nodes have each variant downloaded.
The top-level model group has an (i) info button, but the individual
variant rows don't. This makes it hard to tell which nodes have which
quantization.

## Changes

- Added an (i) info button to each expanded variant row in
`ModelPickerGroup.svelte`
- When clicked, opens the existing info modal scoped to that single
variant (showing its quantization, size, and which nodes have it
downloaded)
- Changed the variant row element from `<button>` to `<div
role="button">` to allow nesting the info `<button>` (matching the
pattern used by the top-level model row)

## Why It Works

Reuses the existing `onShowInfo` callback and info modal by constructing
a synthetic single-variant `ModelGroup` from the clicked variant. No
changes needed to `ModelPickerModal.svelte` — the info modal already
handles single-variant groups correctly.

## Test Plan

### Manual Testing
<!-- Hardware: MacBook Pro -->
- Open dashboard, open model picker
- Expand a model with multiple variants — each variant row now has an
(i) icon
- Click a variant's (i) — the info modal shows that single variant's
quantization/size and which nodes have it downloaded

### Automated Testing
- Dashboard builds successfully with `npm run build`
- `nix fmt` passes

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

Files touched

Diff

commit dc89ba662a5757c2f2878edb79ed52c1f3f97550
Author: Alex Cheema <41707476+AlexCheema@users.noreply.github.com>
Date:   Mon Feb 23 09:53:36 2026 -0800

    feat: add info button to model picker variant rows (#1589)
    
    ## Motivation
    
    When a model has multiple quantization variants (e.g., 4-bit, 8-bit),
    expanding the group shows each variant's quantization and size — but
    there's no way to see which specific nodes have each variant downloaded.
    The top-level model group has an (i) info button, but the individual
    variant rows don't. This makes it hard to tell which nodes have which
    quantization.
    
    ## Changes
    
    - Added an (i) info button to each expanded variant row in
    `ModelPickerGroup.svelte`
    - When clicked, opens the existing info modal scoped to that single
    variant (showing its quantization, size, and which nodes have it
    downloaded)
    - Changed the variant row element from `<button>` to `<div
    role="button">` to allow nesting the info `<button>` (matching the
    pattern used by the top-level model row)
    
    ## Why It Works
    
    Reuses the existing `onShowInfo` callback and info modal by constructing
    a synthetic single-variant `ModelGroup` from the clicked variant. No
    changes needed to `ModelPickerModal.svelte` — the info modal already
    handles single-variant groups correctly.
    
    ## Test Plan
    
    ### Manual Testing
    <!-- Hardware: MacBook Pro -->
    - Open dashboard, open model picker
    - Expand a model with multiple variants — each variant row now has an
    (i) icon
    - Click a variant's (i) — the info modal shows that single variant's
    quantization/size and which nodes have it downloaded
    
    ### Automated Testing
    - Dashboard builds successfully with `npm run build`
    - `nix fmt` passes
    
    Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
---
 .../src/lib/components/ModelPickerGroup.svelte     | 45 ++++++++++++++++++++--
 1 file changed, 41 insertions(+), 4 deletions(-)

diff --git a/dashboard/src/lib/components/ModelPickerGroup.svelte b/dashboard/src/lib/components/ModelPickerGroup.svelte
index e8e893d6..b5270f5a 100644
--- a/dashboard/src/lib/components/ModelPickerGroup.svelte
+++ b/dashboard/src/lib/components/ModelPickerGroup.svelte
@@ -490,20 +490,28 @@
         {@const modelCanFit = canModelFit(variant.id)}
         {@const variantHasInstance = instanceStatuses[variant.id] != null}
         {@const isSelected = selectedModelId === variant.id}
-        <button
-          type="button"
+        <div
           class="w-full flex items-center gap-3 px-3 py-2 pl-10 hover:bg-white/5 transition-colors text-left {!modelCanFit &&
           !variantHasInstance
             ? 'opacity-50 cursor-not-allowed'
             : 'cursor-pointer'} {isSelected
             ? 'bg-exo-yellow/10 border-l-2 border-exo-yellow'
             : 'border-l-2 border-transparent'}"
-          disabled={!modelCanFit && !variantHasInstance}
+          role="button"
+          tabindex="0"
           onclick={() => {
             if (modelCanFit || variantHasInstance) {
               onSelectModel(variant.id);
             }
           }}
+          onkeydown={(e) => {
+            if (e.key === "Enter" || e.key === " ") {
+              e.preventDefault();
+              if (modelCanFit) {
+                onSelectModel(variant.id);
+              }
+            }
+          }}
         >
           <!-- Quantization badge -->
           <span
@@ -602,7 +610,36 @@
               />
             </svg>
           {/if}
-        </button>
+
+          <!-- Info button -->
+          <button
+            type="button"
+            class="p-1 rounded hover:bg-white/10 transition-colors flex-shrink-0"
+            onclick={(e) => {
+              e.stopPropagation();
+              onShowInfo({
+                id: variant.id,
+                name: variant.name || variant.id,
+                capabilities: group.capabilities,
+                family: group.family,
+                variants: [variant],
+                smallestVariant: variant,
+                hasMultipleVariants: false,
+              });
+            }}
+            title="View variant details"
+          >
+            <svg
+              class="w-4 h-4 text-white/30 hover:text-white/50"
+              viewBox="0 0 24 24"
+              fill="currentColor"
+            >
+              <path
+                d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"
+              />
+            </svg>
+          </button>
+        </div>
       {/each}
     </div>
   {/if}

← 5cd96b50 feat: seamless chat UX with auto model selection and smart r  ·  back to Exo  ·  fix: detect completed downloads by checking final file exist 7024ddcf →