diff --git a/agenta-web/src/components/NoMobilePageWrapper/NoMobilePageWrapper.tsx b/agenta-web/src/components/NoMobilePageWrapper/NoMobilePageWrapper.tsx new file mode 100644 index 0000000000..2e39bfcba1 --- /dev/null +++ b/agenta-web/src/components/NoMobilePageWrapper/NoMobilePageWrapper.tsx @@ -0,0 +1,72 @@ +import {type PropsWithChildren, useState, useCallback} from "react" +import {Typography, Button, theme} from "antd" +import clsx from "clsx" +import useResizeObserver from "@/hooks/useResizeObserver" +import {createUseStyles} from "react-jss" +import {JSSTheme} from "@/lib/Types" +import {Transition} from "@headlessui/react" +import {useRouter} from "next/router" +import {MOBILE_UNOPTIMIZED_APP_ROUTES} from "./assets/constants" + +const useStyles = createUseStyles((theme: JSSTheme) => ({ + overlay: { + background: `${theme.colorBgContainer}`, + }, +})) + +const {useToken} = theme + +const NoMobilePageWrapper: React.FC = ({children}) => { + const [dismissed, setDismissed] = useState(false) + const [shouldDisplay, setShouldDisplay] = useState(false) + const {overlay} = useStyles() + const {pathname} = useRouter() + const {token} = useToken() + + const observerCallback = useCallback( + (bounds: DOMRectReadOnly) => { + setShouldDisplay(() => { + if (dismissed) return false // keep hidden if already dismissed by the user + if (!MOBILE_UNOPTIMIZED_APP_ROUTES.some((route) => pathname.startsWith(route))) + return false + + return bounds.width < token.screenMD + }) + }, + [dismissed, pathname, token.screenMD], + ) + + useResizeObserver(observerCallback, typeof window !== "undefined" ? document.body : undefined) + + const handleDismiss = () => { + setDismissed(true) + } + + return ( + + + Agenta works better in larger laptop or desktop screens. + + + + ) +} + +export default NoMobilePageWrapper diff --git a/agenta-web/src/components/NoMobilePageWrapper/assets/constants.ts b/agenta-web/src/components/NoMobilePageWrapper/assets/constants.ts new file mode 100644 index 0000000000..058d997c1f --- /dev/null +++ b/agenta-web/src/components/NoMobilePageWrapper/assets/constants.ts @@ -0,0 +1,9 @@ +// List of routes where the component should be displayed +export const MOBILE_UNOPTIMIZED_APP_ROUTES = [ + "/apps", + "/observability", + "/settings", + "/testsets", + "/evaluations", + "/workspaces", +] diff --git a/agenta-web/src/hooks/useResizeObserver.ts b/agenta-web/src/hooks/useResizeObserver.ts index 7d87861dc9..476dd227d8 100644 --- a/agenta-web/src/hooks/useResizeObserver.ts +++ b/agenta-web/src/hooks/useResizeObserver.ts @@ -1,26 +1,27 @@ import {useLayoutEffect, useRef} from "react" -function useResizeObserver( - callback: (entry: ResizeObserverEntry["contentRect"]) => void, -) { +const useResizeObserver = ( + callback?: (entry: ResizeObserverEntry["contentRect"]) => void, + element?: HTMLElement, +) => { const ref = useRef(null) useLayoutEffect(() => { - const element = ref?.current + const _element = ref?.current || element - if (!element) { + if (!_element) { return } const observer = new ResizeObserver((entries) => { - callback(entries[0].contentRect) + callback?.(entries[0].contentRect) }) - observer.observe(element) + observer.observe(_element) return () => { observer.disconnect() } - }, [callback, ref]) + }, [callback, element, ref]) return ref } diff --git a/agenta-web/src/pages/_app.tsx b/agenta-web/src/pages/_app.tsx index 72e6f5da46..c84846caf9 100644 --- a/agenta-web/src/pages/_app.tsx +++ b/agenta-web/src/pages/_app.tsx @@ -2,12 +2,14 @@ import {useEffect} from "react" import type {AppProps} from "next/app" import {useRouter} from "next/router" import Head from "next/head" +import dynamic from "next/dynamic" import posthog from "posthog-js" import {PostHogProvider} from "posthog-js/react" import "@/styles/globals.css" import Layout from "@/components/Layout/Layout" +import {dynamicComponent} from "@/lib/helpers/dynamic" import ThemeContextProvider from "@/components/Layout/ThemeContextProvider" import AppContextProvider from "@/contexts/app.context" import ProfileContextProvider from "@/contexts/profile.context" @@ -16,6 +18,8 @@ import "ag-grid-community/styles/ag-grid.css" import "ag-grid-community/styles/ag-theme-alpine.css" import {Inter} from "next/font/google" +const NoMobilePageWrapper = dynamicComponent("NoMobilePageWrapper/NoMobilePageWrapper") + const inter = Inter({ subsets: ["latin"], variable: "--font-inter", @@ -60,6 +64,7 @@ export default function App({Component, pageProps}: AppProps) { +