fix(stories): size the video player box to the real aspect ratio
The player box was full-bleed (w-full h-full) with object-fit: contain handling the letterboxing internally — visually correct but the box itself still spanned the whole screen, so the black letterbox area read as part of the player rather than just backdrop. Sizes the box itself to the story's aspectRatio (defaulting to 9:16 before Mux reports the real value), centered via flex — same visual result, but now only the actual content area is the "box".
This commit is contained in:
1 parent
8186c36b9a
commit
07c0f82293
1 file changed
+51
-36
@@ -224,43 +224,58 @@ export function StoryViewer({
|
||||
normal feed videos) — object-contain here matters even more:
|
||||
no fixed aspect-video box like VideoCard uses. */}
|
||||
{isVideo ? (
|
||||
<div className="relative w-full h-full">
|
||||
{videoStatus === "READY" && videoPlaybackId ? (
|
||||
<MuxPlayer
|
||||
playbackId={videoPlaybackId}
|
||||
streamType="on-demand"
|
||||
autoPlay
|
||||
muted={isMuted}
|
||||
style={{ width: "100%", height: "100%", objectFit: "contain" }}
|
||||
onTimeUpdate={handleVideoTimeUpdate}
|
||||
onEnded={handleVideoEnded}
|
||||
// The player BOX itself is sized to the video's real aspect
|
||||
// ratio (default 9:16 — most story videos are phone-shot
|
||||
// portrait — until Mux reports the actual value), not just the
|
||||
// content inside a full-bleed box. object-fit: contain on a
|
||||
// full-screen box still leaves a full-screen click/visual
|
||||
// target with the letterboxing baked into the box; sizing the
|
||||
// box itself means the black is purely the backdrop showing
|
||||
// through, not part of the box.
|
||||
<div className="relative w-full h-full flex items-center justify-center">
|
||||
<div
|
||||
className="relative h-full w-auto max-w-full"
|
||||
style={{
|
||||
aspectRatio: (currentStory.aspectRatio ?? "9:16").replace(":", " / "),
|
||||
}}
|
||||
>
|
||||
{videoStatus === "READY" && videoPlaybackId ? (
|
||||
<MuxPlayer
|
||||
playbackId={videoPlaybackId}
|
||||
streamType="on-demand"
|
||||
autoPlay
|
||||
muted={isMuted}
|
||||
style={{ width: "100%", height: "100%" }}
|
||||
onTimeUpdate={handleVideoTimeUpdate}
|
||||
onEnded={handleVideoEnded}
|
||||
/>
|
||||
) : videoStatus === "ERROR" ? (
|
||||
<div className="flex h-full w-full items-center justify-center text-white/70 text-sm">
|
||||
{t("videoError")}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
<Loader2 className="h-8 w-8 text-white animate-spin" />
|
||||
</div>
|
||||
)}
|
||||
{videoStatus === "READY" && (
|
||||
<button
|
||||
className="absolute bottom-3 right-3 flex h-10 w-10 items-center justify-center rounded-full bg-black/40 text-white hover:bg-black/60"
|
||||
onClick={() => setIsMuted((m) => !m)}
|
||||
aria-label={isMuted ? t("unmute") : t("mute")}
|
||||
>
|
||||
{isMuted ? (
|
||||
<VolumeX className="h-4 w-4" aria-hidden="true" />
|
||||
) : (
|
||||
<Volume2 className="h-4 w-4" aria-hidden="true" />
|
||||
)}
|
||||
</button>
|
||||
)}
|
||||
<AiDisclosureBadge
|
||||
value={currentStory.aiDisclosure}
|
||||
className="top-auto left-auto bottom-3 right-16 h-10"
|
||||
/>
|
||||
) : videoStatus === "ERROR" ? (
|
||||
<div className="flex h-full w-full items-center justify-center text-white/70 text-sm">
|
||||
{t("videoError")}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
<Loader2 className="h-8 w-8 text-white animate-spin" />
|
||||
</div>
|
||||
)}
|
||||
{videoStatus === "READY" && (
|
||||
<button
|
||||
className="absolute bottom-3 right-3 flex h-10 w-10 items-center justify-center rounded-full bg-black/40 text-white hover:bg-black/60"
|
||||
onClick={() => setIsMuted((m) => !m)}
|
||||
aria-label={isMuted ? t("unmute") : t("mute")}
|
||||
>
|
||||
{isMuted ? (
|
||||
<VolumeX className="h-4 w-4" aria-hidden="true" />
|
||||
) : (
|
||||
<Volume2 className="h-4 w-4" aria-hidden="true" />
|
||||
)}
|
||||
</button>
|
||||
)}
|
||||
<AiDisclosureBadge
|
||||
value={currentStory.aiDisclosure}
|
||||
className="top-auto left-auto bottom-3 right-16 h-10"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
mediaUrl && (
|
||||
|
||||
Reference in new issue
Block a user