Skip to content

Commit ca3a3ce

Browse files
Alexey Panfilovclaude
andcommitted
fix(adminapi): full-width layout + expandable recommendations explainer
- Remove body max-width: 1200px cap. The admin page is data-dense (14 columns of model metrics) and users with wide displays were stuck scrolling a narrow column with huge dead space on both sides. Body now uses the full viewport with 1.5rem/2rem padding. - Replace the hover-only "How recommendations work" title tooltip with a click-expandable <details> block. The tooltip approach was unreliable across browsers for multi-line text and required hovering over a tiny text target; <details> renders the full formula inline, with a formatted block that wraps code samples and highlights the sections (Pareto / knee point / effective price / quality axis per role). - Add .table-wrap { overflow-x: auto } so the 14-column table scrolls horizontally when the viewport is narrower than its natural width, without clipping or breaking the page. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent dd88cb2 commit ca3a3ce

2 files changed

Lines changed: 27 additions & 5 deletions

File tree

internal/adminapi/templates/index.html

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<script src="/static/dzarlax.js" defer></script>
99
<script src="/static/htmx.min.js" defer></script>
1010
<style>
11-
body { padding: 1.5rem; max-width: var(--container-lg, 1200px); margin: 0 auto; }
11+
body { padding: 1.5rem 2rem; margin: 0; max-width: none; }
1212
h1 { margin-bottom: 1rem; }
1313
.admin-section { margin-bottom: 2rem; }
1414
.filters { display: flex; gap: 0.75rem; flex-wrap: wrap; align-items: center; margin-bottom: 1rem; }
@@ -20,7 +20,16 @@
2020
.price-cell { white-space: nowrap; font-variant-numeric: tabular-nums; }
2121
.preset-banner { padding: 0.75rem 1rem; border-radius: var(--radius, 8px); background: var(--surface-2, #E8E6E3); margin-bottom: 1rem; display: flex; justify-content: space-between; align-items: center; gap: 1rem; flex-wrap: wrap; }
2222
.preset-banner .preset-meta { color: var(--text-secondary, rgba(0,0,0,0.6)); font-size: 0.875rem; margin-top: 0.25rem; }
23+
.preset-banner details { margin-top: 0.5rem; font-size: 0.85em; }
24+
.preset-banner details > summary { cursor: pointer; color: var(--text-secondary, rgba(0,0,0,0.6)); user-select: none; list-style: none; }
25+
.preset-banner details > summary::-webkit-details-marker { display: none; }
26+
.preset-banner details > summary::before { content: "▸ "; display: inline-block; transition: transform 0.15s; }
27+
.preset-banner details[open] > summary::before { content: "▾ "; }
28+
.preset-banner details .formula { margin-top: 0.5rem; padding: 0.5rem 0.75rem; background: rgba(0,0,0,0.04); border-left: 3px solid var(--accent, #888); border-radius: 4px; line-height: 1.45; font-size: 0.9em; }
29+
.preset-banner details .formula code { background: rgba(0,0,0,0.06); padding: 0 0.25rem; border-radius: 3px; }
2330
.suggest-btn { margin-left: 0.5rem; }
31+
.table-wrap { overflow-x: auto; }
32+
.table-wrap table { width: 100%; }
2433
</style>
2534
</head>
2635
<body>

internal/adminapi/templates/partials_models_browser.html

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,29 @@
2424
<strong>Suggesting for role:</strong> <code>{{.Filters.ActivePreset}}</code>
2525
<span style="color:var(--text-secondary);margin-left:0.5rem;">— {{len .Models}} candidates</span>
2626
<div class="preset-meta">{{.Filters.PresetDescription}}</div>
27-
<div class="preset-meta" style="color:var(--text-secondary);font-size:0.85em;margin-top:0.25rem;"
28-
title="Pareto frontier: model kept iff no other has both higher quality AND lower price. Then sorted by quality desc.&#10;&#10;Best value (knee point): max(quality / price) among frontier models where quality ≥ 50% of top. Hidden when the top-quality model is already best value.&#10;&#10;Effective price for non-vision candidates under simple/default/complex: 0.9 × candidate.prompt + 0.1 × multimodal_slot.prompt — assumes 10% of messages contain images.">
29-
<em>How recommendations work</em>
30-
</div>
3127
{{if .Filters.ValueLeaderID}}
3228
<div class="preset-meta" style="margin-top:0.25rem;">
3329
<strong>Best value:</strong> <code>{{.Filters.ValueLeaderID}}</code>
3430
<span style="color:var(--text-secondary);">— {{.Filters.ValueLeaderHint}}</span>
3531
</div>
3632
{{end}}
33+
<details>
34+
<summary>How recommendations work</summary>
35+
<div class="formula">
36+
<strong>Pareto frontier:</strong> a model is kept iff no other candidate has both higher quality AND lower price. Frontier is then sorted by quality descending, so the top row is the best achievable quality under the filters.
37+
<br><br>
38+
<strong>Best value (knee point):</strong> among frontier models with quality ≥ 50% of the top, pick the one that maximises <code>quality / price</code>. Shown separately only when it's <em>not</em> the top-quality model — i.e., when there's a real trade-off to make.
39+
<br><br>
40+
<strong>Effective price</strong> (Eff$ column) accounts for capability fallback:
41+
for <code>simple</code>/<code>default</code>/<code>complex</code>, non-vision candidates are charged
42+
<code>0.9 × prompt + 0.1 × multimodal_slot.prompt</code> because image messages route to the multimodal slot. Assumes 10% of messages contain images. Vision-capable models pay nominal price.
43+
<br><br>
44+
<strong>Quality axis</strong> is role-specific:
45+
<code>simple</code>/<code>default</code>/<code>complex</code> → AA Agentic Index;
46+
<code>multimodal</code>/<code>compaction</code> → AA Intelligence Index;
47+
<code>classifier</code> → 1/TTFT when speed data available, else Intelligence.
48+
</div>
49+
</details>
3750
</div>
3851
<button class="btn btn--ghost btn--small"
3952
hx-get="/models"

0 commit comments

Comments
 (0)