Skip to main content

The phone tab bar: top-level destinations, the current one lit.

Phones only, fixed to the bottom of the screen: see it in the phone frame, or on a phone. Leave about 8rem of bottom padding on the page so the last row isn't hidden behind it. Pass isActive when a destination owns more than its own href.

Usage

Example.svelte
<script lang="ts">
	import { page } from "$app/state";
	import BellIcon from "@lucide/svelte/icons/bell";
	import FolderIcon from "@lucide/svelte/icons/folder";
	import HouseIcon from "@lucide/svelte/icons/house";
	import UserRoundIcon from "@lucide/svelte/icons/user-round";

	import BottomNav from "@zedensix/ui/blocks/bottom-nav";

	const items = [
		{ href: "#home", label: "Home", icon: HouseIcon },
		{ href: "#projects", label: "Projects", icon: FolderIcon },
		{ href: "#inbox", label: "Inbox", icon: BellIcon },
		{ href: "#account", label: "Account", icon: UserRoundIcon },
	];
</script>

<p class="text-muted-foreground text-sm">
	Phones only, fixed to the bottom of the screen: see it in the phone frame, or
	on a phone. Leave about 8rem of bottom padding on the page so the last row
	isn't hidden behind it. Pass <code>isActive</code> when a destination owns more
	than its own href.
</p>
<BottomNav
	{items}
	isActive={(_pathname, href) => href === (page.url.hash || "#home")}
/>
+layout.svelte
<script lang="ts">
	import HouseIcon from "@lucide/svelte/icons/house";
	import UserRoundIcon from "@lucide/svelte/icons/user-round";
	import UsersIcon from "@lucide/svelte/icons/users";

	import BottomNav from "@zedensix/ui/blocks/bottom-nav";

	const { children } = $props();

	const items = [
		{ href: "/", label: "Home", icon: HouseIcon },
		{ href: "/groups", label: "Groups", icon: UsersIcon },
		{ href: "/account", label: "Account", icon: UserRoundIcon },
	];
</script>

<main class="min-h-dvh pb-32 md:pb-10">
	{@render children()}
</main>
<BottomNav {items} />