aboutsummaryrefslogtreecommitdiffstats
path: root/website/src/lib/components/header/navigation-bar.svelte
diff options
context:
space:
mode:
Diffstat (limited to 'website/src/lib/components/header/navigation-bar.svelte')
-rw-r--r--website/src/lib/components/header/navigation-bar.svelte179
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>