From 4eee45bf679257b10dde5eb73fa90ec2a96f71a0 Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Thu, 18 Jun 2026 14:33:39 +0300 Subject: [PATCH] Fix YouTube embed overlaps side nav in new design Closes #3066 --- app/features/vods/routes/vods.new.module.css | 28 ++++++----- app/features/vods/routes/vods.new.tsx | 50 +++++++++++++++++++- 2 files changed, 63 insertions(+), 15 deletions(-) diff --git a/app/features/vods/routes/vods.new.module.css b/app/features/vods/routes/vods.new.module.css index 7aa7d29b9..d41559c11 100644 --- a/app/features/vods/routes/vods.new.module.css +++ b/app/features/vods/routes/vods.new.module.css @@ -6,20 +6,22 @@ margin-block: var(--s-2); } -@media (min-width: 1425px) { - .embedContainer { - position: fixed; - left: max(24px, calc((100vw - 800px) / 2 - 320px - 48px)); - top: 120px; - width: 320px; - margin-block: 0; - } -} +/* When the form's left margin can fit the embed (measured in JS so it accounts + for the side nav being collapsed and the chat sidebar being open), float it + just left of the form. The rail is anchored to the form's own left edge, so + the side nav offset cancels out and it never overlaps the nav. Its width is + set inline by the same JS. The rail spans the full form height while the + embed sticks within it, so it stays in view while scrolling the long form. */ +.embedRail.floating { + position: absolute; + top: 0; + bottom: 0; + right: calc(100% + var(--s-6)); -@media (min-width: 1700px) { - .embedContainer { - left: max(24px, calc((100vw - 800px) / 2 - 400px - 48px)); - width: 400px; + & .embedContainer { + position: sticky; + top: calc(var(--layout-nav-height) + var(--s-4)); + margin-block: 0; } } diff --git a/app/features/vods/routes/vods.new.tsx b/app/features/vods/routes/vods.new.tsx index 4a6757f7a..1a87a48ec 100644 --- a/app/features/vods/routes/vods.new.tsx +++ b/app/features/vods/routes/vods.new.tsx @@ -1,3 +1,4 @@ +import clsx from "clsx"; import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { useLoaderData } from "react-router"; @@ -13,6 +14,7 @@ import { FormFieldWrapper } from "~/form/fields/FormFieldWrapper"; import type { WeaponPoolItem } from "~/form/fields/WeaponPoolFormField"; import type { FormRenderProps } from "~/form/SendouForm"; import { SendouForm, useFormFieldContext } from "~/form/SendouForm"; +import { useIsomorphicLayoutEffect } from "~/hooks/useIsomorphicLayoutEffect"; import { useRecentlyReportedWeapons } from "~/hooks/useRecentlyReportedWeapons"; import type { MainWeaponId, StageId } from "~/modules/in-game-lists/types"; import { useHasRole } from "~/modules/permissions/hooks"; @@ -127,6 +129,7 @@ function YouTubeEmbedWrapper({ onPlayerReady: (player: YT.Player) => void; }) { const { values } = useFormFieldContext(); + const floatWidth = useFloatingEmbedWidth(); const youtubeUrl = values.youtubeUrl as string | undefined; if (!youtubeUrl) return null; @@ -135,12 +138,55 @@ function YouTubeEmbedWrapper({ if (!videoId) return null; return ( -