fix(ui): a longer label fits its control — pill value truncates, headers get their room (E30 S5)
Found in the Hungarian UAT: a toolbar SelectTrigger's text value wrapped out of the pill in a narrow place (the playlists rail) — it now truncates in its own span; the Channels "Prioritás" and "Utolsó feltöltés" headers were clipped by their fixed columns — sized for the label, funnel and sort arrow; a sortable header is at least 24px wide (Hungarian "Ki" was a 12px target). PRE-EXISTING, any language: the messages unlock button and "Forgot passphrase" sat flush — one gapped row.
This commit is contained in:
@@ -168,15 +168,18 @@ export default function KeyGate({ meId, compact = false }: { meId: number; compa
|
||||
{err}
|
||||
</div>
|
||||
)}
|
||||
<Button variant="primary" size="md" onClick={submit} disabled={busy || !pass}>
|
||||
<Lock className="w-4 h-4" />
|
||||
{configured ? t("messages.unlock") : t("messages.setUp")}
|
||||
</Button>
|
||||
{configured && (
|
||||
<Button variant="link-muted" onClick={toReset} className="text-xs">
|
||||
{t("messages.forgotPass")}
|
||||
{/* One row with a gap: as two bare inline buttons the link sat flush against the primary. */}
|
||||
<div className="flex flex-wrap items-center gap-3">
|
||||
<Button variant="primary" size="md" onClick={submit} disabled={busy || !pass}>
|
||||
<Lock className="w-4 h-4" />
|
||||
{configured ? t("messages.unlock") : t("messages.setUp")}
|
||||
</Button>
|
||||
)}
|
||||
{configured && (
|
||||
<Button variant="link-muted" onClick={toReset} className="text-xs">
|
||||
{t("messages.forgotPass")}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
{!configured && !compact && <p className="text-xs text-muted">{t("messages.setupWarn")}</p>}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -93,7 +93,9 @@ export function buildChannelColumns(deps: ChannelColumnDeps): Column<ManagedChan
|
||||
key: "priority",
|
||||
header: t("channels.cols.priority"),
|
||||
align: "center",
|
||||
width: "5.5rem",
|
||||
// Sized to the longer language's label + the funnel + a sort arrow ("Prioritás ▼ ⧩"): fixed layout
|
||||
// clips a header that outgrows its column instead of widening it.
|
||||
width: "7.5rem",
|
||||
// Off on a tablet-wide table, with About and Length: the row's "…" menu sets the priority too.
|
||||
tabletHidden: true,
|
||||
sortable: true,
|
||||
@@ -155,7 +157,7 @@ export function buildChannelColumns(deps: ChannelColumnDeps): Column<ManagedChan
|
||||
key: "lastUpload",
|
||||
header: t("channels.cols.lastUpload"),
|
||||
nowrap: true,
|
||||
width: "6rem",
|
||||
width: "8rem", // "Utolsó feltöltés" + a sort arrow, as the priority column above
|
||||
sortable: true,
|
||||
sortValue: (c) => (c.last_video_at ? new Date(c.last_video_at).getTime() : 0),
|
||||
render: (c) => <RelativeTime at={c.last_video_at} empty="—" className="text-muted" />,
|
||||
|
||||
@@ -33,7 +33,7 @@ export const SelectTrigger = forwardRef<
|
||||
ref={ref}
|
||||
type="button"
|
||||
className={clsx(
|
||||
"glass-hover inline-flex shrink-0 items-center gap-1.5 border text-left text-sm transition touch-target",
|
||||
"glass-hover inline-flex max-w-full shrink-0 items-center gap-1.5 border text-left text-sm whitespace-nowrap transition touch-target",
|
||||
context === "toolbar"
|
||||
? "glass-card h-7 rounded-full px-3"
|
||||
: "h-8 w-full rounded-lg bg-transparent px-2.5",
|
||||
@@ -43,17 +43,23 @@ export const SelectTrigger = forwardRef<
|
||||
{...rest}
|
||||
>
|
||||
{icon}
|
||||
{label != null && <span className="text-muted">{label}:</span>}
|
||||
{label != null && <span className="shrink-0 text-muted">{label}:</span>}
|
||||
{/* The toolbar value is a row, whatever the caller puts in it: an <svg> is display:block under the
|
||||
preflight, and in a plain span it broke the value onto its own line (the saved-view chip,
|
||||
E28). The form value is text that truncates, which a flex box would not do. */}
|
||||
E28). The form value is text that truncates, which a flex box would not do — nor would a bare
|
||||
text node in the toolbar row, so a text value gets its own truncating span: in a narrow place
|
||||
(the playlists rail) a long value ("Rendezés: Egyéni sorrend") used to wrap out of the pill. */}
|
||||
<span
|
||||
className={clsx(
|
||||
"text-fg",
|
||||
context === "form" ? "flex-1 truncate" : "flex min-w-0 items-center gap-1.5",
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
{context === "toolbar" && typeof children === "string" ? (
|
||||
<span className="truncate">{children}</span>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</span>
|
||||
{trailing}
|
||||
<ChevronDown
|
||||
|
||||
@@ -229,10 +229,12 @@ export function ColumnHead<T>({
|
||||
{/* Only a sortable header is a control. A non-sortable one used to render a
|
||||
focusable no-op button, which put unlabeled dead stops in the tab order —
|
||||
two of them per playlist table, whose grip and actions headers are empty. */}
|
||||
{/* min-w-6 as well as min-h-6: a short header ("Ki", Hungarian "Who") was a 12px
|
||||
target beside its funnel, under the 24px floor. */}
|
||||
{col.sortable ? (
|
||||
<Pressable
|
||||
onClick={() => onToggleSort(col.key)}
|
||||
className="inline-flex min-h-6 items-center gap-1 hover:text-fg cursor-pointer touch-target"
|
||||
className="inline-flex min-h-6 min-w-6 items-center gap-1 hover:text-fg cursor-pointer touch-target"
|
||||
>
|
||||
{col.header}
|
||||
{isSorted &&
|
||||
|
||||
Reference in New Issue
Block a user