Navbar Menu

A navbar menu that animates its children on hover, makes a beautiful bignav

The Navbar will show on top of the page

Installation

Install Dependencies

npm i svelte-motion clsx tailwind-merge

Add util file

src/lib/utils/cn.ts
import { type ClassValue, clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';
        
export function cn(...inputs: ClassValue[]) {
    return twMerge(clsx(inputs));
}

Copy the source code

src/lib/components/ui/NavbarMenu/HoveredLink.svelte
<a class="text-neutral-700 hover:text-black dark:text-neutral-200" {...$$props}>
	<slot />
</a>
src/lib/components/ui/NavbarMenu/MenuItem.svelte
<script lang="ts">
	import { Motion } from 'svelte-motion';

	const transition = {
		type: 'spring',
		mass: 0.5,
		damping: 11.5,
		stiffness: 100,
		restDelta: 0.001,
		restSpeed: 0.001
	};

	export let active: string | null;
	export let item: string;
</script>

<div on:mouseenter={() => (active = item)} on:mouseleave={() => (active = null)} class="relative">
	<Motion let:motion transition={{ duration: 0.3 }}>
		<p use:motion class="cursor-pointer text-black hover:opacity-[0.9] dark:text-white">
			{item}
		</p>
	</Motion>
	{#if active !== null}
		<Motion
			let:motion
			initial={{ opacity: 0, scale: 0.85, y: 0 }}
			animate={{ opacity: 1, scale: 1, y: 0 }}
			{transition}
		>
			<div use:motion>
				{#if active === item}
					<div class="absolute left-1/2 -translate-x-1/2 transform pt-4">
						<Motion let:motion {transition} layoutId="active">
							<div
								use:motion
								class="overflow-hidden rounded-2xl border border-black/[0.2] bg-white shadow-xl backdrop-blur-sm dark:border-white/[0.2] dark:bg-black"
							>
								<Motion let:motion layout>
									<div use:motion class="h-full w-max p-4">
										<slot />
									</div>
								</Motion>
							</div>
						</Motion>
					</div>
				{/if}
			</div>
		</Motion>
	{/if}
</div>
src/lib/components/ui/NavbarMenu/NavbarMenu.svelte
<nav
	class="boder relative flex justify-center space-x-4 rounded-full bg-black px-8 py-6 shadow-input dark:border-white/[0.2]"
>
	<slot />
</nav>
src/lib/components/ui/NavbarMenu/ProductItem.svelte
<script lang="ts">
	export let title: string;
	export let description: string;
	export let href: string;
	export let src: string;
</script>

<a {href} class="flex space-x-2">
	<img {src} width={140} height={70} alt={title} class="flex-shrink-0 rounded-md shadow-2xl" />
	<div>
		<h4 class="mb-1 text-xl font-bold text-black dark:text-white">
			{title}
		</h4>
		<p class="max-w-[10rem] text-sm text-neutral-700 dark:text-neutral-300">
			{description}
		</p>
	</div>
</a>
src/lib/components/ui/NavbarMenu/index.ts
import NavbarMenu from './NavbarMenu.svelte';
import HoveredLink from './HoveredLink.svelte';
import MenuItem from './MenuItem.svelte';
import ProductItem from './ProductItem.svelte';

export { NavbarMenu, HoveredLink, MenuItem, ProductItem };

Props

MenuItem
Prop Type Description
active string | null Set the active menu item
item string The name of the menu item
NavbarMenu
Prop Type Description
active string | null Set the active menu item
ProductItem
Prop Type Description
title string The title of the product
description string The description of the product
href string The link to the product
src string The image source of the product