diff --git a/apps/web/src/features/earn/components/earn-page.tsx b/apps/web/src/features/earn/components/earn-page.tsx index b4e5d08..384314c 100644 --- a/apps/web/src/features/earn/components/earn-page.tsx +++ b/apps/web/src/features/earn/components/earn-page.tsx @@ -1,5 +1,6 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@workspace/ui/components/tabs" -import { Heading, Text } from "@workspace/ui/components/text" +import { AppShell } from "@workspace/ui/components/app-shell" +import { PageHeader } from "@workspace/ui/components/page-header" import { Navbar } from "../../../ui/Navbar" import { PortfolioTab } from "./portfolio/portfolio-tab" import { DiscoverTab } from "./discover/discover-tab" @@ -8,38 +9,34 @@ import { DistributionsTab } from "./distributions/distributions-tab" export function EarnPage() { return ( -
- -
-
-

Earn

-

- Stake SO4 and buy GLV or GM to earn rewards - -

+ } maxWidth="260"> + + + Portfolio + Discover + Additional opportunities + Distributions + - - - Portfolio - Discover - Additional opportunities - Distributions - - - - - - - - - - - - - - - -
-
+ + + + + + + + + + + + + + } + /> + ) } diff --git a/apps/web/src/features/faucet/components/faucet-page.tsx b/apps/web/src/features/faucet/components/faucet-page.tsx index 1acb488..50ca46b 100644 --- a/apps/web/src/features/faucet/components/faucet-page.tsx +++ b/apps/web/src/features/faucet/components/faucet-page.tsx @@ -1,10 +1,9 @@ import { Alert, AlertDescription } from "@workspace/ui/components/alert" -import { Badge } from "@workspace/ui/components/badge" +import { AppShell } from "@workspace/ui/components/app-shell" import { Card, CardContent } from "@workspace/ui/components/card" import { LoadingButton } from "@workspace/ui/components/loading-button" -import { NumericText } from "@workspace/ui/components/numeric" -import { Stat } from "@workspace/ui/components/stat" -import { Heading, Text } from "@workspace/ui/components/text" +import { PageHeader } from "@workspace/ui/components/page-header" +import { Text } from "@workspace/ui/components/text" import { FAUCET_TOKENS, type FaucetTokenConfig } from "../data/tokens" // eslint-disable-line import/consistent-type-specifier-style import { FAUCET_CONTRACT_ID } from "../lib/clients" import { useFaucetData } from "../hooks/useFaucetData" @@ -121,24 +120,25 @@ export function FaucetPage() { const claimDisabled = !isConnected || mismatch return ( -
- - - -
- {/* Header */} -
+ } + banner={} + maxWidth="2xl" + > + -

Testnet Faucet

- - - Stellar Testnet - + Testnet Faucet
- - Claim test tokens to try trading on SO4. Tokens have no real value. - - + } + description="Claim test tokens to try trading on SO4. Tokens have no real value." + metadata={ + + + Stellar Testnet + + } + /> {!isTestnet ? ( @@ -176,7 +176,7 @@ export function FaucetPage() {

Receive TUSDC, TWBTC, TETH, and TXLM in a single transaction. A cooldown applies between claims. - +

{mismatch && ( @@ -209,7 +209,7 @@ export function FaucetPage() { {data?.cooldownLedgers != null && data.cooldownLedgers > 0 && (

Cooldown: {data.cooldownLedgers.toLocaleString()} ledgers between claims - +

)} @@ -238,7 +238,6 @@ export function FaucetPage() { )} - - + ) } diff --git a/apps/web/src/features/gallery/components/gallery-page.tsx b/apps/web/src/features/gallery/components/gallery-page.tsx index ab6f8bd..a1f7eba 100644 --- a/apps/web/src/features/gallery/components/gallery-page.tsx +++ b/apps/web/src/features/gallery/components/gallery-page.tsx @@ -1,7 +1,9 @@ import { useState } from "react" +import { AppShell } from "@workspace/ui/components/app-shell" import { Badge } from "@workspace/ui/components/badge" import { Button } from "@workspace/ui/components/button" import { Input } from "@workspace/ui/components/input" +import { PageHeader } from "@workspace/ui/components/page-header" import { Separator } from "@workspace/ui/components/separator" import { Skeleton } from "@workspace/ui/components/skeleton" import { Slider } from "@workspace/ui/components/slider" @@ -139,6 +141,123 @@ export function GalleryPage() { A tooltip, positioned automatically. + +
+
+

+ Constrained layout (default) — used for Pools, Earn, Referrals, Faucet +

+
+ + Navbar slot +
+ } + banner={ +
+ Banner slot +
+ } + > +
+ Content area +
+ +
+ +

+ Full layout — used for Trade (fills viewport) +

+
+ + Navbar slot +
+ } + > +
+ Full-viewport content area +
+ + + +
+ +
+
+
+

Minimal — title + description

+
+ +
+
+ +
+

With actions slot

+
+ + + +
+ } + /> +
+
+ +
+

With metadata + tabs slot

+
+ + Active + Tier 3 + + } + tabs={ + + + Traders + Affiliates + Distributions + + + } + /> +
+
+ +
+

With breadcrumbs slot

+
+ + Home + + Settings + + } + /> +
+
+ +
) } diff --git a/apps/web/src/features/pools/components/pools-page.tsx b/apps/web/src/features/pools/components/pools-page.tsx index 46d58a0..05bc623 100644 --- a/apps/web/src/features/pools/components/pools-page.tsx +++ b/apps/web/src/features/pools/components/pools-page.tsx @@ -1,4 +1,6 @@ import { Link } from "@tanstack/react-router" +import { AppShell } from "@workspace/ui/components/app-shell" +import { PageHeader } from "@workspace/ui/components/page-header" import { usePoolsData } from "../hooks/use-pools-data" import { usePoolsTimeRange } from "../hooks/use-pools-time-range" import { PoolsCard } from "./pools-card" @@ -13,18 +15,15 @@ export function PoolsPage() { const { markets, glvEnabled } = usePoolsData(timeRange) return ( -
- - - -
-
-
-

Pools

-

- Provide liquidity to bootstrapped SO4 GM markets on Stellar testnet. -

-
+ } + banner={} + maxWidth="320" + > +

Total pool TVL

@@ -32,7 +31,8 @@ export function PoolsPage() {
- + } + />
Deposit and withdrawal transactions are disabled until liquidity seeding and oracle @@ -65,7 +65,6 @@ export function PoolsPage() { GLV vaults are hidden because GLV contracts are not deployed for this testnet.
) : null} - - + ) } diff --git a/apps/web/src/features/referrals/components/referrals-page.tsx b/apps/web/src/features/referrals/components/referrals-page.tsx index 3b5db4f..d65a7ba 100644 --- a/apps/web/src/features/referrals/components/referrals-page.tsx +++ b/apps/web/src/features/referrals/components/referrals-page.tsx @@ -1,6 +1,7 @@ import { useState } from "react" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@workspace/ui/components/tabs" -import { Heading, Text } from "@workspace/ui/components/text" +import { AppShell } from "@workspace/ui/components/app-shell" +import { PageHeader } from "@workspace/ui/components/page-header" import { useQueryClient } from "@tanstack/react-query" import { Navbar } from "../../../ui/Navbar" import { useTraderStats } from "../hooks/use-referrals-data" @@ -46,21 +47,16 @@ export function ReferralsPage() { const hasAffiliateCode = Boolean(affiliateCode) return ( -
- -
-
-

Referrals

-

- Get fee discounts and earn up to 15% commission through the SO4 referral program - -

- - setTab(v as ReferralsTab)} - className="gap-6" - > + } maxWidth="260"> + setTab(v as ReferralsTab)} + className="gap-6" + > Traders Affiliates @@ -102,7 +98,7 @@ export function ReferralsPage() { />
-
- + + ) } diff --git a/apps/web/src/features/trade/components/TradePage.tsx b/apps/web/src/features/trade/components/TradePage.tsx index eba651e..d368599 100644 --- a/apps/web/src/features/trade/components/TradePage.tsx +++ b/apps/web/src/features/trade/components/TradePage.tsx @@ -2,6 +2,7 @@ import { useEffect, useRef } from "react" import { getRouteApi } from "@tanstack/react-router" import { useTradeState } from "../hooks/useTradeState" import { useOrderEventPolling } from "../hooks/useOrderEventPolling" +import { AppShell } from "@workspace/ui/components/app-shell" import { Navbar } from "../../../ui/Navbar" import { TVChart } from "./chart/TVChart" import { TradePanel } from "./trade-panel/TradePanel" @@ -36,9 +37,12 @@ export function TradePage() { }, [search.ref]) return ( -
- - + } + banner={} + className="overflow-hidden" + >
{/* ── Left: Chart + Bottom Tabs ──────────────────────────────── */}
@@ -67,6 +71,6 @@ export function TradePage() {
-
+ ) } diff --git a/apps/web/src/ui/Navbar.tsx b/apps/web/src/ui/Navbar.tsx index 043785f..f91be4c 100644 --- a/apps/web/src/ui/Navbar.tsx +++ b/apps/web/src/ui/Navbar.tsx @@ -1,50 +1,18 @@ -import { useState } from "react" import { Link } from "@tanstack/react-router" import { Button } from "@workspace/ui/components/button" import { ThemeToggle } from "./theme-toggle" import { ConnectButton } from "@/features/wallet/components/ConnectButton" - -function Logo() { - return ( - - - - - - - - - - - so4.market - - - ) -} +import { + SiteLogo, + HamburgerButton, + useMobileMenu, + navOuterClass, + containerClass, + desktopLinkClass, + desktopActiveLinkClass, + mobileLinkClass, + mobileActiveLinkClass, +} from "./nav/primitives" const LANDING_LINKS = [ { label: "Trade", href: "/trade" }, @@ -64,35 +32,23 @@ const APP_LINKS: Array<{ label: string; to: "/trade" | "/pools" | "/earn" | "/re { label: "Docs", to: null }, ] -const desktopAppLinkClass = - "relative inline-flex h-8 items-center rounded-md px-2 text-13-5 text-muted-foreground transition-colors hover:bg-muted/60 hover:text-foreground" - -const desktopAppLinkActiveClass = - "relative inline-flex h-8 items-center rounded-md bg-primary/10 px-2 text-13-5 font-medium text-foreground after:absolute after:inset-x-2 after:-bottom-[13px] after:h-0.5 after:rounded-full after:bg-primary" - -const mobileAppLinkClass = - "block rounded-md px-3 py-2 text-sm text-muted-foreground transition-colors hover:bg-muted/60 hover:text-foreground" - -const mobileAppLinkActiveClass = - "block rounded-md bg-primary/10 px-3 py-2 text-sm font-medium text-foreground ring-1 ring-primary/20" - type Props = { variant: "landing" | "app" } export function Navbar({ variant }: Props) { - const [mobileOpen, setMobileOpen] = useState(false) + const { open, toggle, close } = useMobileMenu() const isApp = variant === "app" return ( -