From ea94534c94b6c4b38f1af5ccad65a9f996732762 Mon Sep 17 00:00:00 2001 From: christiangruender <131187233+christiangruender@users.noreply.github.com> Date: Mon, 3 Nov 2025 18:51:17 +0100 Subject: [PATCH 1/2] feat: redesign landing page with aurora background Major landing page redesign with simplified content and animated background: - Added aurora background component with animated gradient effect - Simplified hero section and streamlined messaging - Removed scroll-reveal card animations for better performance - Reorganized feature cards for better user flow - Centered governance section cards - Added CSS animations for aurora effect in globals.css - Cleaned up unnecessary sections and redundant content Files changed: - src/components/pages/homepage/index.tsx: Complete page restructure - src/components/ui/background.tsx: New aurora background component - src/styles/globals.css: Added aurora animation keyframes --- src/components/pages/homepage/index.tsx | 501 ++++++++++++++++++++++-- src/components/ui/background.tsx | 110 ++++++ src/styles/globals.css | 21 + 3 files changed, 600 insertions(+), 32 deletions(-) create mode 100644 src/components/ui/background.tsx diff --git a/src/components/pages/homepage/index.tsx b/src/components/pages/homepage/index.tsx index 013f7e7f..e9ebfda6 100644 --- a/src/components/pages/homepage/index.tsx +++ b/src/components/pages/homepage/index.tsx @@ -1,19 +1,143 @@ import ConnectWallet from "@/components/common/cardano-objects/connect-wallet"; import { Button } from "@/components/ui/button"; +import { Separator } from "@/components/ui/separator"; +import { Background } from "@/components/ui/background"; import Link from "next/link"; import useUser from "@/hooks/useUser"; import { useRouter } from "next/router"; import { api } from "@/utils/api"; import CardUI from "@/components/ui/card-content"; import RowLabelInfo from "@/components/common/row-label-info"; -import Globe from "./globe"; +import Image from "next/image"; +import { useEffect, useState } from "react"; +import { Database } from "lucide-react"; + +// DApp Card Component +function DappCard({ title, description, url }: { title: string; description: string; url: string }) { + const [ogImage, setOgImage] = useState(null); + const [favicon, setFavicon] = useState(null); + const [isFetchingOg, setIsFetchingOg] = useState(true); + const [imageLoaded, setImageLoaded] = useState(false); + const [imageError, setImageError] = useState(false); + + useEffect(() => { + let cancelled = false; + async function fetchOg() { + setIsFetchingOg(true); + try { + const res = await fetch(`/api/local/og?url=${encodeURIComponent(url)}`); + const data = await res.json(); + if (!cancelled) { + setOgImage(data.image || null); + setFavicon(data.favicon || null); + setImageLoaded(false); + setImageError(false); + } + } catch { + if (!cancelled) { + setOgImage(null); + setFavicon(null); + setImageLoaded(false); + setImageError(true); + } + } finally { + if (!cancelled) setIsFetchingOg(false); + } + } + fetchOg(); + return () => { + cancelled = true; + }; + }, [url]); + + const shouldShowImageArea = Boolean(ogImage) && !imageError; + + return ( + + + {shouldShowImageArea ? ( +
+ {title} setImageLoaded(true)} + onError={() => setImageError(true)} + /> + {!imageLoaded && ( +
+ )} +
+ ) : ( +
+ {isFetchingOg ? ( +
+ ) : ( +
+ {favicon ? ( + favicon + ) : ( +
+ )} + {new URL(url).hostname} +
+ )} +
+ )} + +
+

+ {favicon && favicon} + {title} +

+

{description}

+
+ +
+ ); +} export function PageHomepage() { const { user } = useUser(); const router = useRouter(); - const pathIsNewWallet = router.pathname == "/wallets/invite/[id]"; + const pathIsNewWallet = router.pathname === "/wallets/invite/[id]"; const newWalletId = pathIsNewWallet ? (router.query.id as string) : undefined; + // Scroll detection for aurora fade-out + const [scrollY, setScrollY] = useState(0); + + useEffect(() => { + const handleScroll = (e: Event) => { + const target = e.target as HTMLElement; + const currentScrollY = target.scrollTop; + setScrollY(currentScrollY); + }; + + // Find the main element (scrollable container) + const mainElement = document.querySelector('main'); + + if (mainElement) { + // Initial call + setScrollY(mainElement.scrollTop); + + // Listen to scroll on main element + mainElement.addEventListener("scroll", handleScroll, { passive: true }); + + return () => { + mainElement.removeEventListener("scroll", handleScroll); + }; + } + }, []); + + // Aurora Fade-Out (Top): 500px - 1500px + const calculateTopAuroraOpacity = () => { + if (scrollY < 500) return 0.4; + if (scrollY > 1500) return 0; + return 0.4 * (1 - (scrollY - 500) / 1000); + }; + + const topAuroraOpacity = calculateTopAuroraOpacity(); + const { data: newWallet } = api.wallet.getNewWallet.useQuery( { walletId: newWalletId! }, { @@ -22,45 +146,358 @@ export function PageHomepage() { ); return ( -
-
-
-
-

Multisig Platform

-

- Secure your treasury and participant in governance, as a team with - multi-signature -

- {newWallet && ( - - - - - )} -
-
+
+ {/* Aurora Background - Fixed with Smooth Fade-Out */} +
+ +
+ + {/* Hero Section */} +
+
+

+ Manage Cardano Treasuries with Multisig Security +

+ +

+ Free, open-source, Cardano-native wallet built by Mesh with multi-signature security for teams and organizations +

+ + {newWallet && ( + + + + + )} + +
{user ? ( -
- - -
+ ) : ( )}
+ +

+ Secure Treasuries • Participate in Governance • Collaborate +

-
-
- -
+ + + + + {/* Control Your Cardano Treasuries Section */} +
+
+

+ Control Your Cardano Treasuries +

+
+ + + {/* Wallet Management */} + + + +
+ Invite and verify signers +
+
+ + +
+ Multi-wallet management +
+
+ + + {/* Transaction Management */} + + + +
+ Create transactions +
+
+ + + +
+ Transaction history +
+
+ + +
+ Pending transactions +
+
+ + {/* Chat and Collaborate */} + +
+ Team chat +
+
+
+
+
+ + + + {/* Governance and Staking Section */} +
+
+

+ Participate in Governance +

+

+ + Governance in the Multisig Platform + +

+ +
+
+ +
+ Governance proposals +
+
+
+ +
+ +
+ DRep registration +
+
+
+
+
+
+ + + + {/* Integrate Your DApps Section */} +
+
+

+ Use with Your Favorite DApps +

+ + {/* DApps Grid */} +
+ + + +
+ + {/* API Integration Box */} +
+ +
+ +
+
+
+
+
+ + + + + {/* Final CTA Section */} +
+
+

+ Ready to Secure Your Treasury? +

+ +

+ Connect your Cardano wallet to get started. Create your first multisig + wallet in minutes. +

+ +
+ {user ? ( + + ) : ( + + )} +
+
+
+ + + + {/* Footer with Social Links */} +
); } diff --git a/src/components/ui/background.tsx b/src/components/ui/background.tsx new file mode 100644 index 00000000..c7f3a2b5 --- /dev/null +++ b/src/components/ui/background.tsx @@ -0,0 +1,110 @@ +"use client" + +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" +import { cn } from "@/lib/utils" + +const backgroundVariants = cva( + "absolute inset-0", + { + variants: { + variant: { + aurora: cn( + // Aurora gradient animation + "bg-aurora", + "animate-aurora", + "blur-[40px]", + // GPU acceleration + "transform-gpu", + "will-change-[background-position]" + ), + "aurora-static": cn( + // Static aurora (no animation) + "bg-aurora", + "blur-[40px]" + ), + // Future variants can go here: + // grid: "...", + // dots: "...", + // particles: "...", + }, + }, + defaultVariants: { + variant: "aurora", + }, + } +) + +export interface BackgroundProps + extends React.HTMLAttributes, + VariantProps { + /** + * Show radial gradient mask for center focus + * @default true + */ + showRadialGradient?: boolean +} + +/** + * Background Component + * + * Animated background component with multiple variants. + * Built with Class Variance Authority (CVA) following shadcn/ui patterns. + * + * @example + * ```tsx + * // Aurora background (default) + *
+ * + *
+ * ``` + */ +const Background = React.forwardRef( + ({ className, variant, showRadialGradient = true, children, ...props }, ref) => { + return ( +
+ {/* Animated background layer */} +
+ + {/* Optional radial gradient mask for center focus */} + {showRadialGradient && ( +
+ )} + + {/* Children content */} + {children} +
+ ) + } +) +Background.displayName = "Background" + +export { Background, backgroundVariants } \ No newline at end of file diff --git a/src/styles/globals.css b/src/styles/globals.css index 4c7e0373..220e7c9e 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -48,6 +48,27 @@ animation: spin 1s linear infinite; } +@keyframes aurora { + from { + background-position: 50% 50%; + } + to { + background-position: 350% 50%; + } +} + +.animate-aurora { + /* 70s = Smoother, more subtle gradient movement (~15% slower) */ + animation: aurora 70s linear infinite; +} + +/* Reduced motion support */ +@media (prefers-reduced-motion: reduce) { + .animate-aurora { + animation-duration: 140s; /* Slower for accessibility */ + } +} + /** * Glass Morphism Navigation Enhancements * Applied globally to sidebar and header elements From 47752dc6c082529763659a027ba68c37e1e63a9d Mon Sep 17 00:00:00 2001 From: christiangruender <131187233+christiangruender@users.noreply.github.com> Date: Fri, 7 Nov 2025 21:48:35 +0100 Subject: [PATCH 2/2] Hide sidebar and navigation on landing page when user is not logged in --- src/components/common/overall-layout/layout.tsx | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/components/common/overall-layout/layout.tsx b/src/components/common/overall-layout/layout.tsx index 5d549a82..870d142c 100644 --- a/src/components/common/overall-layout/layout.tsx +++ b/src/components/common/overall-layout/layout.tsx @@ -187,11 +187,12 @@ export default function RootLayout({ const isLoggedIn = !!user; return ( -
+
{isLoading && } - {/* Sidebar for larger screens */} -