fix(player): the channel line wraps instead of squeezing the meta into a column

On a narrow card (a tablet, a zoomed window) the unwrapped row of name, meta and
actions left the meta a one-word column. The row now wraps: the meta keeps at
least 12rem, and the actions move down together.
This commit is contained in:
2026-10-08 02:25:58 +02:00
parent 49a9319f84
commit ca949d22de
+16 -13
View File
@@ -145,6 +145,9 @@ const metaSep = (
</span> </span>
); );
const META_OWN_LINE = "w-full [&>span:first-child>[data-meta-sep]]:hidden"; const META_OWN_LINE = "w-full [&>span:first-child>[data-meta-sep]]:hidden";
// Beside the channel name the meta takes what is left of the line, but never less than this: under it
// the line wraps and the meta, or the actions after it, move down instead of squeezing.
const META_MIN = "min-w-48 flex-1";
export default function PlayerModal({ export default function PlayerModal({
video, video,
@@ -961,10 +964,13 @@ export default function PlayerModal({
</Button> </Button>
</div> </div>
{/* Channel + meta on one line, with the watched toggle pushed to the right. {/* Channel + meta on one line, with the actions pushed to the right.
When navigated to a linked video we only have its author (from the player), When navigated to a linked video we only have its author (from the player),
so we show that as plain text and hide feed-video-specific bits. */} so we show that as plain text and hide feed-video-specific bits.
<div className={`flex items-center gap-3 mt-3 ${wide ? "flex-wrap" : ""}`}> It wraps: the meta never gets narrower than META_MIN, and the actions move down as one
group. Unwrapped, a narrow card (a tablet, a zoomed window) squeezed the meta into a
one-word column between the name and the buttons. */}
<div className="flex flex-wrap items-center gap-x-3 gap-y-2 mt-3">
{!navigated && ( {!navigated && (
<Avatar <Avatar
src={active.channel_thumbnail} src={active.channel_thumbnail}
@@ -1012,7 +1018,7 @@ export default function PlayerModal({
)} )}
{!navigated ? ( {!navigated ? (
<div <div
className={`flex flex-wrap items-center gap-x-2 gap-y-0.5 text-sm text-muted min-w-0 ${wide ? META_OWN_LINE : ""}`} className={`flex flex-wrap items-center gap-x-2 gap-y-0.5 text-sm text-muted ${wide ? META_OWN_LINE : META_MIN}`}
> >
{active.view_count != null && ( {active.view_count != null && (
<span> <span>
@@ -1043,7 +1049,7 @@ export default function PlayerModal({
) : ( ) : (
// Linked video's stats come from the (already-fetched) video detail. // Linked video's stats come from the (already-fetched) video detail.
<div <div
className={`flex flex-wrap items-center gap-x-2 gap-y-0.5 text-sm text-muted min-w-0 ${wide ? META_OWN_LINE : ""}`} className={`flex flex-wrap items-center gap-x-2 gap-y-0.5 text-sm text-muted ${wide ? META_OWN_LINE : META_MIN}`}
> >
{detail.data?.view_count != null && ( {detail.data?.view_count != null && (
<span> <span>
@@ -1076,28 +1082,25 @@ export default function PlayerModal({
own (which hides our chrome). Mirrors the F key (maximise, a CSS big view); from there own (which hides our chrome). Mirrors the F key (maximise, a CSS big view); from there
the docked bar offers OUR true fullscreen. */} the docked bar offers OUR true fullscreen. */}
{!navigated && ( {!navigated && (
// Narrow: the actions end the channel line. Wide: their own line in the panel.
<div className={`flex items-center gap-3 ${wide ? "flex-wrap" : "ml-auto"}`}>
<IconButton <IconButton
variant="outline" variant="outline"
size="md" size="md"
onClick={toggleFullscreen} onClick={toggleFullscreen}
label={t("player.fullscreen")} label={t("player.fullscreen")}
title={`${t("player.fullscreen")} · F`} title={`${t("player.fullscreen")} · F`}
// Narrow: the actions end the channel line. Wide: their own line in the panel.
className={wide ? undefined : "ml-auto"}
> >
<Maximize /> <Maximize />
</IconButton> </IconButton>
)} <AddToPlaylist videoId={active.id} variant="outline" size="md" />
{!navigated && <AddToPlaylist videoId={active.id} variant="outline" size="md" />}
{!navigated && (
<DownloadButton <DownloadButton
videoId={active.id} videoId={active.id}
title={active.title} title={active.title}
variant="outline" variant="outline"
size="md" size="md"
/> />
)} {onRemoveFromList && (
{!navigated && onRemoveFromList && (
<IconButton <IconButton
variant="outline-danger" variant="outline-danger"
size="md" size="md"
@@ -1110,7 +1113,6 @@ export default function PlayerModal({
<Trash2 /> <Trash2 />
</IconButton> </IconButton>
)} )}
{!navigated && (
<Button <Button
variant="outline" variant="outline"
size="sm" size="sm"
@@ -1121,6 +1123,7 @@ export default function PlayerModal({
> >
{watched ? t("player.watched") : t("player.markWatched")} {watched ? t("player.watched") : t("player.markWatched")}
</Button> </Button>
</div>
)} )}
</div> </div>
{wide && ( {wide && (