Navbar Component
A responsive navigation bar with hamburger menu following Framework7's panel pattern. Features a left-sliding panel with collapsible category sections, smooth animations, and backdrop overlay.
Features
- Hamburger button that opens a left-sliding panel
- Collapsible category sections for organising many navigation items
- Single-item categories render as direct links (e.g., Home)
- Multi-item categories expand/collapse with chevron indicators
- Active page highlighting with blue accent and indicator dot
- Auto-expands the category containing the active page
- Smooth staggered animations for menu items
- Backdrop overlay when panel is open
- Keyboard accessible (Tab navigation, Escape to close, focus trap)
- Sticky positioning with backdrop blur
- Optional Clerk authentication UI integration
Interactive Demo
Click the hamburger menu (β°) in the top-left corner to see the navbar in action. The current navbar you're using is the component! Try expanding different categories and navigating between pages.
Usage (Categorised Navigation)
<script lang="ts">
import Navbar from '$lib/components/Navbar.svelte';
import type { MenuCategory } from '$lib/types';
const menuCategories: MenuCategory[] = [
{
name: 'Home',
icon: 'π ',
items: [{ label: 'Home', href: '/', icon: 'π ', active: true }]
},
{
name: 'Components',
icon: 'π§©',
items: [
{ label: 'CardStack', href: '/cardstack', icon: 'π', active: false },
{ label: 'MagicCard', href: '/magiccard', icon: 'β¨', active: false }
]
}
];
</script>
<Navbar {menuCategories} currentPageTitle="Home" />Props
| Prop | Type | Default | Description |
|---|---|---|---|
menuCategories | MenuCategory[] | [] | Categorised navigation items (recommended) |
menuItems | MenuItem[] | [] | Legacy flat menu items (for backwards compatibility) |
currentPageTitle | string | 'Home' | Title of the current page (for accessibility) |
logoIcon | string | 'β‘' | Logo icon or emoji |
logoText | string | 'Svelte Templates' | Logo text displayed next to icon |
logoHref | string | '/' | URL the logo links to |
isClerkConfigured | boolean | false | Show Clerk auth UI (SignIn/UserButton) or demo badge |
Type Definitions
// Categorised navigation (recommended)
interface MenuCategory {
name: string; // Category display name
icon?: string; // Optional category icon/emoji
items: MenuItem[]; // Items in this category
}
// Individual menu item
interface MenuItem {
label: string; // Display text
href: string; // Link URL
icon?: string; // Optional icon/emoji
active?: boolean; // Whether this is the active page
}Category Behaviour
- Single-item categories: Render as direct links without expand/collapse (e.g., Home)
- Multi-item categories: Show a collapsible header with chevron; click to expand/collapse
- Auto-expand: The category containing the active page automatically expands on load
- Active highlighting: Active items show blue text and a small indicator dot
Implementation Notes
- Panel Scrolling: The panel automatically becomes scrollable if menu items exceed viewport height
- Body Scroll Lock: When panel is open, body scrolling is prevented (coordinated with other components via scrollLock utility)
- Close Triggers: Panel closes when clicking a menu item, clicking overlay, or pressing Escape
- Focus Trap: Tab navigation stays within the panel when open (WCAG 2.4.3)
- Responsive: Panel width adapts based on screen size (280px mobile, 320px tablet+)
- Accessibility: ARIA labels, expanded states, focus management, and reduced motion support
Clerk Integration
When isClerkConfigured is true, the navbar displays Clerk's
authentication UI in the right section:
- Signed out: Shows a "Sign in" button
- Signed in: Shows the UserButton avatar with dropdown menu
- Not configured: Shows a "Demo Mode" badge
Copy the Component
This component is self-contained and can be copied directly into your project. You'll need:
src/lib/components/Navbar.svelte- The component filesrc/lib/types.ts- MenuCategory, MenuItem, and NavbarProps interfacessrc/lib/scrollLock.ts- Scroll lock utility (optional, for coordination)svelte-clerk- Only if using Clerk auth integration