diff --git a/studio/frontend/src/features/model-picker/components/model-selector.tsx b/studio/frontend/src/features/model-picker/components/model-selector.tsx
index cda6e49e24..9ae7e59a1f 100644
--- a/studio/frontend/src/features/model-picker/components/model-selector.tsx
+++ b/studio/frontend/src/features/model-picker/components/model-selector.tsx
@@ -301,12 +301,12 @@ const HUB_SECTION_TABS: { value: string; label: string; icon?: ReactNode }[] = [
{
value: "recommended",
label: "Recommended",
- icon: ,
+ icon: ,
},
{
value: "downloaded",
label: "On Device",
- icon: ,
+ icon: ,
},
];
@@ -384,7 +384,9 @@ function ModelSelectorContent({
{
value: "connected",
label: "Connected",
- icon: ,
+ icon: (
+
+ ),
},
]
: HUB_SECTION_TABS,
diff --git a/studio/frontend/src/features/model-picker/components/model-selector/pickers.tsx b/studio/frontend/src/features/model-picker/components/model-selector/pickers.tsx
index 20810b3f11..71b20058f4 100644
--- a/studio/frontend/src/features/model-picker/components/model-selector/pickers.tsx
+++ b/studio/frontend/src/features/model-picker/components/model-selector/pickers.tsx
@@ -3064,13 +3064,18 @@ export function HubModelPicker({
) : null}
- {/* Section tabs then the format and sort dropdowns, packed left with one
- uniform gap between every control. The box is sized so the last
- dropdown still lands on Search Hub's edge. Dropdowns hide on Connected. */}
-
+ {/* Keep the left-packed controls on one line while they fit, then wrap
+ whole groups before their intrinsic widths cross the picker edge.
+ Dropdowns hide on Connected. */}
+
{sectionToggle}
{showConnected ? null : (
-
+
onValueChange(tab.value)}
className={cn(
"relative z-10 inline-flex items-center justify-center gap-1.5 rounded-full transition-colors",
- fit ? "shrink-0" : "min-w-0 flex-1",
+ fit ? "min-w-0 shrink" : "min-w-0 flex-1",
compact ? "h-7 px-2.5 text-ui-11" : "h-9 px-3 text-ui-12p5",
value === tab.value
? "text-foreground"
@@ -97,7 +98,7 @@ export function PillTabs({
)}
>
{tab.icon}
- {tab.label}
+ {tab.label}
))}
diff --git a/tests/studio/test_model_picker_contracts.py b/tests/studio/test_model_picker_contracts.py
index 62b1a3cf76..3934b72d83 100644
--- a/tests/studio/test_model_picker_contracts.py
+++ b/tests/studio/test_model_picker_contracts.py
@@ -217,6 +217,24 @@ def test_local_picker_rows_require_chat_capability():
assert "row.capabilities.canChat" in memo.group(0)
+def test_model_picker_toolbar_reflows_before_crossing_picker_edge():
+ """The content-sized section tabs and fixed-width dropdowns must reflow,
+ while an oversized tab group must shrink labels but preserve its icons."""
+ picker = _read("features/model-picker/components/model-selector/pickers.tsx")
+ assert '"flex flex-wrap items-center gap-2"' in picker
+ assert 'hasConnected ? "-mr-4" : "-mr-2"' in picker
+ assert '"flex max-w-full min-w-0 flex-wrap items-center gap-2"' in picker
+
+ tabs = _read("features/model-picker/components/model-selector/pill-tabs.tsx")
+ assert 'fit ? "min-w-0 shrink" : "min-w-0 flex-1"' in tabs
+ assert '
{tab.label}' in tabs
+
+ selector = _read("features/model-picker/components/model-selector.tsx")
+ assert 'icon={StarIcon} className="size-3.5 shrink-0"' in selector
+ assert 'icon={Download01Icon} className="size-3.5 shrink-0"' in selector
+ assert 'icon={CloudIcon} className="size-3.5 shrink-0"' in selector
+
+
def test_native_picked_gguf_template_read_through_lease():
"""A native (picked / drag-drop) GGUF's path lives only in its signed lease,
and the picker chat-template GET has no lease plumbing, so the default