refactor: implement smart navigation for "Get Mycelium Connector" button with smooth scroll utility

- Added smoothScrollToElement utility function in src/utils/scroll.ts with easeInOutQuad animation and configurable duration
- Changed Header and HeaderDark "Get Mycelium Connector" button from static /download link to onClick handler with conditional navigation
- Added handleGetConnectorClick function that scrolls to #download section when on /network page, otherwise navigates to /network
- Change
This commit is contained in:
2025-11-24 14:13:40 +01:00
parent a22a8ddcc9
commit 6b4c7b3329
6 changed files with 95 additions and 16 deletions

View File

@@ -1,5 +1,6 @@
import { useState } from 'react'
import { Link } from 'react-router-dom'
import { Link, useLocation, useNavigate } from 'react-router-dom'
import { smoothScrollToElement } from '@/utils/scroll'
import { Container } from './Container'
import { Button } from './Button'
import pmyceliumLogo from '../images/logos/mainlogo.svg'
@@ -9,6 +10,17 @@ import { Bars3Icon, XMarkIcon } from '@heroicons/react/24/outline'
export function Header() {
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
const navigate = useNavigate()
const location = useLocation()
const handleGetConnectorClick = () => {
if (location.pathname === '/network') {
smoothScrollToElement('download', 1200)
} else {
navigate('/network')
}
}
return (
<header className="bg-white">
<nav className="border-b border-gray-100">
@@ -61,7 +73,7 @@ export function Header() {
>
Deploy Now
</Button>
<Button to="/download" variant="solid" color="cyan">
<Button variant="solid" color="cyan" onClick={handleGetConnectorClick}>
Get Mycelium Connector
</Button>
</div>
@@ -150,7 +162,15 @@ export function Header() {
>
Start Deployment
</Button>
<Button to="/download" variant="solid" color="cyan" className="mt-4 w-full" onClick={() => setMobileMenuOpen(false)}>
<Button
variant="solid"
color="cyan"
className="mt-4 w-full"
onClick={() => {
setMobileMenuOpen(false)
handleGetConnectorClick()
}}
>
Get Mycelium Connector
</Button>
</div>

View File

@@ -1,5 +1,6 @@
import { useState } from 'react'
import { Link } from 'react-router-dom'
import { Link, useLocation, useNavigate } from 'react-router-dom'
import { smoothScrollToElement } from '@/utils/scroll'
import { Container } from './Container'
import { Button } from './Button'
import pmyceliumLogo from '../images/logos/mainlogo.svg'
@@ -9,6 +10,17 @@ import { Bars3Icon, XMarkIcon } from '@heroicons/react/24/outline'
export function HeaderDark() {
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
const navigate = useNavigate()
const location = useLocation()
const handleGetConnectorClick = () => {
if (location.pathname === '/network') {
smoothScrollToElement('download', 1200)
} else {
navigate('/network')
}
}
return (
<header className="bg-[#111111]">
<nav className="border-b border-gray-800">
@@ -61,7 +73,7 @@ export function HeaderDark() {
>
Deploy Now
</Button>
<Button to="/download" variant="solid" color="cyan">
<Button variant="solid" color="cyan" onClick={handleGetConnectorClick}>
Get Mycelium Connector
</Button>
</div>
@@ -150,7 +162,15 @@ export function HeaderDark() {
>
Start Deployment
</Button>
<Button to="/download" variant="solid" color="cyan" className="mt-4 w-full" onClick={() => setMobileMenuOpen(false)}>
<Button
variant="solid"
color="cyan"
className="mt-4 w-full"
onClick={() => {
setMobileMenuOpen(false)
handleGetConnectorClick()
}}
>
Get Mycelium Connector
</Button>
</div>

View File

@@ -6,9 +6,10 @@ import {
useScroll,
useMotionValueEvent,
} from "motion/react";
import { Link } from "react-router-dom";
import { Link, useLocation, useNavigate } from "react-router-dom";
import { cn } from "@/lib/utils";
import { Button } from "../Button";
import { smoothScrollToElement } from "@/utils/scroll";
export const FloatingNav = ({
@@ -23,8 +24,17 @@ export const FloatingNav = ({
className?: string;
}) => {
const { scrollYProgress } = useScroll();
const [visible, setVisible] = useState(true);
const navigate = useNavigate();
const location = useLocation();
const handleGetConnectorClick = () => {
if (location.pathname === "/network") {
smoothScrollToElement("download", 1200);
} else {
navigate("/network");
}
};
useMotionValueEvent(scrollYProgress, "change", (current) => {
if (typeof current === "number") {
@@ -80,7 +90,7 @@ export const FloatingNav = ({
>
<span className="hidden sm:block text-sm">Docs</span>
</a>
<Button to="/download" variant="solid" color="cyan">
<Button variant="solid" color="cyan" onClick={handleGetConnectorClick}>
Get Mycelium Connector
</Button>
</div>

View File

@@ -1,6 +1,7 @@
import { useId } from 'react'
import { Container } from '@/components/Container'
import { Button } from '@/components/Button'
import { smoothScrollToElement } from '@/utils/scroll'
import phoneFrame from '../../images/phoneframe.png'
import { H3, P
, Eyebrow } from "@/components/Texts";
@@ -93,7 +94,11 @@ export function Hero() {
Your Pod is your personal gateway to the network.
</P>
<div className="mt-8 flex flex-wrap gap-x-6 gap-y-4">
<Button to="/download" variant="solid" color="cyan">
<Button
variant="solid"
color="cyan"
onClick={() => smoothScrollToElement('download', 1200)}
>
Get Started
</Button>
<Button

View File

@@ -2,6 +2,7 @@
import { Button } from '@/components/Button'
import { Eyebrow, H3, P } from '@/components/Texts'
import { smoothScrollToElement } from '@/utils/scroll'
export function NodeHero() {
return (
@@ -31,12 +32,7 @@ export function NodeHero() {
<Button
variant="solid"
color="cyan"
onClick={() => {
const el = document.getElementById('node-how-it-works')
if (el) {
el.scrollIntoView({ behavior: 'smooth', block: 'start' })
}
}}
onClick={() => smoothScrollToElement('node-how-it-works', 1200)}
>
How it works
</Button>

28
src/utils/scroll.ts Normal file
View File

@@ -0,0 +1,28 @@
export function smoothScrollToElement(id: string, duration = 800) {
const element = document.getElementById(id)
if (!element) return
const startY = window.scrollY || window.pageYOffset
const targetRect = element.getBoundingClientRect()
const targetY = startY + targetRect.top
const startTime = performance.now()
function easeInOutQuad(t: number) {
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t
}
function step(currentTime: number) {
const elapsed = currentTime - startTime
const progress = Math.min(elapsed / duration, 1)
const eased = easeInOutQuad(progress)
const nextY = startY + (targetY - startY) * eased
window.scrollTo(0, nextY)
if (progress < 1) {
requestAnimationFrame(step)
}
}
requestAnimationFrame(step)
}