From 7e5f4d87de2d884f3837e379fdf7a06a5e9ec47b Mon Sep 17 00:00:00 2001 From: Unsloth Date: Sat, 25 Jul 2026 04:17:05 -0700 Subject: [PATCH] Images: center the mode switch, flip the arrow with the orientation, app tooltips everywhere The Create/Train switch is centered on the page instead of trailing the model selector, with wider buttons. The flip control's arrows now rotate with the orientation and its label says which way the flip goes. Every native title tooltip on the page is now the app's tooltip, so they all get the rounded surface instead of the OS box. --- .../src/features/images/images-page.tsx | 183 +++++++++++------- .../images/train/dataset-labeling-grid.tsx | 36 ++-- .../images/train/dataset-showcase.tsx | 53 ++--- .../images/train/example-dataset-cards.tsx | 34 ++-- 4 files changed, 188 insertions(+), 118 deletions(-) diff --git a/studio/frontend/src/features/images/images-page.tsx b/studio/frontend/src/features/images/images-page.tsx index 523ca00bc2..0aebea49e2 100644 --- a/studio/frontend/src/features/images/images-page.tsx +++ b/studio/frontend/src/features/images/images-page.tsx @@ -52,7 +52,11 @@ import { Slider } from "@/components/ui/slider"; import { Spinner } from "@/components/ui/spinner"; import { Switch } from "@/components/ui/switch"; import { Textarea } from "@/components/ui/textarea"; -import { Tooltip, TooltipContent } from "@/components/ui/tooltip"; +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from "@/components/ui/tooltip"; import { InfoHint } from "@/components/ui/info-hint"; import { ModelSelector } from "@/features/model-picker/components/model-selector"; import { IMAGE_GEN_TASKS } from "@/features/model-picker/components/model-selector/pickers"; @@ -508,14 +512,18 @@ function ResolvedBadge({ }) { const resolved = status?.resolved?.[controlKey]; if (!resolved || resolved.source !== "auto") return null; - return ( - + const badge = ( + Auto: {formatResolvedValue(controlKey, resolved.value)} ); + if (!resolved.reason) return badge; + return ( + + {badge} + {resolved.reason} + + ); } // A compact labeled Select row for the Advanced Options panel. @@ -596,20 +604,24 @@ function ImageDropzone({ return (
Source - + + + + + Remove +
); } @@ -2214,16 +2226,20 @@ export function ImagesPage({ active = true }: { active?: boolean }) { wires lastLoad for it), so it keeps Reapply even before any user-initiated load; GGUF/single_file residents have no reload target and hide the button. */} {status?.loaded && (canReapply || status?.model_kind === "pipeline") && ( - + + + + + Reload the current model with these advanced options + )} ); @@ -2233,7 +2249,7 @@ export function ImagesPage({ active = true }: { active?: boolean }) { {/* ── Top: the model selector, kept at the chat tab's exact position so the shared element matches. The load progress shows in a chat-style toast, not here. ── */} -
+
setSelectorOpen(active && o)} /> - {/* Create | Train page-mode switch, next to the model selector (which stays - leftmost: its position is shared with Chat's). PillTabs is the app's - segmented control, so this matches the picker and Hub toggles. Icons match - the sidebar's New chat / Train rows. Height pinned to the row's 34px. */} +
+ {/* Create | Train page-mode switch, centered on the page rather than tied to the + selector's width (the selector stays leftmost: its position is shared with + Chat's). PillTabs is the app's segmented control, so this matches the picker + and Hub toggles. Icons match the sidebar's New chat / Train rows. */} +
setPageMode(v as "create" | "train")} fit={true} - // ml-5 sets it off from the selector rather than sitting against it. - className="ml-5 h-[34px] [&>button]:h-[34px] [&>button]:px-4" + className="pointer-events-auto h-[34px] [&>button]:h-[34px] [&>button]:px-7" tabs={[ { value: "create", @@ -2285,21 +2302,25 @@ export function ImagesPage({ active = true }: { active?: boolean }) { toggle, same icon in both states so it never moves). Highlighted when open. Only meaningful in Create mode (load-time tuning), so hidden while training. */} {pageMode === "create" && ( - + + + + + Advanced options + )}
@@ -2821,16 +2842,30 @@ export function ImagesPage({ active = true }: { active?: boolean }) { ))} - + + + + + + {portrait ? "Switch to landscape" : "Switch to portrait"} + +
@@ -2929,16 +2964,20 @@ export function ImagesPage({ active = true }: { active?: boolean }) { - + + + + + Delete + ) : selected ? ( diff --git a/studio/frontend/src/features/images/train/dataset-labeling-grid.tsx b/studio/frontend/src/features/images/train/dataset-labeling-grid.tsx index 07ca862c96..f3d262079f 100644 --- a/studio/frontend/src/features/images/train/dataset-labeling-grid.tsx +++ b/studio/frontend/src/features/images/train/dataset-labeling-grid.tsx @@ -9,6 +9,11 @@ import { HugeiconsIcon } from "@hugeicons/react"; import { Button } from "@/components/ui/button"; import { Spinner } from "@/components/ui/spinner"; import { Textarea } from "@/components/ui/textarea"; +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from "@/components/ui/tooltip"; import { cn } from "@/lib/utils"; import { toast } from "@/lib/toast"; @@ -114,15 +119,19 @@ function LabelTile({ )} - + + + + + Remove this image from the dataset +