Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 24 additions & 8 deletions apps/frontend/src/components/Navbar/DesktopNavbar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Link, useParams } from "@tanstack/react-router";
import { Link, useParams, useRouterState } from "@tanstack/react-router";
import { useTranslation } from "react-i18next";
import { cn } from "../../helpers/cn";
import { useWidgetMode } from "../../hooks/useWidgetMode";
Expand All @@ -10,31 +10,47 @@ export const DesktopNavbar = () => {
const isWidgetMode = useWidgetMode();
const { resetRampAndNavigateHome } = useNavbarHandlers();
const params = useParams({ strict: false });
const routerState = useRouterState();

const isBusinessPage = routerState.location.pathname.includes("/business");
const useTransparentStyle = isWidgetMode || isBusinessPage;

return (
<div className={cn("relative px-4 py-4 md:px-10 md:py-5", isWidgetMode ? "bg-transparent" : "bg-blue-950")}>
<div className={cn("relative px-4 py-4 md:px-10 md:py-5", useTransparentStyle ? "bg-transparent" : "bg-blue-950")}>
<div className="mx-6 flex items-center justify-between sm:container sm:mx-auto">
{isWidgetMode ? (
<LogoButton onClick={resetRampAndNavigateHome} />
<LogoButton onClick={resetRampAndNavigateHome} variant="blue" />
) : (
<>
<div className="group flex grow items-center gap-10">
<LogoButton onClick={resetRampAndNavigateHome} />
<LogoButton onClick={resetRampAndNavigateHome} variant={isBusinessPage ? "blue" : "white"} />
<Link
activeProps={{
className: "text-white transition-colors hover:text-white group-hover:[&:not(:hover)]:text-gray-400"
className: cn(
"transition-colors group-hover:[&:not(:hover)]:text-gray-400",
isBusinessPage ? "text-blue-950 hover:text-blue-950" : "text-white hover:text-white"
)
}}
className="text-gray-400 text-xl transition-colors hover:text-white"
className={cn(
"text-xl transition-colors",
isBusinessPage ? "text-gray-600 hover:text-blue-950" : "text-gray-400 hover:text-white"
)}
params={params}
to="/{-$locale}"
>
{t("components.navbar.individuals")}
</Link>
<Link
activeProps={{
className: "text-white transition-colors hover:text-white group-hover:[&:not(:hover)]:text-gray-400"
className: cn(
"transition-colors group-hover:[&:not(:hover)]:text-gray-400",
isBusinessPage ? "text-blue-950 hover:text-blue-950" : "text-white hover:text-white"
)
}}
className="text-gray-400 text-xl transition-colors hover:text-white"
className={cn(
"text-xl transition-colors",
isBusinessPage ? "text-gray-600 hover:text-blue-950" : "text-gray-400 hover:text-white"
)}
params={params}
to="/{-$locale}/business"
>
Expand Down
11 changes: 7 additions & 4 deletions apps/frontend/src/components/Navbar/LogoButton.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
import { useTranslation } from "react-i18next";
import blueLogo from "../../assets/logo/blue.svg";
import whiteLogo from "../../assets/logo/white.png";
import { useWidgetMode } from "../../hooks/useWidgetMode";

interface LogoButtonProps {
onClick: () => void;
variant?: "blue" | "white";
}

export const LogoButton = ({ onClick }: LogoButtonProps) => {
export const LogoButton = ({ onClick, variant = "white" }: LogoButtonProps) => {
const { t } = useTranslation();
const isWidgetMode = useWidgetMode();

return (
<button className="cursor-pointer" onClick={onClick}>
<img alt={t("components.navbar.vortexLogo")} className="xs:block max-w-38" src={isWidgetMode ? blueLogo : whiteLogo} />
<img
alt={t("components.navbar.vortexLogo")}
className="xs:block max-w-38"
src={variant === "blue" ? blueLogo : whiteLogo}
/>
</button>
);
};
11 changes: 8 additions & 3 deletions apps/frontend/src/components/Navbar/MobileNavbar.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useRouterState } from "@tanstack/react-router";
import { AnimatePresence } from "motion/react";
import { useRef, useState } from "react";
import { cn } from "../../helpers/cn";
Expand All @@ -12,9 +13,13 @@ export const MobileNavbar = () => {
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
const isWidgetMode = useWidgetMode();
const navbarRef = useRef<HTMLDivElement>(null);
const routerState = useRouterState();

const { resetRampAndNavigateHome } = useNavbarHandlers();

const isBusinessPage = routerState.location.pathname.includes("/business");
const useTransparentStyle = isWidgetMode || isBusinessPage;

const toggleMobileMenu = () => {
setIsMobileMenuOpen(!isMobileMenuOpen);
};
Expand All @@ -27,13 +32,13 @@ export const MobileNavbar = () => {

return (
<div className="relative" ref={navbarRef}>
<div className={cn("relative z-20 px-4 py-4", isWidgetMode ? "bg-transparent" : "bg-blue-950")}>
<div className={cn("relative z-20 px-4 py-4", useTransparentStyle ? "bg-transparent" : "bg-blue-950")}>
<div className="flex items-center justify-between">
{isWidgetMode ? (
<LogoButton onClick={resetRampAndNavigateHome} />
<LogoButton onClick={resetRampAndNavigateHome} variant="blue" />
) : (
<div className="flex grow items-center justify-between">
<LogoButton onClick={resetRampAndNavigateHome} />
<LogoButton onClick={resetRampAndNavigateHome} variant={isBusinessPage ? "blue" : "white"} />
<HamburgerButton isOpen={isMobileMenuOpen} onClick={toggleMobileMenu} />
</div>
)}
Expand Down
92 changes: 64 additions & 28 deletions apps/frontend/src/sections/business/Hero/index.tsx
Original file line number Diff line number Diff line change
@@ -1,83 +1,119 @@
import { ArrowTopRightOnSquareIcon } from "@heroicons/react/20/solid";
import { motion } from "motion/react";
import { motion, useReducedMotion, type Variants } from "motion/react";
import { useTranslation } from "react-i18next";
import WidgetSnippetImageEUR from "../../../assets/metawallet-vortex.png";
import { AnimatedTitle } from "../../../components/AnimatedTitle";
import { fadeInUp, prefersReducedMotion, staggerContainer } from "../../../constants/animations";
import { fadeInUp, staggerContainer } from "../../../constants/animations";

const heroImageVariants: Variants = {
hidden: {
opacity: 0,
scale: 0.92,
y: 40
},
visible: {
opacity: 1,
scale: 1,
transition: {
damping: 25,
delay: 0.3,
duration: 0.8,
ease: [0.25, 0.46, 0.45, 0.94],
stiffness: 100,
type: "spring"
},
y: 0
}
};

export function Hero() {
const { t } = useTranslation();
const reducedMotion = prefersReducedMotion();
const reducedMotion = useReducedMotion();

return (
<main>
<section
aria-label={t("pages.business.hero.title")}
className="relative overflow-hidden bg-gradient-to-b from-white to-blue-50 py-24 lg:py-32"
className="overflow-hidden bg-gradient-to-b from-white to-blue-50 py-24 lg:py-32"
>
<div className="container mx-auto flex flex-col gap-x-20 gap-y-10 px-4 sm:px-8 lg:grid lg:grid-cols-[1fr_1.8fr]">
<div className="flex flex-col gap-6">
<div className="container relative mx-auto flex flex-col gap-x-20 gap-y-10 px-4 sm:px-8 lg:grid lg:grid-cols-[1fr_1.8fr]">
<motion.div
className="flex flex-col gap-6"
initial={reducedMotion ? "visible" : "hidden"}
viewport={{ amount: 0.3, once: true }}
whileInView="visible"
>
<motion.h1
animate="visible"
className="text-center font-bold text-gray-800 text-h2 lg:pt-0 lg:text-start"
initial={reducedMotion ? "visible" : "hidden"}
style={{ perspective: "1000px" }}
variants={staggerContainer}
>
<AnimatedTitle highlightColor="text-blue-700" text={t("pages.business.hero.title")} />
</motion.h1>
<motion.p
animate="visible"
className="text-center text-body-lg lg:text-left"
custom={0.45}
initial={reducedMotion ? "visible" : "hidden"}
variants={fadeInUp}
>
<motion.p className="text-center text-body-lg lg:text-left" custom={0.45} variants={fadeInUp}>
{t("pages.business.hero.description")}
</motion.p>

<div className="mt-2 flex justify-center gap-x-4 lg:justify-start">
<motion.a
animate="visible"
aria-label={t("pages.business.hero.contactUs")}
className="btn btn-vortex-primary w-1/2 sm:w-1/3 lg:w-1/2 xl:w-2/5"
custom={0.55}
href="mailto:business@vortexfinance.co"
initial={reducedMotion ? "visible" : "hidden"}
rel="noopener noreferrer"
target="_blank"
variants={fadeInUp}
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
>
{t("pages.business.hero.contactUs")} <ArrowTopRightOnSquareIcon aria-hidden="true" className="h-4 w-4" />
</motion.a>
<motion.a
animate="visible"
aria-label={t("pages.business.hero.readDocs")}
className="btn btn-vortex-primary-inverse w-1/2 sm:w-1/3 lg:w-1/2 xl:w-2/5"
custom={0.65}
href="https://api-docs.vortexfinance.co/"
initial={reducedMotion ? "visible" : "hidden"}
rel="noopener noreferrer"
target="_blank"
variants={fadeInUp}
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
>
{t("pages.business.hero.readDocs")} <ArrowTopRightOnSquareIcon aria-hidden="true" className="h-4 w-4" />
</motion.a>
</div>
</div>
</motion.div>

<div
<motion.div
aria-label="Vortex business integration with MetaMask wallet demonstration"
className="mx-auto flex flex-col items-center justify-center pt-2 md:w-4/5 lg:mx-0 xl:w-full"
initial={reducedMotion ? "visible" : "hidden"}
role="img"
viewport={{ amount: 0.2, once: true }}
whileInView="visible"
>
<img
alt="Vortex integration with MetaMask wallet showing EUR cryptocurrency transaction interface"
className="z-10 rounded-lg shadow-custom lg:absolute lg:top-1/6 lg:right-[-230px] lg:w-full lg:max-w-[780px] xl:static"
draggable={false}
src={WidgetSnippetImageEUR}
/>
</div>
<motion.div
className="relative z-10 lg:absolute lg:top-0 lg:right-[-200px] lg:right-[-230px] lg:w-full lg:max-w-[780px] xl:right-0"
variants={heroImageVariants}
>
<img
alt="Vortex integration with MetaMask wallet showing EUR cryptocurrency transaction interface"
className="rounded-lg shadow-2xl"
draggable={false}
src={WidgetSnippetImageEUR}
/>
<motion.div
animate={reducedMotion ? undefined : { opacity: [0.15, 0.25, 0.15], scale: [1, 1.02, 1] }}
className="-z-10 absolute inset-0 translate-y-4 rounded-lg bg-blue-500/20 blur-2xl"
transition={{
duration: 4,
ease: "easeInOut",
repeat: Infinity,
repeatType: "loop"
}}
/>
</motion.div>
</motion.div>
</div>
</section>
</main>
Expand Down
4 changes: 2 additions & 2 deletions apps/frontend/src/sections/individuals/Hero/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const Hero = () => {
<Trans i18nKey="pages.main.hero.subtitle" />
</motion.p>
<div className="mt-2 flex w-full justify-center gap-x-4 lg:justify-start">
<Link className="w-1/3" to="/{-$locale}/widget">
<Link className="w-1/2 sm:w-1/3 lg:w-1/2 xl:w-2/5" to="/{-$locale}/widget">
<motion.div
animate="visible"
aria-label={t("pages.main.hero.buyAndSellCrypto")}
Expand All @@ -49,7 +49,7 @@ export const Hero = () => {
{t("pages.main.hero.buyAndSellCrypto")}
</motion.div>
</Link>
<Link className="w-1/3" to="/{-$locale}/business">
<Link className="w-1/2 sm:w-1/3 lg:w-1/2 xl:w-2/5" to="/{-$locale}/business">
<motion.div
animate="visible"
aria-label={t("pages.main.hero.partnerWithUs")}
Expand Down