From 2f1c971c1e355fe596f220b9dda06972659dbacb Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Sun, 27 Sep 2026 19:42:18 +0300 Subject: [PATCH] ViewTransition fixes --- app/features/sendouq/components/GroupCard.tsx | 8 ++++--- .../settings/routes/settings.global.css | 20 ----------------- app/features/settings/routes/settings.tsx | 1 - app/features/settings/routes/wave.svg | 8 ------- .../components/LFGGroupCard.tsx | 8 ++++--- app/utils/view-transition.ts | 22 +++++++++++++------ 6 files changed, 25 insertions(+), 42 deletions(-) delete mode 100644 app/features/settings/routes/settings.global.css delete mode 100644 app/features/settings/routes/wave.svg diff --git a/app/features/sendouq/components/GroupCard.tsx b/app/features/sendouq/components/GroupCard.tsx index 1b5e657d0..987b86cda 100644 --- a/app/features/sendouq/components/GroupCard.tsx +++ b/app/features/sendouq/components/GroupCard.tsx @@ -33,7 +33,7 @@ import { inGameNameWithoutDiscriminator } from "~/utils/strings"; import { SENDOUQ_LOOKING_PAGE, TIERS_PAGE, tierImageUrl } from "~/utils/urls"; import { finishUpdateIfUnmoved, - usePageViewTransitionClass, + usePageViewTransitionClasses, } from "~/utils/view-transition"; import type { SQGroup, @@ -306,12 +306,14 @@ function GroupCardContainer({ isOwnGroup: boolean; children: React.ReactNode; }) { - const updateClass = usePageViewTransitionClass("card-update"); + const transitionClasses = usePageViewTransitionClasses({ + update: "card-update", + }); if (isOwnGroup) return <>{children}; return ( - + {children} ); diff --git a/app/features/settings/routes/settings.global.css b/app/features/settings/routes/settings.global.css deleted file mode 100644 index 43c3c8510..000000000 --- a/app/features/settings/routes/settings.global.css +++ /dev/null @@ -1,20 +0,0 @@ -::view-transition-old(root), -.dark::view-transition-old(root) { - animation: none; - animation-fill-mode: both; - z-index: -1; -} - -::view-transition-new(root) { - mask: url("./wave.svg") no-repeat; - mask-position: 50% 200%; - mask-size: max(100vw, 200vh); - animation: sweep 1.5s; - animation-fill-mode: both; -} - -@keyframes sweep { - to { - mask-position: 50% 0%; - } -} diff --git a/app/features/settings/routes/settings.tsx b/app/features/settings/routes/settings.tsx index 04f6539d2..4c4ad3acf 100644 --- a/app/features/settings/routes/settings.tsx +++ b/app/features/settings/routes/settings.tsx @@ -31,7 +31,6 @@ import { loader } from "../loaders/settings.server"; import type { SettingsTabSlug } from "../settings-constants"; import { settingsSearchParams } from "../settings-search-params"; import { defaultTab, resolveActiveTab } from "../settings-utils"; -import "./settings.global.css"; export { action, loader }; diff --git a/app/features/settings/routes/wave.svg b/app/features/settings/routes/wave.svg deleted file mode 100644 index 10b93f8b4..000000000 --- a/app/features/settings/routes/wave.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/app/features/tournament-lfg/components/LFGGroupCard.tsx b/app/features/tournament-lfg/components/LFGGroupCard.tsx index fce123d74..53ca87caa 100644 --- a/app/features/tournament-lfg/components/LFGGroupCard.tsx +++ b/app/features/tournament-lfg/components/LFGGroupCard.tsx @@ -26,7 +26,7 @@ import type { MainWeaponId } from "~/modules/in-game-lists/types"; import { navIconUrl } from "~/utils/urls"; import { finishUpdateIfUnmoved, - usePageViewTransitionClass, + usePageViewTransitionClasses, } from "~/utils/view-transition"; import { lookingSchema, @@ -185,12 +185,14 @@ function LFGGroupCardContainer({ isOwnGroup: boolean; children: React.ReactNode; }) { - const updateClass = usePageViewTransitionClass("card-update"); + const transitionClasses = usePageViewTransitionClasses({ + update: "card-update", + }); if (isOwnGroup) return <>{children}; return ( - + {children} ); diff --git a/app/utils/view-transition.ts b/app/utils/view-transition.ts index b593462a1..8bcaae852 100644 --- a/app/utils/view-transition.ts +++ b/app/utils/view-transition.ts @@ -1,4 +1,4 @@ -import type { ViewTransitionInstance } from "react"; +import type { ViewTransitionInstance, ViewTransitionProps } from "react"; import * as React from "react"; interface PseudoElement { @@ -14,6 +14,12 @@ type PseudoElements = Record< const MEASURED_PROPERTIES = ["transform", "width", "height"] as const; const NUMBER_PATTERN = /-?\d*\.?\d+/g; const HOVER_CURSOR_PROPERTY = "--hover-cursor"; +const MODAL_OPEN_CLASSES: ViewTransitionClasses = { default: "none" }; + +type ViewTransitionClasses = Pick< + ViewTransitionProps, + "default" | "enter" | "exit" | "update" | "share" +>; /** How many modal dialogs are open, provided by the root. */ export const OpenModalsContext = React.createContext<{ @@ -113,7 +119,7 @@ export function useHoverCursorForViewTransitions() { }, []); } -/** Counts the calling dialog as an open modal while `isOpen`, see `usePageViewTransitionClass`. */ +/** Counts the calling dialog as an open modal while `isOpen`, see `usePageViewTransitionClasses`. */ export function useReportModalOpen(isOpen: boolean) { const { setCount } = React.useContext(OpenModalsContext); @@ -125,10 +131,12 @@ export function useReportModalOpen(isOpen: boolean) { } /** - * The `` class for an element of the page: `"none"` while a modal dialog is open. - * Snapshots paint above the dialog's backdrop, so a transition under it would show the page - * unblurred for a few frames, and there is nothing worth animating under a modal anyway. + * The `` classes for an element of the page, every trigger `"none"` while a modal + * dialog is open. Snapshots paint above the dialog's backdrop, so a transition under it would show + * the page unblurred for a few frames, and there is nothing worth animating under a modal anyway. */ -export function usePageViewTransitionClass(className: string) { - return React.useContext(OpenModalsContext).count > 0 ? "none" : className; +export function usePageViewTransitionClasses(classes: ViewTransitionClasses) { + return React.useContext(OpenModalsContext).count > 0 + ? MODAL_OPEN_CLASSES + : classes; }