Navigation
Navigation components provide wayfinding through the interface. Headers orient, sidebars structure, and breadcrumbs trace paths. Each pattern follows Canon motion tokens for consistent, purposeful transitions.
Header Navigation
The primary navigation bar appears at the top of every page. It includes the logo, main links, and optional call-to-action or user menu.
Basic Header
Fixed or static positioning. Mobile menu appears below 1024px breakpoint.
"token attr-name">class="token tag"><script "token attr-name">lang="ts">
import { Navigation } from '@create-something/components';
const links = [
{ label: 'Home', href: '/' },
{ label: 'About', href: '/about' },
{ label: 'Contact', href: '/contact' }
];
"token attr-name">class="token tag"></script>
"token attr-name">class="token tag"><Navigation
"token attr-name">logo="CREATE"
"token attr-name">logoSuffix=".something"
{links}
"token attr-name">currentPath={$page.url.pathname}
/>With CTA and User Menu
Add a call-to-action button and authenticated user dropdown.
"token attr-name">class="token tag"><Navigation
"token attr-name">logo="App"
"token attr-name">links={[
{ label: 'Dashboard', href: '/dashboard' },
{ label: 'Settings', href: '/settings' }
]}
"token attr-name">ctaLabel="Upgrade"
"token attr-name">ctaHref="/pricing"
"token attr-name">user={{ email: '[email protected]', id: '123' }}
"token attr-name">onLogout={() => signOut()}
/>Sidebar Navigation
Sidebar navigation provides structured navigation for documentation, dashboards, and applications with deep hierarchies.
Documentation Sidebar
Grouped sections with expandable items. Active state shows current page.
"token attr-name">class="token tag"><script "token attr-name">lang="ts">
import { page } from '$app/stores';
interface NavSection {
title: string;
items: { label: string; href: string; badge?: string }[];
}
const navigation: NavSection[] = [
{
title: 'Getting Started',
items: [
{ label: 'Introduction', href: '/docs' },
{ label: 'Philosophy', href: '/docs/philosophy' },
{ label: 'Quick Start', href: '/docs/quick-start' }
]
}
];
"token attr-name">class="token tag"></script>
"token attr-name">class="token tag"><aside "token attr-name">class="sidebar">
"token attr-name">class="token tag"><nav "token attr-name">aria-label="Documentation">
{#each navigation as section}
"token attr-name">class="token tag"><div "token attr-name">class="nav-section">
"token attr-name">class="token tag"><h3 "token attr-name">class="nav-section-title">{section.title}"token attr-name">class="token tag"></h3>
"token attr-name">class="token tag"><ul>
{#each section.items as item}
"token attr-name">class="token tag"><li>
"token attr-name">class="token tag"><a
"token attr-name">href={item.href}
class:active={$page.url.pathname === item.href}
>
{item.label}
"token attr-name">class="token tag"></a>
"token attr-name">class="token tag"></li>
{/each}
"token attr-name">class="token tag"></ul>
"token attr-name">class="token tag"></div>
{/each}
"token attr-name">class="token tag"></nav>
"token attr-name">class="token tag"></aside>Breadcrumbs
Breadcrumbs show the user's location within a hierarchical structure. They provide a trail back to the starting point.
Basic Breadcrumbs
The last item represents the current page and is not a link.
"token attr-name">class="token tag"><script "token attr-name">lang="ts">
import { Breadcrumbs } from '@create-something/components';
const items = [
{ label: 'Home', href: '/' },
{ label: 'Components', href: '/components' },
{ label: 'Navigation' } // No href = current page
];
"token attr-name">class="token tag"></script>
"token attr-name">class="token tag"><Breadcrumbs {items} />With Home Icon
Replace the first item's text with a home icon for compact navigation.
"token attr-name">class="token tag"><Breadcrumbs
"token attr-name">items={[
{ label: 'Home', href: '/' },
{ label: 'Products', href: '/products' },
{ label: 'Widget Pro' }
]}
"token attr-name">showHomeIcon={true}
/>Tabs
Tabs organize content into separate views where only one is visible at a time. Full keyboard navigation with arrow keys.
Default Tabs
Underline indicator shows the active tab. Use arrow keys to navigate.
Tab panel content appears here.
"token attr-name">class="token tag"><script "token attr-name">lang="ts">
import { Tabs } from '@create-something/components';
const tabs = [
{ id: 'overview', label: 'Overview' },
{ id: 'features', label: 'Features' },
{ id: 'pricing', label: 'Pricing' }
];
let activeTab = 'overview';
"token attr-name">class="token tag"></script>
"token attr-name">class="token tag"><Tabs {tabs} bind:activeTab>
{#snippet children(tabId)}
{#if tabId === 'overview'}
"token attr-name">class="token tag"><p>Overview content here."token attr-name">class="token tag"></p>
{:else if tabId === 'features'}
"token attr-name">class="token tag"><p>Features content here."token attr-name">class="token tag"></p>
{:else}
"token attr-name">class="token tag"><p>Pricing content here."token attr-name">class="token tag"></p>
{/if}
{/snippet}
"token attr-name">class="token tag"></Tabs>Pills Variant
Pill-shaped tabs with elevated active state.
"token attr-name">class="token tag"><Tabs
"token attr-name">tabs={[
{ id: 'all', label: 'All' },
{ id: 'active', label: 'Active' },
{ id: 'archived', label: 'Archived' }
]}
"token attr-name">variant="pills"
>
<!-- content -->
"token attr-name">class="token tag"></Tabs>Mobile Navigation
Mobile navigation patterns ensure touch-friendly interaction with 44px minimum touch targets.
Mobile Menu Button
Hamburger icon toggles to close icon when open. Slide-down animation respects reduced motion.
"token attr-name">class="token tag"><button
"token attr-name">onclick={toggleMobileMenu}
"token attr-name">class="nav-menu-button"
"token attr-name">aria-label={mobileMenuOpen ? 'Close menu' : 'Open menu'}
"token attr-name">aria-expanded={mobileMenuOpen}
>
{#if mobileMenuOpen}
"token attr-name">class="token tag"><svg "token attr-name">class="w-6 h-6" "token attr-name">fill="none" "token attr-name">stroke="currentColor" "token attr-name">viewBox="0 0 24 24">
"token attr-name">class="token tag"><path "token attr-name">stroke-linecap="round" "token attr-name">stroke-linejoin="round" "token attr-name">stroke-width="2"
"token attr-name">d="M6 18L18 6M6 6l12 12" />
"token attr-name">class="token tag"></svg>
{:else}
"token attr-name">class="token tag"><svg "token attr-name">class="w-6 h-6" "token attr-name">fill="none" "token attr-name">stroke="currentColor" "token attr-name">viewBox="0 0 24 24">
"token attr-name">class="token tag"><path "token attr-name">stroke-linecap="round" "token attr-name">stroke-linejoin="round" "token attr-name">stroke-width="2"
"token attr-name">d="M4 6h16M4 12h16M4 18h16" />
"token attr-name">class="token tag"></svg>
{/if}
"token attr-name">class="token tag"></button>
"token attr-name">class="token tag"><style>
.nav-menu-button {
width: 44px;
height: 44px; /* WCAG minimum touch target */
display: flex;
align-items: center;
justify-content: center;
}
"token attr-name">class="token tag"></style>Drawer Navigation
Full-height drawer slides in from the left with overlay backdrop.
"token attr-name">class="token tag"><script "token attr-name">lang="ts">
import { Drawer } from '@create-something/components';
let open = $state(false);
"token attr-name">class="token tag"></script>
"token attr-name">class="token tag"><Drawer bind:open "token attr-name">position="left">
"token attr-name">class="token tag"><nav "token attr-name">class="drawer-nav">
"token attr-name">class="token tag"><a "token attr-name">href="/">Home"token attr-name">class="token tag"></a>
"token attr-name">class="token tag"><a "token attr-name">href="/about">About"token attr-name">class="token tag"></a>
"token attr-name">class="token tag"><a "token attr-name">href="/contact">Contact"token attr-name">class="token tag"></a>
"token attr-name">class="token tag"></nav>
"token attr-name">class="token tag"></Drawer>
"token attr-name">class="token tag"><style>
.drawer-nav {
display: flex;
flex-direction: column;
gap: var(--space-md);
padding: var(--space-lg);
}
"token attr-name">class="token tag"></style>Motion Tokens
All navigation transitions use Canon motion tokens for consistent, purposeful animation.
Link Hover
transition: color var(--duration-micro) var(--ease-standard); 200ms color transition for link hover states.
Mobile Menu
animation: slide-down 0.2s cubic-bezier(0.4, 0, 0.2, 1); Slide-down animation when menu opens.
Sidebar Transform
transition: transform var(--duration-standard) var(--ease-standard); 300ms transform for sidebar show/hide.
@media (prefers-reduced-motion: reduce) {
.animate-slide-down {
animation: none;
}
.sidebar {
transition: none;
}
.nav-link {
transition: none;
}
}Accessibility
Navigation components follow WAI-ARIA patterns for keyboard and screen reader accessibility.
Semantic Markup
- Use
<nav>witharia-label - Breadcrumbs use
<ol>for ordered lists - Tabs use proper
role="tablist"pattern
Keyboard Navigation
- Tab key navigates between interactive elements
- Arrow keys navigate within tab groups
- Escape key closes mobile menus
ARIA States
aria-current="page"for current linkaria-expandedfor collapsible menusaria-selectedfor tab selection
Focus Management
- Visible focus indicators with
--color-focus - Focus trap within mobile drawers
- Skip-to-content link at page top
Token Reference
Navigation components use these Canon design tokens.
--duration-micro 200ms - Link hover transitions--duration-standard 300ms - Menu and sidebar transitions--ease-standard cubic-bezier(0.4, 0.0, 0.2, 1) - All navigation motion--color-fg-secondary rgba(255, 255, 255, 0.8) - Default link color--color-fg-muted rgba(255, 255, 255, 0.46) - Inactive link color--color-hover rgba(255, 255, 255, 0.05) - Hover background--color-active rgba(255, 255, 255, 0.1) - Active background--color-focus rgba(255, 255, 255, 0.5) - Focus ring color--z-fixed 50 - Fixed header z-index--z-modal 100 - Mobile overlay z-index