Use the ui font-size tokens instead of raw px text utilities
text-[11px] and friends ignore the UI font size preference, which the repo's font-scale contract test enforces. Same rendered size at the default scale.
This commit is contained in:
parent
53af720a94
commit
5fd086326c
8 changed files with 46 additions and 46 deletions
|
|
@ -344,7 +344,7 @@ export function DiffusionTrainDialog({
|
|||
{uploading ? "Uploading..." : "Upload"}
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-[11px] text-muted-foreground">
|
||||
<p className="text-ui-11 text-muted-foreground">
|
||||
10-50 images work well. Optional captions: a .txt per image (same
|
||||
filename) or a metadata.jsonl; without them the trigger prompt below
|
||||
captions every image. You can upload more into the same name later.
|
||||
|
|
@ -352,7 +352,7 @@ export function DiffusionTrainDialog({
|
|||
</div>
|
||||
)}
|
||||
{selectedDataset && selectedDataset.caption_count === 0 && (
|
||||
<p className="text-[11px] text-muted-foreground">
|
||||
<p className="text-ui-11 text-muted-foreground">
|
||||
No caption files in this dataset - the trigger prompt below will be used
|
||||
as the caption for every image.
|
||||
</p>
|
||||
|
|
@ -480,7 +480,7 @@ export function DiffusionTrainDialog({
|
|||
: status.message}
|
||||
{status.loss != null && !completed && <> · loss {status.loss.toFixed(4)}</>}
|
||||
{status.lora_path && (
|
||||
<div className="mt-1 break-all text-[11px]">Saved: {status.lora_path}</div>
|
||||
<div className="mt-1 break-all text-ui-11">Saved: {status.lora_path}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -512,7 +512,7 @@ function ResolvedBadge({
|
|||
const resolved = status?.resolved?.[controlKey];
|
||||
if (!resolved || resolved.source !== "auto") return null;
|
||||
const badge = (
|
||||
<span className="shrink-0 rounded-sm bg-muted px-1 py-px text-[9px] font-medium uppercase tracking-wider text-muted-foreground">
|
||||
<span className="shrink-0 rounded-sm bg-muted px-1 py-px text-ui-9 font-medium uppercase tracking-wider text-muted-foreground">
|
||||
Auto: {formatResolvedValue(controlKey, resolved.value)}
|
||||
</span>
|
||||
);
|
||||
|
|
@ -567,7 +567,7 @@ function AdvancedSelect({
|
|||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
{desc && <p className="text-[11px] leading-snug text-muted-foreground/70">{desc}</p>}
|
||||
{desc && <p className="text-ui-11 leading-snug text-muted-foreground/70">{desc}</p>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -949,7 +949,7 @@ function RecipePopover({
|
|||
<PopoverContent align="end" side="top" className="w-80 p-0">
|
||||
<div className="border-b border-border/60 px-4 py-2.5">
|
||||
<p className="text-sm font-semibold">Generation settings</p>
|
||||
<p className="text-[11px] text-muted-foreground">{formatTimestamp(image.created_at)}</p>
|
||||
<p className="text-ui-11 text-muted-foreground">{formatTimestamp(image.created_at)}</p>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2 px-4 py-3 text-xs">
|
||||
<RecipeRow label="Prompt" value={image.prompt} wrap />
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ function LabelTile({
|
|||
type="button"
|
||||
onClick={remove}
|
||||
disabled={deleting}
|
||||
className="absolute right-1 top-1 rounded-md bg-background/80 px-1.5 py-0.5 text-[11px] text-muted-foreground opacity-0 transition-opacity hover:bg-background hover:text-destructive group-hover:opacity-100 focus:opacity-100"
|
||||
className="absolute right-1 top-1 rounded-md bg-background/80 px-1.5 py-0.5 text-ui-11 text-muted-foreground opacity-0 transition-opacity hover:bg-background hover:text-destructive group-hover:opacity-100 focus:opacity-100"
|
||||
>
|
||||
{deleting ? "..." : "Remove"}
|
||||
</button>
|
||||
|
|
@ -140,10 +140,10 @@ function LabelTile({
|
|||
rows={2}
|
||||
spellCheck={false}
|
||||
placeholder="Describe this image..."
|
||||
className="min-h-[3rem] resize-none text-[11px]"
|
||||
className="min-h-[3rem] resize-none text-ui-11"
|
||||
aria-label={`Caption for ${record.filename}`}
|
||||
/>
|
||||
<div className="flex items-center justify-between text-[10px] text-muted-foreground">
|
||||
<div className="flex items-center justify-between text-ui-10 text-muted-foreground">
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild={true}>
|
||||
<span className="truncate">{record.filename}</span>
|
||||
|
|
@ -214,7 +214,7 @@ export function DatasetLabelingGrid({
|
|||
);
|
||||
|
||||
if (error) {
|
||||
return <p className="text-[11px] text-destructive">{error}</p>;
|
||||
return <p className="text-ui-11 text-destructive">{error}</p>;
|
||||
}
|
||||
if (records === null) {
|
||||
return (
|
||||
|
|
@ -224,7 +224,7 @@ export function DatasetLabelingGrid({
|
|||
);
|
||||
}
|
||||
if (records.length === 0) {
|
||||
return <p className="text-[11px] text-muted-foreground">This dataset has no images yet.</p>;
|
||||
return <p className="text-ui-11 text-muted-foreground">This dataset has no images yet.</p>;
|
||||
}
|
||||
|
||||
const uncaptioned = records.filter((r) => !r.caption || r.caption.trim() === "").length;
|
||||
|
|
@ -236,7 +236,7 @@ export function DatasetLabelingGrid({
|
|||
|
||||
return (
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="flex items-center justify-between gap-2 text-[11px] text-muted-foreground">
|
||||
<div className="flex items-center justify-between gap-2 text-ui-11 text-muted-foreground">
|
||||
<span className="min-w-0 truncate">
|
||||
{total} image{total === 1 ? "" : "s"}
|
||||
{uncaptioned > 0 ? ` · ${uncaptioned} without a caption` : " · all captioned"}
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ export function DatasetShowcase({
|
|||
className="hover-scrollbar flex w-full items-center gap-1.5 overflow-x-auto rounded-lg border border-border bg-muted/20 p-1.5 text-left transition-colors hover:border-foreground/20"
|
||||
>
|
||||
{names === null ? (
|
||||
<div className="flex h-14 items-center gap-2 px-2 text-[11px] text-muted-foreground">
|
||||
<div className="flex h-14 items-center gap-2 px-2 text-ui-11 text-muted-foreground">
|
||||
<Spinner className="size-3.5" /> Loading preview...
|
||||
</div>
|
||||
) : (
|
||||
|
|
@ -123,7 +123,7 @@ export function DatasetShowcase({
|
|||
{remaining > 0 && (
|
||||
<div className="flex size-14 shrink-0 flex-col items-center justify-center rounded-md bg-muted text-muted-foreground">
|
||||
<span className="text-sm font-medium">+{remaining}</span>
|
||||
<span className="text-[9px]">more</span>
|
||||
<span className="text-ui-9">more</span>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ export function DiffusionCharts({
|
|||
showAvgLine={true}
|
||||
scale="linear"
|
||||
/>
|
||||
<p className="px-1 text-[11px] leading-snug text-muted-foreground">
|
||||
<p className="px-1 text-ui-11 leading-snug text-muted-foreground">
|
||||
Per-step loss is noisy by design: every step samples a random noise level. Watch
|
||||
the smoothed line for the trend, not the raw jitter.
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -910,7 +910,7 @@ export function DiffusionTrainPanel({
|
|||
<SelectItem value="linear">Linear decay</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<p className="text-[11px] leading-snug text-muted-foreground">
|
||||
<p className="text-ui-11 leading-snug text-muted-foreground">
|
||||
Constant is fine for most runs.
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -933,7 +933,7 @@ export function DiffusionTrainPanel({
|
|||
<SelectItem value="off">Off (faster steps)</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<p className="text-[11px] leading-snug text-muted-foreground">
|
||||
<p className="text-ui-11 leading-snug text-muted-foreground">
|
||||
Less VRAM, slightly slower steps.
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -964,7 +964,7 @@ export function DiffusionTrainPanel({
|
|||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<p className="text-[11px] leading-snug text-muted-foreground">
|
||||
<p className="text-ui-11 leading-snug text-muted-foreground">
|
||||
{familyUntrainable ? (
|
||||
// The reason itself (the backend's bf16-preflight text) already shows in
|
||||
// the family picker's vram_note line above.
|
||||
|
|
@ -995,7 +995,7 @@ export function DiffusionTrainPanel({
|
|||
<SelectItem value="no">fp32 (no mixed)</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<p className="text-[11px] leading-snug text-muted-foreground">
|
||||
<p className="text-ui-11 leading-snug text-muted-foreground">
|
||||
bf16 is right for modern GPUs.
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -1018,7 +1018,7 @@ export function DiffusionTrainPanel({
|
|||
<SelectItem value="off">Off</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<p className="text-[11px] leading-snug text-muted-foreground">
|
||||
<p className="text-ui-11 leading-snug text-muted-foreground">
|
||||
Slower first step, faster after.
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -1036,7 +1036,7 @@ export function DiffusionTrainPanel({
|
|||
<div className="hover-scrollbar flex min-h-0 flex-col gap-5 overflow-y-auto overflow-x-hidden pb-7 pl-0.5 pr-7">
|
||||
<div>
|
||||
<h2 className="text-base font-semibold">Train a LoRA</h2>
|
||||
<p className="mt-1 text-[11px] leading-snug text-muted-foreground">
|
||||
<p className="mt-1 text-ui-11 leading-snug text-muted-foreground">
|
||||
Teach a model a style or subject from your own images.
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -1057,7 +1057,7 @@ export function DiffusionTrainPanel({
|
|||
</SelectContent>
|
||||
</Select>
|
||||
{family?.vram_note && (
|
||||
<p className="text-[11px] leading-snug text-muted-foreground">{family.vram_note}</p>
|
||||
<p className="text-ui-11 leading-snug text-muted-foreground">{family.vram_note}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
|
@ -1127,7 +1127,7 @@ export function DiffusionTrainPanel({
|
|||
</SelectContent>
|
||||
</Select>
|
||||
{importingId && (
|
||||
<p className="text-[11px] text-muted-foreground">
|
||||
<p className="text-ui-11 text-muted-foreground">
|
||||
Importing {examples.find((e) => e.id === importingId)?.label ?? "example"}...
|
||||
</p>
|
||||
)}
|
||||
|
|
@ -1170,7 +1170,7 @@ export function DiffusionTrainPanel({
|
|||
{/* Count and Upload appear only once files are picked. */}
|
||||
{pickedFileCount > 0 && (
|
||||
<>
|
||||
<span className="min-w-0 flex-1 truncate text-[11px] text-muted-foreground">
|
||||
<span className="min-w-0 flex-1 truncate text-ui-11 text-muted-foreground">
|
||||
{pickedFileCount} file{pickedFileCount === 1 ? "" : "s"} selected
|
||||
</span>
|
||||
<Button
|
||||
|
|
@ -1186,7 +1186,7 @@ export function DiffusionTrainPanel({
|
|||
</>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-[11px] leading-snug text-muted-foreground">
|
||||
<p className="text-ui-11 leading-snug text-muted-foreground">
|
||||
10-50 images is plenty. Captions are optional.
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -1214,7 +1214,7 @@ export function DiffusionTrainPanel({
|
|||
/>
|
||||
)}
|
||||
{selectedDataset.caption_count === 0 && !gridOpen && (
|
||||
<p className="text-[11px] leading-snug text-muted-foreground">
|
||||
<p className="text-ui-11 leading-snug text-muted-foreground">
|
||||
No captions yet, so the trigger prompt describes every image.
|
||||
</p>
|
||||
)}
|
||||
|
|
@ -1232,7 +1232,7 @@ export function DiffusionTrainPanel({
|
|||
{/* Trigger + adapter name (trigger first: it describes the dataset, the name
|
||||
just labels the output) */}
|
||||
{fullyCaptioned ? (
|
||||
<p className="text-[11px] leading-snug text-muted-foreground">
|
||||
<p className="text-ui-11 leading-snug text-muted-foreground">
|
||||
All {selectedDataset?.image_count} images have captions, so no trigger prompt
|
||||
is needed.
|
||||
</p>
|
||||
|
|
@ -1245,7 +1245,7 @@ export function DiffusionTrainPanel({
|
|||
onChange={(e) => setInstancePrompt(e.target.value)}
|
||||
className="h-8 text-xs"
|
||||
/>
|
||||
<p className="text-[11px] leading-snug text-muted-foreground">
|
||||
<p className="text-ui-11 leading-snug text-muted-foreground">
|
||||
The words you will use later to get this style back.
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -1259,7 +1259,7 @@ export function DiffusionTrainPanel({
|
|||
onChange={(e) => setOutputDir(e.target.value)}
|
||||
className="h-8 text-xs"
|
||||
/>
|
||||
<p className="text-[11px] leading-snug text-muted-foreground">
|
||||
<p className="text-ui-11 leading-snug text-muted-foreground">
|
||||
Its name in the Create tab's picker.
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -1323,7 +1323,7 @@ export function DiffusionTrainPanel({
|
|||
}
|
||||
/>
|
||||
</div>
|
||||
<p className="text-[11px] text-muted-foreground">
|
||||
<p className="text-ui-11 text-muted-foreground">
|
||||
{viewRun.family ? `${viewRun.family} - ` : ""}
|
||||
{viewRun.base_model || ""}
|
||||
{viewRun.ended_at
|
||||
|
|
@ -1367,7 +1367,7 @@ export function DiffusionTrainPanel({
|
|||
</span>
|
||||
</div>
|
||||
{trainingSettings}
|
||||
<p className="text-[11px] leading-snug text-muted-foreground">
|
||||
<p className="text-ui-11 leading-snug text-muted-foreground">
|
||||
Progress and charts take over here once training starts.
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -1394,14 +1394,14 @@ export function DiffusionTrainPanel({
|
|||
</span>
|
||||
<span className="flex shrink-0 items-center gap-2">
|
||||
{r.saved && (
|
||||
<span className="rounded-full bg-primary/15 px-2 py-0.5 text-[10px] text-primary">
|
||||
<span className="rounded-full bg-primary/15 px-2 py-0.5 text-ui-10 text-primary">
|
||||
adapter saved
|
||||
</span>
|
||||
)}
|
||||
<span className="text-[10px] uppercase tracking-wide text-muted-foreground">
|
||||
<span className="text-ui-10 uppercase tracking-wide text-muted-foreground">
|
||||
{r.status}
|
||||
</span>
|
||||
<span className="text-[10px] text-muted-foreground">
|
||||
<span className="text-ui-10 text-muted-foreground">
|
||||
{r.ended_at ? new Date(r.ended_at * 1000).toLocaleString() : ""}
|
||||
</span>
|
||||
</span>
|
||||
|
|
@ -1457,7 +1457,7 @@ export function DiffusionTrainPanel({
|
|||
/>
|
||||
</div>
|
||||
{status?.message && (
|
||||
<p className="text-[11px] text-muted-foreground">{status.message}</p>
|
||||
<p className="text-ui-11 text-muted-foreground">{status.message}</p>
|
||||
)}
|
||||
{running && (
|
||||
<Button
|
||||
|
|
@ -1493,7 +1493,7 @@ export function DiffusionTrainPanel({
|
|||
<span className="text-sm font-semibold">
|
||||
{completed ? "Adapter ready" : "Partial adapter saved"}
|
||||
</span>
|
||||
<p className="text-[11px] text-muted-foreground">
|
||||
<p className="text-ui-11 text-muted-foreground">
|
||||
{completed
|
||||
? "Trained"
|
||||
: "Stopped early; the adapter as of the last finished step was saved"}
|
||||
|
|
@ -1556,7 +1556,7 @@ export function DiffusionTrainPanel({
|
|||
function Stat({ label, value }: { label: string; value: string }) {
|
||||
return (
|
||||
<div className={cn("rounded-lg border border-border/60 bg-muted/20 px-2.5 py-1.5")}>
|
||||
<div className="text-[10px] uppercase tracking-wide text-muted-foreground">{label}</div>
|
||||
<div className="text-ui-10 uppercase tracking-wide text-muted-foreground">{label}</div>
|
||||
<div className="text-sm font-medium tabular-nums">{value}</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ export function ExampleDatasetCards({
|
|||
|
||||
return (
|
||||
<div className="grid gap-2">
|
||||
<span className="text-[11px] font-medium text-muted-foreground">
|
||||
<span className="text-ui-11 font-medium text-muted-foreground">
|
||||
Or start from an example dataset
|
||||
</span>
|
||||
<div className="grid gap-2">
|
||||
|
|
@ -124,14 +124,14 @@ export function ExampleDatasetCards({
|
|||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild={true}>
|
||||
<span className="max-w-[110px] shrink truncate rounded-full bg-secondary px-2 py-0.5 text-[10px] font-normal text-secondary-foreground">
|
||||
<span className="max-w-[110px] shrink truncate rounded-full bg-secondary px-2 py-0.5 text-ui-10 font-normal text-secondary-foreground">
|
||||
{ex.license}
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{ex.license}</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<p className="line-clamp-2 text-[11px] leading-snug text-muted-foreground">
|
||||
<p className="line-clamp-2 text-ui-11 leading-snug text-muted-foreground">
|
||||
{ex.description}
|
||||
</p>
|
||||
{/* The card's action, so: bottom right, on the thumbnail row. */}
|
||||
|
|
|
|||
|
|
@ -344,7 +344,7 @@ function ResolvedBadge({
|
|||
const resolved = status?.resolved?.[controlKey];
|
||||
if (!resolved || resolved.source !== "auto") return null;
|
||||
const badge = (
|
||||
<span className="shrink-0 rounded-sm bg-muted px-1 py-px text-[9px] font-medium uppercase tracking-wider text-muted-foreground">
|
||||
<span className="shrink-0 rounded-sm bg-muted px-1 py-px text-ui-9 font-medium uppercase tracking-wider text-muted-foreground">
|
||||
Auto: {formatResolvedValue(resolved.value)}
|
||||
</span>
|
||||
);
|
||||
|
|
@ -435,7 +435,7 @@ function RecipePopover({
|
|||
<PopoverContent align="end" side="top" className="w-80 p-0">
|
||||
<div className="border-b border-border/60 px-4 py-2.5">
|
||||
<p className="text-sm font-semibold">Generation settings</p>
|
||||
<p className="text-[11px] text-muted-foreground">{formatTimestamp(video.created_at)}</p>
|
||||
<p className="text-ui-11 text-muted-foreground">{formatTimestamp(video.created_at)}</p>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2 px-4 py-3 text-xs">
|
||||
<RecipeRow label="Prompt" value={video.prompt} wrap />
|
||||
|
|
@ -1401,7 +1401,7 @@ export function VideoPage({ active = true }: { active?: boolean }) {
|
|||
{/* Loaded-model status line: family / kind / offload / speed, like the images page
|
||||
surfaces on load. Hidden until a model is resident. */}
|
||||
{status?.loaded && (
|
||||
<div className="hidden items-center gap-3 text-[11px] md:flex">
|
||||
<div className="hidden items-center gap-3 text-ui-11 md:flex">
|
||||
{status.family && <StatusChip label="Family" value={status.family} />}
|
||||
{status.model_kind && <StatusChip label="Kind" value={status.model_kind} />}
|
||||
{status.offload_policy && (
|
||||
|
|
@ -1584,7 +1584,7 @@ export function VideoPage({ active = true }: { active?: boolean }) {
|
|||
className="max-h-full max-w-full rounded-xl object-contain shadow-sm"
|
||||
/>
|
||||
{selected.has_audio && (
|
||||
<div className="absolute left-4 top-4 flex items-center gap-1 rounded-lg bg-background/80 px-2 py-1 text-[11px] font-medium shadow-lg ring-1 ring-border backdrop-blur">
|
||||
<div className="absolute left-4 top-4 flex items-center gap-1 rounded-lg bg-background/80 px-2 py-1 text-ui-11 font-medium shadow-lg ring-1 ring-border backdrop-blur">
|
||||
<HugeiconsIcon icon={VolumeHighIcon} className="size-3.5" />
|
||||
Audio
|
||||
</div>
|
||||
|
|
@ -1717,7 +1717,7 @@ export function VideoPage({ active = true }: { active?: boolean }) {
|
|||
{/* A terse caption strip so cards read at a glance. Left/bottom
|
||||
padding clears the rounded-lg corner and the selection border
|
||||
so the leading "5.0s" is never clipped by the curve. */}
|
||||
<span className="relative z-10 truncate bg-gradient-to-t from-black/70 to-transparent px-2 pb-1 pt-2 text-left text-[9px] font-medium leading-none text-white">
|
||||
<span className="relative z-10 truncate bg-gradient-to-t from-black/70 to-transparent px-2 pb-1 pt-2 text-left text-ui-9 font-medium leading-none text-white">
|
||||
{clipMeta(video)}
|
||||
</span>
|
||||
{/* Selection marker on a non-focusable overlay. */}
|
||||
|
|
@ -1750,7 +1750,7 @@ export function VideoPage({ active = true }: { active?: boolean }) {
|
|||
className="flex h-16 w-16 shrink-0 flex-col items-center justify-center gap-1 rounded-[10px] text-muted-foreground ring-1 ring-border transition-colors hover:text-destructive hover:ring-destructive/40"
|
||||
>
|
||||
<HugeiconsIcon icon={Delete02Icon} className="size-4" />
|
||||
<span className="text-[9px] font-medium">Clear all</span>
|
||||
<span className="text-ui-9 font-medium">Clear all</span>
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Clear all videos</TooltipContent>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue