fix(feed): keep the row's columns growing with the text-size setting
My last commit made ROW_COL the literal source of the widths — and froze them, because inline pixels can't follow the root font that Settings' text slider drives (0.9-1.3). Measured at 130%: the channel box stuck at 128px while its text wanted 152 and the meta cell, being a rem grid, grew to 156 — one row in two unit systems. The classes come back and ROW_COL documents them, saying plainly that the two are matched by hand and why they have to be. Chasing a comment's literal truth cost a property I'd already verified.
This commit is contained in:
@@ -322,24 +322,28 @@ function Thumb({
|
||||
);
|
||||
}
|
||||
|
||||
// The one-line row's column widths, in ONE place: the boxes below take these directly (as inline
|
||||
// widths — Tailwind can't accept a runtime value), and so do the drop-out thresholds. Two
|
||||
// hand-written sets would drift, and the symptom would be silent: a column appearing just before
|
||||
// it actually fits. Each is measured against the worst case in the LIBRARY and in BOTH languages —
|
||||
// see the row's own comment for where each number comes from.
|
||||
// The one-line row's column widths at the DEFAULT text size, mirroring the Tailwind classes the
|
||||
// boxes actually use. They have to be mirrored by hand — Tailwind can't take a runtime value, and
|
||||
// the classes have to stay, because they're rem: Settings' text-size slider drives the root font
|
||||
// (`html { font-size: calc(16px * var(--font-scale)) }`, 0.9–1.3), so the boxes must grow with
|
||||
// their contents. Inline pixels froze them and a channel name at 130% wanted 152px in a 128px box.
|
||||
// Keep this table and the classes in step; each number is measured against the worst case in the
|
||||
// LIBRARY and in BOTH languages — see the row's own comment for where each comes from.
|
||||
const ROW_COL = {
|
||||
actions: 192, // six buttons at 28 + five 4px gaps = 188
|
||||
channel: 128,
|
||||
meta: 104, // RowMetaCells' own grid: 4rem + 1rem + 1rem + two 4px gaps
|
||||
views: 64,
|
||||
published: 192,
|
||||
actions: 192, // w-48 — six buttons at 28 + five 4px gaps = 188
|
||||
channel: 128, // w-32
|
||||
meta: 104, // RowMetaCells' own grid: 4rem + 1rem + 1rem + two 4px gaps
|
||||
views: 64, // w-16
|
||||
published: 192, // w-48
|
||||
} as const;
|
||||
const ROW_GAP = 12; // gap-3
|
||||
const ROW_PAD = 26; // px-3 both sides, plus a rounding allowance
|
||||
const ROW_TITLE_MIN = 120; // not a column: the floor below which a title isn't worth showing
|
||||
|
||||
// What the row must measure before each column earns its place — cumulative, so each appears only
|
||||
// once everything to its left AND a readable title already fit.
|
||||
// once everything to its left AND a readable title already fit. Calibrated at the default text
|
||||
// size; at 130% the columns grow ~30% while these don't, so they read slightly eager — the title
|
||||
// gets tighter there, but it can't vanish, since the last column standing down frees ~200px.
|
||||
const ROW_BASE = ROW_PAD + ROW_COL.actions + ROW_GAP + ROW_TITLE_MIN;
|
||||
const ROW_FITS = {
|
||||
channel: ROW_BASE + ROW_GAP + ROW_COL.channel,
|
||||
@@ -496,9 +500,7 @@ function VideoCard({
|
||||
<div className={clsx(rowShell, "flex items-center gap-3 px-3 py-2", watched && "opacity-55")}>
|
||||
{/* Actions lead: this is where the eye already is (the title is the thing you read), so
|
||||
they're the shortest pointer trip from it. */}
|
||||
<div className="shrink-0" style={{ width: ROW_COL.actions }}>
|
||||
{actions}
|
||||
</div>
|
||||
<div className="shrink-0 w-48">{actions}</div>
|
||||
{/* Everything else is shrink-0, so the title is the only thing that can give — which means
|
||||
once the fixed columns outgrow the row, it gives ALL of it and vanishes. Columns drop
|
||||
from the right as the row narrows, least important first: a title with no date beats a
|
||||
@@ -506,30 +508,18 @@ function VideoCard({
|
||||
filter panel are doing. Until the first measure lands (width 0) show everything: the
|
||||
row is off-screen for that frame anyway, and guessing narrow would flash. */}
|
||||
<div className="min-w-0 flex-1">{title}</div>
|
||||
{fits(ROW_FITS.channel) && (
|
||||
<div className="shrink-0" style={{ width: ROW_COL.channel }}>
|
||||
{channelButton}
|
||||
</div>
|
||||
)}
|
||||
{fits(ROW_FITS.channel) && <div className="shrink-0 w-32">{channelButton}</div>}
|
||||
{fits(ROW_FITS.meta) && <RowMetaCells video={video} />}
|
||||
{/* Right-aligned like the duration: it's a number, so the digits share an edge. 64px
|
||||
holds the widest bare form ("101.7K" at 48) in either language — dropping the word
|
||||
took this from 144 and handed the difference to the title. */}
|
||||
{fits(ROW_FITS.views) && (
|
||||
<div
|
||||
className="shrink-0 text-sm text-muted text-right tabular-nums truncate"
|
||||
style={{ width: ROW_COL.views }}
|
||||
>
|
||||
<div className="shrink-0 w-16 text-sm text-muted text-right tabular-nums truncate">
|
||||
{viewsCell(false)}
|
||||
</div>
|
||||
)}
|
||||
{fits(ROW_FITS.published) && (
|
||||
<div
|
||||
className="shrink-0 text-sm text-muted truncate"
|
||||
style={{ width: ROW_COL.published }}
|
||||
>
|
||||
{published}
|
||||
</div>
|
||||
<div className="shrink-0 w-48 text-sm text-muted truncate">{published}</div>
|
||||
)}
|
||||
{/* Thumb draws this over the image; with no image it goes on the row itself. */}
|
||||
{pct > 0 && (
|
||||
|
||||
Reference in New Issue
Block a user