From 8f0c0608b663c5aba07ffd109c32d4ebfaf1babb Mon Sep 17 00:00:00 2001 From: Unsloth Date: Wed, 29 Jul 2026 01:22:12 -0700 Subject: [PATCH] Studio: rework the GPU device row Restores the earlier shape, name over backend on the left, but lifts the memory figures and the meter up beside them instead of stacking them underneath. The meter is short rather than full width, which was the original complaint: at full width it read as a rule across the pane rather than a reading for one device. VRAM utilization becomes a rounded pill next to the backend label. The row wraps rather than squeezing the device name when the pane is narrow. --- .../features/settings/tabs/resources-tab.tsx | 168 +++++++++--------- 1 file changed, 81 insertions(+), 87 deletions(-) diff --git a/studio/frontend/src/features/settings/tabs/resources-tab.tsx b/studio/frontend/src/features/settings/tabs/resources-tab.tsx index 7725aaa0ad..6348d2066d 100644 --- a/studio/frontend/src/features/settings/tabs/resources-tab.tsx +++ b/studio/frontend/src/features/settings/tabs/resources-tab.tsx @@ -456,97 +456,91 @@ export function ResourcesTab() { )} -
- {hasGpu ? ( - metrics.devices.map((device, index) => { - const ordinal = deviceOrdinal(device); - // Preserve null (unknown, e.g. Windows ROCm perf counter); coercing - // to 0 would render a fabricated 0 used / full free. - const total = device.memory_total_gb ?? null; - const used = device.vram_used_gb ?? null; - const free = - device.vram_free_gb ?? - (isFiniteNumber(total) && isFiniteNumber(used) - ? Math.max(0, total - used) - : null); - const percent = - device.vram_utilization_pct ?? - (isFiniteNumber(total) && total > 0 && isFiniteNumber(used) - ? (used / total) * 100 - : null); - const safePercent = clampPercent(percent); - const usedText = isFiniteNumber(used) - ? formatGiB(used) - : unknownLabel; - const freeText = isFiniteNumber(free) - ? formatGiB(free) - : unknownLabel; - const totalText = isFiniteNumber(total) - ? formatGiB(total) - : unknownLabel; - const percentText = isFiniteNumber(percent) - ? formatPercent(safePercent) - : unknownLabel; - return ( - // Two compact lines per device. The settings pane is about - // 664px at any window size, which cannot hold the name, three - // figures, meter and percentage on one row, so no breakpoint - // would ever fire. Splitting them keeps the name readable and - // the meter narrow instead of running the width of the pane. -
-
-
-
- {device.name ?? - t("settings.resources.gpu.unknownDevice")} -
-
- {ordinal === undefined - ? backendLabel - : `${t("settings.resources.gpu.deviceWithIndex", { - index: ordinal, - })}, ${backendLabel}`} -
-
-
+ {hasGpu ? ( + metrics.devices.map((device, index) => { + const ordinal = deviceOrdinal(device); + // Preserve null (unknown, e.g. Windows ROCm perf counter); coercing + // to 0 would render a fabricated 0 used / full free. + const total = device.memory_total_gb ?? null; + const used = device.vram_used_gb ?? null; + const free = + device.vram_free_gb ?? + (isFiniteNumber(total) && isFiniteNumber(used) + ? Math.max(0, total - used) + : null); + const percent = + device.vram_utilization_pct ?? + (isFiniteNumber(total) && total > 0 && isFiniteNumber(used) + ? (used / total) * 100 + : null); + const safePercent = clampPercent(percent); + const usedText = isFiniteNumber(used) + ? formatGiB(used) + : unknownLabel; + const freeText = isFiniteNumber(free) + ? formatGiB(free) + : unknownLabel; + const totalText = isFiniteNumber(total) + ? formatGiB(total) + : unknownLabel; + const percentText = isFiniteNumber(percent) + ? formatPercent(safePercent) + : unknownLabel; + return ( + // Name over backend on the left, figures and meter beside them. + // The meter is deliberately short: at full width it read as a + // rule across the pane rather than a reading for one device. +
+
+
+ {device.name ?? t("settings.resources.gpu.unknownDevice")} +
+
+ + {ordinal === undefined + ? backendLabel + : `${t("settings.resources.gpu.deviceWithIndex", { + index: ordinal, + })}, ${backendLabel}`} + + {percentText}{" "} {t("settings.resources.gpu.vramUtilization")} -
-
- {/* Wraps rather than overflows once the pane gets narrow. */} -
-
- - {t("settings.resources.gpu.used", { value: usedText })} - - - {t("settings.resources.gpu.free", { value: freeText })} - - - {t("settings.resources.gpu.total", { - value: totalText, - })} - -
- +
- ); - }) - ) : ( -
- {t("settings.resources.gpu.noGpu")} -
- )} -
+
+
+ + {t("settings.resources.gpu.used", { value: usedText })} + + + {t("settings.resources.gpu.free", { value: freeText })} + + + {t("settings.resources.gpu.total", { + value: totalText, + })} + +
+ +
+
+ ); + }) + ) : ( +
+ {t("settings.resources.gpu.noGpu")} +
+ )}