diff options
Diffstat (limited to 'website/src/lib/components/header/navigation-bar.svelte')
| -rw-r--r-- | website/src/lib/components/header/navigation-bar.svelte | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/website/src/lib/components/header/navigation-bar.svelte b/website/src/lib/components/header/navigation-bar.svelte new file mode 100644 index 0000000..3c3da94 --- /dev/null +++ b/website/src/lib/components/header/navigation-bar.svelte @@ -0,0 +1,179 @@ +<script lang="ts"> + import { onMount } from 'svelte'; + import { Menu, X, Search, ShoppingBag } from 'lucide-svelte'; + import { fade, slide } from 'svelte/transition'; + import { quintOut } from 'svelte/easing'; + import Logo from '../logo.svelte'; + + let mobileOpen = $state(false); + let searchOpen = $state(false); + let scrolled = $state(false); + let query = $state(''); + let user = $state(null); + + const navLinks = [ + { label: 'Discover', href: '/discover' }, + { label: 'Federations', href: '/federations' }, + { label: 'Stores', href: '/stores' }, + { label: 'Developers', href: '/developers' }, + ]; + + const handleScroll = () => { + scrolled = window.scrollY > 10; + }; + + onMount(() => { + window.addEventListener('scroll', handleScroll); + return () => window.removeEventListener('scroll', handleScroll); + }); + + function openSearch() { + searchOpen = true; + mobileOpen = false; // Close mobile menu if search opens + } + + function closeSearch() { + searchOpen = false; + query = ''; + } +</script> + +<nav + class="fixed top-0 left-0 z-50 w-full text-white transition-all duration-300 + {scrolled ? 'bg-black/80 shadow-sm backdrop-blur-xl' : 'bg-black backdrop-blur-lg'}" +> + <div class="mx-auto max-w-7xl px-4"> + <div class="relative flex h-14 items-center justify-between"> + <a + href="/" + class="z-10 flex items-center text-[17px] font-semibold tracking-tight transition-opacity duration-200 {searchOpen + ? 'max-md:hidden' + : ''}" + class:opacity-0={searchOpen} + > + <Logo class="h-8 w-8" /><span>sellers</span><span class="text-rose-600">hut</span> + </a> + + <div class="relative flex flex-1 justify-center px-2"> + {#if !searchOpen} + <div + class="hidden items-center gap-8 text-[13px] font-medium md:flex" + transition:fade={{ duration: 200 }} + > + {#each navLinks as link} + <a + href={link.href} + class="text-neutral-200 transition-colors hover:text-white" + > + {link.label} + </a> + {/each} + </div> + {:else} + <div + class="absolute inset-0 z-20 flex items-center" + in:slide={{ duration: 250, easing: quintOut }} + out:fade={{ duration: 150 }} + > + <div class="relative mx-auto flex w-full max-w-2xl items-center gap-2"> + <div class="relative flex-1"> + <Search + size={16} + class="absolute top-1/2 left-4 -translate-y-1/2 text-neutral-500" + /> + <input + bind:value={query} + placeholder="search sellershut.com" + class="h-10 w-full rounded-lg bg-neutral-100 pr-4 pl-10 text-sm text-black outline-none focus:border-transparent focus:ring-2 focus:ring-rose-500 focus:outline-none" + /> + </div> + <button + onclick={closeSearch} + class="p-2 text-neutral-100 hover:text-white" + > + <X size={20} /> + </button> + </div> + </div> + {/if} + </div> + + <div class="z-10 flex items-center gap-3 md:gap-6"> + {#if !searchOpen} + <button + onclick={openSearch} + class="p-2 text-neutral-200 transition-colors hover:text-white" + aria-label="Search" + > + <Search size={18} /> + </button> + + <button class="p-2 text-neutral-200 hover:text-white" aria-label="Cart"> + <ShoppingBag size={18} /> + </button> + + <div class="hidden sm:block"> + {#if user} + <img + src="/avatar.jpg" + alt="User" + class="h-7 w-7 rounded-full ring-1 ring-black/10" + /> + {:else} + <a + href="/login" + class="inline-flex h-9 items-center justify-center rounded-md bg-rose-600 px-4 py-1 text-sm font-medium tracking-tight text-white shadow-sm transition-all duration-200 hover:bg-rose-700 active:scale-[0.98]" + > + Sign in + </a> + {/if} + </div> + + <button + class="p-2 text-neutral-200 md:hidden" + onclick={() => (mobileOpen = !mobileOpen)} + > + {#if mobileOpen} + <X size={22} /> + {:else} + <Menu size={22} /> + {/if} + </button> + {/if} + </div> + </div> + </div> + + {#if mobileOpen} + <div + class="fixed inset-x-0 top-14 z-40 bg-black text-white md:hidden" + transition:slide={{ duration: 250, easing: quintOut }} + > + <div class="h-screen space-y-8 border-t border-white/10 px-6 py-8"> + <div class="flex flex-col gap-6"> + {#each navLinks as link} + <a + href={link.href} + class="text-2xl font-semibold tracking-tight text-white/90 transition-colors hover:text-rose-500" + onclick={() => (mobileOpen = false)} + > + {link.label} + </a> + {/each} + </div> + + <div class="h-px bg-white/10"></div> + + <a + href="/login" + class="block text-lg font-medium text-rose-500" + onclick={() => (mobileOpen = false)} + > + {user ? 'My Profile' : 'Sign in / Register'} + </a> + </div> + </div> + {/if} +</nav> + +<div class="h-14"></div> |
