From 4eb782a6f092b110c14734dc11ea7d1c9811f2e7 Mon Sep 17 00:00:00 2001 From: Anton Tranelis Date: Mon, 12 Jan 2026 19:34:06 +0100 Subject: [PATCH] refactor(lib): move info modal to dedicated /info route - Add InfoRedirect component for one-time redirect to /info on page load - Simplify Modal component to pure presentation (remove redirect logic) - Change NavBar info button from showModal() to Link to /info route - Remove unused window.my_modal_3 global type declaration - Fix modal centering by removing conflicting position classes Co-Authored-By: Claude Opus 4.5 --- app/src/App.tsx | 12 +++------ lib/src/Components/AppShell/InfoRedirect.tsx | 27 ++++++++++++++++++++ lib/src/Components/AppShell/NavBar.tsx | 9 ++----- lib/src/Components/AppShell/index.tsx | 1 + lib/src/Components/Gaming/Modal.tsx | 2 +- lib/src/index.tsx | 8 ------ 6 files changed, 34 insertions(+), 25 deletions(-) create mode 100644 lib/src/Components/AppShell/InfoRedirect.tsx diff --git a/app/src/App.tsx b/app/src/App.tsx index 7596bb0c..854939ba 100644 --- a/app/src/App.tsx +++ b/app/src/App.tsx @@ -22,6 +22,7 @@ import { Content, AuthProvider, Modal, + InfoRedirect, InvitePage, LoginPage, SignupPage, @@ -41,7 +42,7 @@ import { UserSettings, } from 'utopia-ui' -import { Route, Routes, useNavigate } from 'react-router-dom' +import { Route, Routes } from 'react-router-dom' import './App.css' import { Suspense, useEffect, useState } from 'react' @@ -196,14 +197,6 @@ function App() { const currentUrl = window.location.href const bottomRoutes = getBottomRoutes(currentUrl) - const navigate = useNavigate() - - // Redirect to /info if map.info_open is true (on first load) - useEffect(() => { - if (map?.info_open && window.location.pathname === '/') { - void navigate('/info') - } - }, [map?.info_open, navigate]) if (map && layers) return ( @@ -218,6 +211,7 @@ function App() { > {tagsApi && } + diff --git a/lib/src/Components/AppShell/InfoRedirect.tsx b/lib/src/Components/AppShell/InfoRedirect.tsx new file mode 100644 index 00000000..efd17ca5 --- /dev/null +++ b/lib/src/Components/AppShell/InfoRedirect.tsx @@ -0,0 +1,27 @@ +import { useEffect, useRef } from 'react' +import { useNavigate } from 'react-router-dom' + +interface InfoRedirectProps { + /** If true, redirects to /info route on initial page load (once) */ + enabled?: boolean +} + +/** + * Redirects to /info route on initial page load when enabled. + * Only redirects once per session to avoid redirect loops. + * Place this component inside the Router context but outside of Routes. + * @category AppShell + */ +export function InfoRedirect({ enabled }: InfoRedirectProps) { + const navigate = useNavigate() + const hasRedirected = useRef(false) + + useEffect(() => { + if (enabled && window.location.pathname === '/' && !hasRedirected.current) { + hasRedirected.current = true + void navigate('/info') + } + }, [enabled, navigate]) + + return null +} diff --git a/lib/src/Components/AppShell/NavBar.tsx b/lib/src/Components/AppShell/NavBar.tsx index 17eecc01..307a96e7 100644 --- a/lib/src/Components/AppShell/NavBar.tsx +++ b/lib/src/Components/AppShell/NavBar.tsx @@ -50,14 +50,9 @@ export default function NavBar({ appName }: { appName: string }) { {appName} - + diff --git a/lib/src/Components/AppShell/index.tsx b/lib/src/Components/AppShell/index.tsx index 7f27e9d5..99c4f0c2 100644 --- a/lib/src/Components/AppShell/index.tsx +++ b/lib/src/Components/AppShell/index.tsx @@ -1,4 +1,5 @@ export * from './AppShell' export { SideBar } from './SideBar' export { Content } from './Content' +export { InfoRedirect } from './InfoRedirect' export { default as SVG } from 'react-inlinesvg' diff --git a/lib/src/Components/Gaming/Modal.tsx b/lib/src/Components/Gaming/Modal.tsx index 5a4e7fb0..2563ccf0 100644 --- a/lib/src/Components/Gaming/Modal.tsx +++ b/lib/src/Components/Gaming/Modal.tsx @@ -8,7 +8,7 @@ export function Modal({ children }: { children: React.ReactNode }) { {children} diff --git a/lib/src/index.tsx b/lib/src/index.tsx index e62e6af6..6d6c3e14 100644 --- a/lib/src/index.tsx +++ b/lib/src/index.tsx @@ -10,11 +10,3 @@ export * from './Components/Input' export * from './Components/Item' export * from './Components/Onboarding' export * from './Components/Profile' - -declare global { - interface Window { - my_modal_3: { - showModal(): void - } - } -}