diff --git a/src/components/layout/docs-layout-client.tsx b/src/components/layout/docs-layout-client.tsx index e5b03574..409b22eb 100644 --- a/src/components/layout/docs-layout-client.tsx +++ b/src/components/layout/docs-layout-client.tsx @@ -1,6 +1,8 @@ "use client"; +import { usePathname } from "next/navigation"; import type { ReactNode } from "react"; +import { useMemo } from "react"; import { baseOptions } from "@/app/layout.config"; import { ArbitrumIcon, @@ -21,6 +23,79 @@ interface DocsLayoutClientProps { export function DocsLayoutClient({ children }: DocsLayoutClientProps) { const currentTree = useNavigationTree(); + const pathname = usePathname(); + + // Determine if shared paths should be included in Stellar tab based on sessionStorage + const tabs = useMemo(() => { + const isSharedPath = + pathname.startsWith("/monitor") || pathname.startsWith("/relayer"); + const lastEcosystem = + typeof window !== "undefined" + ? sessionStorage.getItem("lastEcosystem") + : null; + + // Include shared paths in Stellar tab only if coming from Stellar context + const stellarUrls = + isSharedPath && lastEcosystem === "stellar" + ? new Set(["/stellar-contracts", "/monitor", "/relayer"]) + : new Set(["/stellar-contracts"]); + + return [ + { + title: "Ethereum & EVM", + url: "/contracts", + icon: , + urls: new Set([ + "/contracts", + "/community-contracts", + "/upgrades-plugins", + "/wizard", + "/relayer", + "/monitor", + "/ui-builder", + "/upgrades", + "/defender", + "/tools", + ]), + }, + { + title: "Arbitrum Stylus", + url: "/contracts-stylus", + icon: , + }, + { + title: "Starknet", + url: "/contracts-cairo", + icon: , + }, + { + title: "Stellar", + url: "/stellar-contracts", + icon: , + urls: stellarUrls, + }, + { + title: "Midnight", + url: "/contracts-compact", + icon: , + }, + { + title: "Polkadot", + url: "/substrate-runtimes", + icon: , + }, + { + title: "Uniswap Hooks", + url: "/uniswap-hooks", + icon: , + }, + { + title: "Zama FHEVM", + url: "/confidential-contracts", + icon: , + }, + ]; + }, [pathname]); return ( , - urls: new Set([ - "/contracts", - "/community-contracts", - "/upgrades-plugins", - "/wizard", - "/relayer", - "/monitor", - "/ui-builder", - "/upgrades", - "/defender", - "/tools", - ]), - }, - { - title: "Arbitrum Stylus", - url: "/contracts-stylus", - icon: , - }, - { - title: "Starknet", - url: "/contracts-cairo", - icon: , - }, - { - title: "Stellar", - url: "/stellar-contracts", - icon: , - }, - { - title: "Midnight", - url: "/contracts-compact", - icon: , - }, - { - title: "Polkadot", - url: "/substrate-runtimes", - icon: , - }, - { - title: "Uniswap Hooks", - url: "/uniswap-hooks", - icon: , - }, - { - title: "Zama FHEVM", - url: "/confidential-contracts", - icon: , - }, - ], + tabs, }} > {children} diff --git a/src/hooks/use-navigation-tree.ts b/src/hooks/use-navigation-tree.ts index 2dfda17d..2f0a0e3f 100644 --- a/src/hooks/use-navigation-tree.ts +++ b/src/hooks/use-navigation-tree.ts @@ -1,6 +1,7 @@ "use client"; import { usePathname } from "next/navigation"; +import { useEffect } from "react"; import { arbitrumStylusTree, ethereumEvmTree, @@ -15,6 +16,26 @@ import { export function useNavigationTree() { const pathname = usePathname(); + // Track ecosystem changes in sessionStorage + useEffect(() => { + if (typeof window === "undefined") return; + + if (pathname.startsWith("/stellar-contracts")) { + sessionStorage.setItem("lastEcosystem", "stellar"); + } else if ( + pathname.startsWith("/contracts") || + pathname.startsWith("/community-contracts") || + pathname.startsWith("/upgrades-plugins") || + pathname.startsWith("/wizard") || + pathname.startsWith("/ui-builder") || + pathname.startsWith("/upgrades") || + pathname.startsWith("/defender") || + pathname.startsWith("/tools") + ) { + sessionStorage.setItem("lastEcosystem", "ethereum"); + } + }, [pathname]); + // Determine which navigation tree to use based on the current path if (pathname.startsWith("/contracts-stylus")) { return arbitrumStylusTree; @@ -34,5 +55,23 @@ export function useNavigationTree() { return ethereumEvmTree; } + // For shared paths like /monitor and /relayer, check sessionStorage to see + // which ecosystem was last active, defaulting to ethereumEvmTree + if (typeof window !== "undefined") { + const lastEcosystem = sessionStorage.getItem("lastEcosystem"); + + if (pathname.startsWith("/monitor") || pathname.startsWith("/relayer")) { + switch (lastEcosystem) { + case "stellar": + return stellarTree; + case "ethereum": + return ethereumEvmTree; + default: + return ethereumEvmTree; + } + } + } + + // Default to ethereumEvmTree for other paths return ethereumEvmTree; } diff --git a/src/navigation/ethereum-evm.json b/src/navigation/ethereum-evm.json index 1c2078c8..7bc278aa 100644 --- a/src/navigation/ethereum-evm.json +++ b/src/navigation/ethereum-evm.json @@ -785,7 +785,7 @@ }, { "type": "separator", - "name": "Tools" + "name": "Open Source Tools" }, { "type": "folder", @@ -837,11 +837,6 @@ "name": "Solana Integration", "url": "/relayer/solana" }, - { - "type": "page", - "name": "Stellar Integration", - "url": "/relayer/stellar" - }, { "type": "folder", "name": "API Reference", @@ -1085,6 +1080,11 @@ { "type": "folder", "name": "Monitor", + "index": { + "type": "page", + "name": "Overview", + "url": "/monitor" + }, "children": [ { "type": "page", diff --git a/src/navigation/stellar.json b/src/navigation/stellar.json index 0db75ee8..9b3bea6d 100644 --- a/src/navigation/stellar.json +++ b/src/navigation/stellar.json @@ -257,5 +257,351 @@ ] } ] + }, + { + "type": "separator", + "name": "Open Source Tools" + }, + { + "type": "folder", + "name": "Relayer", + "children": [ + { + "type": "page", + "name": "Overview", + "url": "/relayer" + }, + { + "type": "page", + "name": "Quickstart", + "url": "/relayer/quickstart" + }, + { + "type": "folder", + "name": "Configuration", + "index": { + "type": "page", + "name": "Overview", + "url": "/relayer/configuration" + }, + "children": [ + { + "type": "page", + "name": "Signers", + "url": "/relayer/configuration/signers" + }, + { + "type": "page", + "name": "Network Configuration", + "url": "/relayer/network_configuration" + }, + { + "type": "page", + "name": "Storage Configuration", + "url": "/relayer/configuration/storage" + } + ] + }, + { + "type": "page", + "name": "Stellar Integration", + "url": "/relayer/stellar" + }, + { + "type": "folder", + "name": "API Reference", + "index": { + "type": "page", + "name": "Overview", + "url": "/relayer/api" + }, + "children": [ + { + "type": "folder", + "name": "Relayers", + "children": [ + { + "type": "page", + "name": "List Relayers", + "url": "/relayer/api/listRelayers" + }, + { + "type": "page", + "name": "Create Relayer", + "url": "/relayer/api/createRelayer" + }, + { + "type": "page", + "name": "Get Relayer", + "url": "/relayer/api/getRelayer" + }, + { + "type": "page", + "name": "Delete Relayer", + "url": "/relayer/api/deleteRelayer" + }, + { + "type": "page", + "name": "Update Relayer", + "url": "/relayer/api/updateRelayer" + }, + { + "type": "page", + "name": "Get Relayer Balance", + "url": "/relayer/api/getRelayerBalance" + }, + { + "type": "page", + "name": "RPC", + "url": "/relayer/api/rpc" + }, + { + "type": "page", + "name": "Sign", + "url": "/relayer/api/sign" + }, + { + "type": "page", + "name": "Sign Transaction", + "url": "/relayer/api/signTransaction" + }, + { + "type": "page", + "name": "Sign Typed Data", + "url": "/relayer/api/signTypedData" + }, + { + "type": "page", + "name": "Get Relayer Status", + "url": "/relayer/api/getRelayerStatus" + }, + { + "type": "page", + "name": "Send Transaction", + "url": "/relayer/api/sendTransaction" + }, + { + "type": "page", + "name": "List Transactions", + "url": "/relayer/api/listTransactions" + }, + { + "type": "page", + "name": "Get Transaction by Nonce", + "url": "/relayer/api/getTransactionByNonce" + }, + { + "type": "page", + "name": "Delete Pending Transactions", + "url": "/relayer/api/deletePendingTransactions" + }, + { + "type": "page", + "name": "Get Transaction by ID", + "url": "/relayer/api/getTransactionById" + }, + { + "type": "page", + "name": "Replace Transaction", + "url": "/relayer/api/replaceTransaction" + }, + { + "type": "page", + "name": "Cancel Transaction", + "url": "/relayer/api/cancelTransaction" + } + ] + }, + { + "type": "folder", + "name": "Plugins", + "children": [ + { + "type": "page", + "name": "Call Plugin", + "url": "/relayer/api/callPlugin" + } + ] + }, + { + "type": "folder", + "name": "Notifications", + "children": [ + { + "type": "page", + "name": "List Notifications", + "url": "/relayer/api/listNotifications" + }, + { + "type": "page", + "name": "Create Notification", + "url": "/relayer/api/createNotification" + }, + { + "type": "page", + "name": "Get Notification", + "url": "/relayer/api/getNotification" + }, + { + "type": "page", + "name": "Delete Notification", + "url": "/relayer/api/deleteNotification" + }, + { + "type": "page", + "name": "Update Notification", + "url": "/relayer/api/updateNotification" + } + ] + }, + { + "type": "folder", + "name": "Signers", + "children": [ + { + "type": "page", + "name": "List Signers", + "url": "/relayer/api/listSigners" + }, + { + "type": "page", + "name": "Create Signer", + "url": "/relayer/api/createSigner" + }, + { + "type": "page", + "name": "Get Signer", + "url": "/relayer/api/getSigner" + }, + { + "type": "page", + "name": "Delete Signer", + "url": "/relayer/api/deleteSigner" + }, + { + "type": "page", + "name": "Update Signer", + "url": "/relayer/api/updateSigner" + } + ] + }, + { + "type": "folder", + "name": "Metrics", + "children": [ + { + "type": "page", + "name": "Scrape Metrics", + "url": "/relayer/api/scrape_metrics" + }, + { + "type": "page", + "name": "List Metrics", + "url": "/relayer/api/list_metrics" + }, + { + "type": "page", + "name": "Metric Detail", + "url": "/relayer/api/metric_detail" + } + ] + }, + { + "type": "folder", + "name": "Health", + "children": [ + { + "type": "page", + "name": "Health", + "url": "/relayer/api/health" + } + ] + } + ] + }, + { + "type": "page", + "name": "Project Structure", + "url": "/relayer/structure" + }, + { + "type": "page", + "name": "Project Roadmap", + "url": "/relayer/roadmap" + }, + { + "type": "page", + "name": "Plugins", + "url": "/relayer/plugins" + }, + { + "type": "page", + "name": "Changelog", + "url": "/relayer/changelog" + }, + { + "type": "page", + "name": "Rust Book", + "url": "https://docs-v1-1--openzeppelin-relayer.netlify.app/openzeppelin_relayer/", + "external": true + } + ] + }, + { + "type": "folder", + "name": "Monitor", + "children": [ + { + "type": "page", + "name": "Quickstart", + "url": "/monitor/quickstart" + }, + { + "type": "page", + "name": "Architecture Guide", + "url": "/monitor/architecture" + }, + { + "type": "page", + "name": "Project Structure", + "url": "/monitor/project-structure" + }, + { + "type": "page", + "name": "RPC Client", + "url": "/monitor/rpc" + }, + { + "type": "page", + "name": "Custom scripts", + "url": "/monitor/scripts" + }, + { + "type": "page", + "name": "Error Handling", + "url": "/monitor/error" + }, + { + "type": "page", + "name": "Testing", + "url": "/monitor/testing" + }, + { + "type": "page", + "name": "Contribution guidelines", + "url": "/monitor/contribution" + }, + { + "type": "page", + "name": "Changelog", + "url": "/monitor/changelog" + }, + { + "type": "page", + "name": "Technical Rust Documentation", + "url": "https://docs-v1-0--openzeppelin-monitor.netlify.app/openzeppelin_monitor/", + "external": true + } + ] } ]