Files
miniSCP/ui/src/app/skins/7like/transfer-bar/transfer-bar.html
T
jgamboaandClaude 9f2a076e08 Scale stage 1: everything the UI sizes with is now rem
Groundwork for the continuous interface scale (a root font-size lever): every
size the UI derives from must be root-relative, or it freezes while the rest
grows. Gate for this commit: at the default 16px root the app renders
pixel-identical to before — every conversion is exact (11px = 0.6875rem …).

- The 8 panel-chrome tokens in styles.css: px -> rem, and the data-text
  compact/large tiers are DELETED — a continuous scale replaces discrete
  tiers. Same for --w7-fs (12px -> 0.75rem) and the win7 --radius (5px ->
  0.3125rem, still landing rounded-md exactly on --w7-el-bdr's 3px).
  --radius-sm/md subtrahends: px -> rem, or corners would sharpen as the UI
  grew.
- All 93 text-[11px]/text-[10px] arbitraries -> rem equivalents, plus the two
  inline padding:24px empty-state cells in the 7like file panel.
- 7like.css gains a scale bridge in skinfix: 7.css is 370 px values with zero
  rem, and --w7-font reaches only 15 rules' TYPOGRAPHY — under a root lever
  win7 text would grow inside boxes frozen at 23px/14px/15px. The bridge
  re-expresses 7.css's size vars and its hardcoded box metrics (buttons via
  .w7-btn only, inputs, table rows/headers, title-bar controls, menu items,
  tabs, the 10pt check glyph) in rem at identical scale-1 pixels. 1px
  hairlines and focus rects stay px deliberately — crisp at any scale, and
  the tr border exists precisely to stop selection shifting rows.
- Two skinfix traps found while writing it, one by reasoning and one by
  pixels: (a) NO blanket `.win7 button` restatement — skinfix outranks the
  skin-layer neutralizer that strips 7.css's 75x23 metrics off the ~84 icon
  buttons, so a blanket rule would re-inflate them all; (b) restating a base
  rule in skinfix also outranks 7.css's own VARIANTS of it by layer — the
  title-bar rule silently shrank the close button from 48px to 29px until the
  harness pixel diff caught it, and the active tab's padding-bottom needed
  the same treatment. Both variants are restated alongside their base rules.
- TS px constants that mirror rem CSS are the latent-bug half of this work:
  both context menus' flip/clamp math converts through a new @core/metrics
  remPx() helper reading the LIVE root font-size (the shadlike menu's
  MENU_W=224 diverged from its w-56 box the moment scale != 1; the 7like
  menu's [style.width.px] pinned the box at 200px while text grew — it now
  binds width in rem, so math and box cannot disagree). The editors'
  cachedCharWidth is now keyed on the computed font string, self-invalidating
  under any font change, and both || px fallbacks derive from the element's
  font size instead of assuming a 16px root.

Verified: tsc + build clean; modern and win7 live captures and the harness
all diff to zero against pre-change baselines in their opaque regions (the
harness to exactly zero end to end; modern's only delta is the native GTK
titlebar focus state; win7's is the translucent Aero corner over the
desktop).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-16 18:02:41 +02:00

60 lines
2.6 KiB
HTML

@if (transfers.expanded() && transfers.hasJobs()) {
<div class="flex items-center justify-between border-t border-border bg-chrome px-3 py-1 text-[0.6875rem] text-muted-foreground">
<span>
{{ i18n.t('transfer.summary', { active: transfers.activeJobs().length, finished: transfers.finishedJobs().length }) }}
</span>
<button
(click)="transfers.clearFinished()"
[disabled]="!transfers.finishedJobs().length"
class="flex items-center gap-1 rounded px-1.5 py-0.5 hover:bg-accent hover:text-foreground disabled:opacity-40 disabled:hover:bg-transparent"
>
<ng-icon name="mynaTrash" size="0.75rem" /> {{ i18n.t('transfer.clearFinished') }}
</button>
</div>
<div class="has-scrollbar max-h-40 overflow-y-auto border-t border-border bg-chrome">
@for (job of transfers.jobs(); track job.id) {
<div class="flex items-center gap-2 px-3 py-1.5 text-xs">
<ng-icon [name]="stateIcon(job)" size="0.95rem" [class]="stateClass(job)" />
<span class="w-40 shrink-0 truncate font-medium" [title]="job.srcPath">{{ job.name }}</span>
<div class="min-w-0 flex-1">
<div class="truncate text-[0.6875rem] text-muted-foreground">{{ progressLabel(job) }}</div>
@if (isActive(job)) {
<!-- role+aria are 7.css's hook for the Win7 progress bar
([role=progressbar] > div); under the modern skin they are
inert and the Tailwind classes below still draw the bar. -->
<div
role="progressbar"
aria-valuemin="0"
aria-valuemax="100"
[attr.aria-valuenow]="jobPercent(job)"
class="mt-0.5 h-1 overflow-hidden rounded-full bg-muted"
>
<div
class="h-full rounded-full bg-primary transition-[width] duration-100"
[style.width.%]="jobPercent(job)"
></div>
</div>
}
</div>
@if (isActive(job)) {
<button
(click)="transfers.cancel(job.id)"
[title]="i18n.t('transfer.cancel')"
class="shrink-0 rounded p-1 text-muted-foreground hover:bg-accent hover:text-destructive"
>
<ng-icon name="mynaX" size="0.9rem" />
</button>
} @else {
<button
(click)="transfers.dismiss(job.id)"
[title]="i18n.t('transfer.dismiss')"
class="shrink-0 rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground"
>
<ng-icon name="mynaX" size="0.9rem" />
</button>
}
</div>
}
</div>
}