Skip to main content

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.

Reduced motion support
@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> with aria-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 link
  • aria-expanded for collapsible menus
  • aria-selected for 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