feat(NavBar, hero Image): added new navbar animations + mobile version, fixed hero image on mobile

This commit is contained in:
Vrezh Fedora 2025-02-06 11:04:05 +01:00
parent 5d6b9bb8af
commit 97d617f22c
8 changed files with 241 additions and 18 deletions

View file

@ -1,13 +1,13 @@
export function getTitleAnimation(delay = 0) { export function getTitleAnimation(delay = 0, duration = 0.3, once = true) {
return { return {
initial: { opacity: 0, translateY: 20, filter: 'blur(4px)' }, initial: { opacity: 0, translateY: 20, filter: 'blur(4px)' },
whileInView: { whileInView: {
opacity: 1, opacity: 1,
translateY: 0, translateY: 0,
filter: 'blur(0px)', filter: 'blur(0px)',
transition: { duration: 0.3, delay }, transition: { duration, delay },
}, },
viewport: { once: true }, viewport: { once: once },
} }
} }

View file

@ -63,11 +63,15 @@ function getHeroTitleAnimation() {
</div> </div>
</div> </div>
</header> </header>
<motion.span client:load {...getHeroTitleAnimation()}> <motion.span
className="flex max-w-full px-8 lg:max-w-none lg:flex-none lg:px-0"
client:load
{...getHeroTitleAnimation()}
>
<Image <Image
src={myImage} src={myImage}
alt="Zen browser" alt="Zen browser"
class="mx-4 lg:mx-auto lg:w-3/4 mb-24 shadow-md rounded-3xl dark:opacity-80" class="mb-24 rounded-3xl shadow-md lg:mx-auto lg:w-3/4 dark:opacity-80"
loading="eager" loading="eager"
/> />
</motion.span> </motion.span>

View file

@ -1,4 +1,9 @@
---
const { class: className } = Astro.props
---
<svg <svg
class={className}
width="32" width="32"
height="32" height="32"
viewBox="0 0 64 64" viewBox="0 0 64 64"

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Before After
Before After

View file

@ -0,0 +1,155 @@
import React, { useState } from 'react'
import MyLogo from './Mylogo'
import { Menu } from 'lucide-react'
const MobileNavbar: React.FC = () => {
const [isMenuOpen, setMenuOpen] = useState(false)
const menuTransformClass = isMenuOpen ? 'translate-x-0' : 'translate-x-full'
return (
<div className="lg:hidden">
{/* Mobile Header */}
<header className="flex items-center justify-between bg-paper px-4 py-2 dark:shadow">
<a className="flex items-center gap-2" href="/">
<MyLogo className="h-8 w-8 text-coral" />
<span className="text-lg font-bold">zen browser</span>
</a>
<button
id="burger-btn"
className="p-2 text-dark"
aria-label="Open menu"
onClick={() => setMenuOpen(true)}
>
<Menu className="h-6 w-6" />
</button>
</header>
{/* Mobile Slide Menu (slides in from the right) */}
<div
id="mobile-menu"
className={`fixed inset-y-0 right-0 z-40 w-64 transform bg-paper shadow-lg transition-transform duration-300 ${menuTransformClass}`}
>
<div className="flex items-center justify-between border-b border-dark px-4 py-2">
<div className="text-lg font-bold">Menu</div>
<button
id="close-btn"
className="p-2 text-dark"
aria-label="Close menu"
onClick={() => setMenuOpen(false)}
>
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</button>
</div>
<nav className="px-4 py-2">
<ul className="space-y-4">
{/* Getting Started Links */}
<li>
<div className="mb-2 font-bold">Getting Started</div>
<ul className="ml-4 space-y-2">
<li>
<a href="/mods" className="block text-dark hover:text-coral">
Zen Mods
</a>
</li>
<li>
<a
href="/release-notes"
className="block text-dark hover:text-coral"
>
Release Notes
</a>
</li>
<li>
<a
href="https://discord.gg/zen-browser"
className="block text-dark hover:text-coral"
>
Discord
</a>
</li>
</ul>
</li>
{/* Useful Links */}
<li>
<div className="mb-2 font-bold">Useful Links</div>
<ul className="ml-4 space-y-2">
<li>
<a
href="/donate"
className="block text-dark hover:text-coral"
>
Donate
</a>
</li>
<li>
<a href="/about" className="block text-dark hover:text-coral">
About Us 🌟
</a>
</li>
<li>
<a
href="https://docs.zen-browser.app"
className="block text-dark hover:text-coral"
>
Documentation
</a>
</li>
<li>
<a
href="https://github.com/zen-browser"
target="_blank"
className="block text-dark hover:text-coral"
>
GitHub
</a>
</li>
</ul>
</li>
{/* Extra Links */}
<li>
<a
href="/mods"
className="block font-bold text-dark hover:text-coral"
>
Mods
</a>
</li>
<li>
<a
href="/download"
className="block font-bold text-dark hover:text-coral"
>
Download
</a>
</li>
</ul>
</nav>
</div>
{/* Overlay for Mobile Menu */}
{isMenuOpen && (
<div
id="overlay"
className="fixed inset-0 z-30 bg-black opacity-50"
onClick={() => setMenuOpen(false)}
/>
)}
</div>
)
}
export default MobileNavbar

37
src/components/Mylogo.tsx Normal file
View file

@ -0,0 +1,37 @@
import React from 'react'
interface MyLogoProps {
className?: string
}
const MyLogo: React.FC<MyLogoProps> = ({ className }) => (
<svg
className={className}
width="32"
height="32"
viewBox="0 0 64 64"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M32 44.3077C38.7974 44.3077 44.3077 38.7974 44.3077 32C44.3077 25.2027 38.7974 19.6923 32 19.6923C25.2027 19.6923 19.6923 25.2027 19.6923 32C19.6923 38.7974 25.2027 44.3077 32 44.3077ZM41.8462 32C41.8462 37.4379 37.4379 41.8462 32 41.8462C26.5621 41.8462 22.1538 37.4379 22.1538 32C22.1538 26.5621 26.5621 22.1538 32 22.1538C37.4379 22.1538 41.8462 26.5621 41.8462 32Z"
fill="currentColor"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M53.3333 32C53.3333 43.7821 43.7821 53.3333 32 53.3333C20.2179 53.3333 10.6667 43.7821 10.6667 32C10.6667 20.2179 20.2179 10.6667 32 10.6667C43.7821 10.6667 53.3333 20.2179 53.3333 32ZM32 49.2308C41.5163 49.2308 49.2308 41.5163 49.2308 32C49.2308 22.4837 41.5163 14.7692 32 14.7692C22.4837 14.7692 14.7692 22.4837 14.7692 32C14.7692 41.5163 22.4837 49.2308 32 49.2308Z"
fill="currentColor"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M64 32C64 49.6731 49.6731 64 32 64C14.3269 64 0 49.6731 0 32C0 14.3269 14.3269 0 32 0C49.6731 0 64 14.3269 64 32ZM32 58.2564C46.501 58.2564 58.2564 46.501 58.2564 32C58.2564 17.499 46.501 5.74359 32 5.74359C17.499 5.74359 5.74359 17.499 5.74359 32C5.74359 46.501 17.499 58.2564 32 58.2564Z"
fill="currentColor"
/>
</svg>
)
export default MyLogo

View file

@ -1,4 +1,5 @@
--- ---
import { motion } from 'motion/react'
import Title from '../components/Title.astro' import Title from '../components/Title.astro'
import Description from '../components/Description.astro' import Description from '../components/Description.astro'
import Button from '../components/Button.astro' import Button from '../components/Button.astro'
@ -13,21 +14,22 @@ import {
import { ArrowRight, ChevronDown, Download, DownloadCloud } from 'lucide-astro' import { ArrowRight, ChevronDown, Download, DownloadCloud } from 'lucide-astro'
import Logo from './Logo.astro' import Logo from './Logo.astro'
import { ThemeSwitch } from 'free-astro-components' import { ThemeSwitch } from 'free-astro-components'
import { getTitleAnimation } from '../animations.ts'
--- ---
<nav <nav
id="nav-bar" id="nav-bar"
class="relative z-20 flex w-full items-center justify-between lg:px-6 lg:pt-3" class="relative z-20 hidden w-full items-center justify-between lg:flex lg:px-6 lg:pt-3"
> >
<Astronav> <Astronav>
<MenuItems <MenuItems
class="relative mx-auto flex w-full gap-2 bg-paper p-2 lg:w-3/4 lg:min-w-fit" class="relative mx-auto flex w-full justify-between gap-2 bg-paper p-2 lg:w-3/4 lg:min-w-fit"
> >
<a class="flex items-center gap-2 text-lg font-bold" href="/"> <a class="flex items-center gap-2 text-lg font-bold" href="/">
<Logo class="text-dark" /> <Logo class="text-coral" />
<span class="hidden lg:block">zen browser</span> <span class="hidden lg:block">zen browser</span>
</a> </a>
<div class="flex mx-auto"> <div class="flex">
<div class="flex items-center gap-6 text-xs sm:text-sm lg:text-base"> <div class="flex items-center gap-6 text-xs sm:text-sm lg:text-base">
<Dropdown class="group"> <Dropdown class="group">
<button class="flex items-center"> <button class="flex items-center">
@ -37,8 +39,10 @@ import { ThemeSwitch } from 'free-astro-components'
/> />
</button> </button>
<DropdownItems> <DropdownItems>
<div <motion.div
class="navbar-dropdown left-0 right-1/4 top-16 w-full lg:w-fit" className="navbar-dropdown"
{...getTitleAnimation(0, 0.3, false)}
client:load
> >
<a class="dropdown-item bg-dark/5 row-span-2" href="/mods"> <a class="dropdown-item bg-dark/5 row-span-2" href="/mods">
<div class="dropdown-title">Zen Mods</div> <div class="dropdown-title">Zen Mods</div>
@ -62,7 +66,7 @@ import { ThemeSwitch } from 'free-astro-components'
Join our community on Discord to chat with other Zen users! Join our community on Discord to chat with other Zen users!
</div> </div>
</a> </a>
</div> </motion.div>
</DropdownItems> </DropdownItems>
</Dropdown> </Dropdown>
<Dropdown class="group"> <Dropdown class="group">
@ -73,8 +77,10 @@ import { ThemeSwitch } from 'free-astro-components'
/> />
</button> </button>
<DropdownItems> <DropdownItems>
<div <motion.div
class="navbar-dropdown left-0 top-16 w-full !grid-cols-1 gap-1 lg:left-1/3 lg:right-1/4 lg:w-fit" className="navbar-dropdown !grid-cols-1 gap-1"
{...getTitleAnimation(0, 0.3, false)}
client:load
> >
<a class="dropdown-item" href="/donate"> <a class="dropdown-item" href="/donate">
<div class="dropdown-title">Donate ❤️</div> <div class="dropdown-title">Donate ❤️</div>
@ -104,7 +110,7 @@ import { ThemeSwitch } from 'free-astro-components'
Contribute to the development of Zen Browser on GitHub. Contribute to the development of Zen Browser on GitHub.
</div> </div>
</a> </a>
</div> </motion.div>
</DropdownItems> </DropdownItems>
</Dropdown> </Dropdown>
<a class="hidden items-center lg:block" href="/mods"> <a class="hidden items-center lg:block" href="/mods">
@ -112,7 +118,7 @@ import { ThemeSwitch } from 'free-astro-components'
</a> </a>
</div> </div>
</div> </div>
<div class="flex gap-2 lg:gap-4 items-center"> <div class="flex items-center gap-2 lg:gap-4">
<div id="theme-switcher" class="ml-auto md:mr-2"> <div id="theme-switcher" class="ml-auto md:mr-2">
<ThemeSwitch label="" class="px-1 py-2" /> <ThemeSwitch label="" class="px-1 py-2" />
</div> </div>
@ -129,10 +135,10 @@ import { ThemeSwitch } from 'free-astro-components'
</MenuItems> </MenuItems>
</Astronav> </Astronav>
</nav> </nav>
<style> <style>
.navbar-dropdown { .navbar-dropdown {
@apply absolute grid grid-cols-2 gap-2 rounded-lg border-2 border-dark bg-paper p-3 shadow-sm; @apply absolute left-1/2 mt-2 grid !-translate-x-1/2 !transform grid-cols-2 gap-2 rounded-lg border-2 border-dark bg-paper p-3 shadow-sm;
& .dropdown-item { & .dropdown-item {
@apply flex cursor-pointer select-none flex-col gap-2 rounded-lg p-4 transition-colors duration-200; @apply flex cursor-pointer select-none flex-col gap-2 rounded-lg p-4 transition-colors duration-200;

View file

@ -8,6 +8,7 @@ const { title, isHome } = Astro.props
import '@fontsource/bricolage-grotesque/400.css' import '@fontsource/bricolage-grotesque/400.css'
import NavBar from '../components/NavBar.astro' import NavBar from '../components/NavBar.astro'
import Footer from '../components/Footer.astro' import Footer from '../components/Footer.astro'
import MobileNavBar from '../components/MobileNavBar'
--- ---
<script is:inline data-cfasync="false"> <script is:inline data-cfasync="false">
@ -85,6 +86,7 @@ import Footer from '../components/Footer.astro'
class="overflow-x-hidden bg-paper font-['bricolage-grotesque'] text-dark" class="overflow-x-hidden bg-paper font-['bricolage-grotesque'] text-dark"
> >
<NavBar /> <NavBar />
<MobileNavBar client:load />
<slot /> <slot />
<Footer /> <Footer />
</body> </body>

View file

@ -16,6 +16,20 @@ export default {
'zen-blue': '#6287f5', 'zen-blue': '#6287f5',
'zen-green': '#63f78b', 'zen-green': '#63f78b',
}, },
keyframes: {
fadeIn: {
'0%': { opacity: 0 },
'100%': { opacity: 1 },
},
breathe: {
'50%': { transform: 'scale(1.2)' },
'0%, 100%': { transform: 'scale(1)' },
},
},
animation: {
fadeIn: 'fadeIn 2s ease-in-out',
breathe: 'breathe 5s ease-in-out infinite',
},
}, },
}, },
plugins: [], plugins: [],