Sidebar Navigation System

6 min leer

By System Documentation December 19, 2024

Complete guide to the custom sidebar navigation system with autogeneration, nested menus, page-level navigation, and hiding functionality.

#documentation #sidebar #navigation #astro

Sidebar Navigation System

A comprehensive, lightweight sidebar navigation system built for Astro with support for autogeneration from content collections, nested menus, page-level navigation, and visibility controls.

Quick Start

1. Basic Setup

The sidebar is automatically configured in astro.config.mjs:

export default defineConfig({
  // ... other config
  sidebar: [
    {
      label: 'Resources',
      autogenerate: { directory: 'resources' },
    }
  ],
  // ... rest of config
});

2. Using in Layouts

Apply the sidebar to any layout:

---
import Sidebar from '@/components/sidebar/Sidebar.astro';
import { getSidebarConfig } from '@/config/sidebar';

const sidebarConfig = getSidebarConfig();
const pageNavigation = frontmatter.sidebar ? [frontmatter.sidebar].flat() : [];
---

<div class="layout-with-sidebar">
  <div class="sidebar-wrapper">
    <Sidebar 
      config={sidebarConfig} 
      currentUrl={Astro.url} 
      headings={headings} 
      pageNavigation={pageNavigation}
    />
  </div>
  <main class="main-content-with-sidebar">
    <slot />
  </main>
</div>

Configuration

Configure the main navigation structure in astro.config.mjs:

sidebar: [
  // Manual navigation group
  {
    label: 'Guides',
    items: [
      { label: 'Getting Started', slug: 'guides/getting-started' },
      { label: 'Advanced Topics', slug: 'guides/advanced' },
    ],
  },
  
  // Autogenerated navigation group
  {
    label: 'Resources',
    autogenerate: { 
      directory: 'resources',
      collapsed: false,  // Subgroups open by default
      maxDepth: 2       // Maximum nesting levels
    },
  },
]

Autogeneration Options

OptionTypeDefaultDescription
directorystring-Content collection directory to scan
collapsedbooleanfalseWhether subgroups are collapsed by default
maxDepthnumber2Maximum nesting levels (1-2 supported)

Features

1. Multilingual Support (i18n)

The sidebar now supports internationalization using the same i18n system as other components:

Features:

  • All sidebar labels are translatable
  • Uses the existing Translate component
  • Supports translation keys in configuration
  • Automatically adapts to current locale

Usage:

// Configuration with i18n keys
export const sidebarConfig = [
  {
    label: 'sidebar.guides',  // Translation key instead of hardcoded text
    items: [
      { label: 'sidebar.example-guide', slug: 'guides/example' },
    ],
  },
  {
    label: 'sidebar.resources',
    autogenerate: { directory: 'resources' },
  },
];

Components automatically wrap labels with <Translate>:

  • Group titles: <Translate>{group.label}</Translate>
  • Link labels: <Translate>{item.label}</Translate>
  • Table of Contents: <Translate>{title}</Translate>

TOC Translation Examples:

<!-- Using default translatable title -->
<TableOfContentsWithScroll headings={headings} />

<!-- Using custom translation key -->
<TableOfContentsWithScroll 
  headings={headings} 
  title="toc.custom-title" 
/>

<!-- Using hardcoded text (still works but not recommended) -->
<TableOfContentsWithScroll 
  headings={headings} 
  title="Page Contents" 
/>

2. Autogenerated Navigation

Automatically creates navigation from your content collections:

src/content/resources/
├── getting-started.md      → /resources/getting-started/
├── advanced/
│   ├── deployment.md       → /resources/advanced/deployment/
│   └── optimization.md     → /resources/advanced/optimization/
└── tutorials/
    ├── basic.mdx          → /resources/tutorials/basic/
    └── advanced.mdx       → /resources/tutorials/advanced/

Result in sidebar:

  • Resources
    • Getting Started
    • Advanced (collapsible group)
      • Deployment
      • Optimization
    • Tutorials (collapsible group)
      • Basic
      • Advanced

2. Page-Level Navigation

Add custom navigation to specific pages via frontmatter:

---
title: My Page
sidebar:
  label: "Page Navigation"
  items:
    - label: "Quick Start"
      href: "#quick-start"
    - label: "Configuration"
      href: "#configuration"
    - label: "Examples"
      href: "#examples"
---

Features:

  • Appears first in the sidebar
  • Visually distinguished with blue styling
  • Perfect for page-specific jump links
  • Supports internal anchors and external URLs
  • Page-level labels are also translatable when using translation keys

3. Hide Pages from Navigation

Hide specific pages from autogenerated navigation:

---
title: Hidden Page
sidebar:
  hide: true
---

Use cases:

  • Draft pages under development
  • Landing pages accessed via specific links
  • Admin or utility pages
  • Pages not ready for public navigation

4. Table of Contents (TOC)

Automatic TOC generation with scroll-based active highlighting:

Features:

  • Auto-generated from markdown headings
  • Scroll-based active state indication
  • Nested heading support
  • Sticky positioning
  • Mobile responsive
  • Fully translatable title using translation keys
  • Default title: "toc.on-this-page" (translatable)
  • Title wrapped with <Translate>{title}</Translate>

5. Nested Directory Support

Supports up to 2 levels of nesting:

content/
├── page1.md                 → Level 1 (root)
└── category/
    ├── page2.md            → Level 2 (in collapsible group)
    └── subcategory/
        └── page3.md        → Level 2 (flattened with category)

Notes:

  • Maximum 2 levels supported for UI clarity
  • Subdirectories become collapsible groups
  • Files deeper than 2 levels are flattened to level 2
  • Directory names are automatically formatted and translatable

6. Responsive Design

Desktop (768px+):

  • Sticky positioning
  • 288px width (w-72)
  • Always visible

Mobile:

  • Slide-out overlay
  • Backdrop blur effect
  • Touch-friendly toggle button

Examples

Example 1: Basic Autogenerated Section

// astro.config.mjs
{
  label: 'Documentation',
  autogenerate: { directory: 'docs' }
}

Example 2: Collapsed Subgroups by Default

// astro.config.mjs
{
  label: 'API Reference',
  autogenerate: { 
    directory: 'api',
    collapsed: true,
    maxDepth: 2
  }
}

Example 3: Mixed Manual and Auto Navigation

// astro.config.mjs
sidebar: [
  // Manual section
  {
    label: 'Getting Started',
    items: [
      { label: 'Installation', slug: 'install' },
      { label: 'Quick Start', slug: 'quickstart' },
    ]
  },
  // Auto section
  {
    label: 'Guides',
    autogenerate: { directory: 'guides' }
  }
]

Example 4: Page with Custom Navigation

---
title: Complete Tutorial
description: Step-by-step guide
sidebar:
  label: "Tutorial Steps"
  items:
    - label: "1. Setup"
      href: "#setup"
    - label: "2. Configuration"
      href: "#configuration"
    - label: "3. Deployment"
      href: "#deployment"
    - label: "4. Troubleshooting"
      href: "#troubleshooting"
---

# Complete Tutorial

Your tutorial content here...

Example 5: Hidden Development Page

---
title: Work in Progress
description: This page is still being written
sidebar:
  hide: true
---

# Work in Progress

This page won't appear in navigation but is accessible via direct URL.

File Naming and URL Generation

Clean URLs

The system automatically generates clean URLs:

FileGenerated URL
getting-started.md/resources/getting-started/
api/endpoints.mdx/resources/api/endpoints/
tutorials/basic.md/resources/tutorials/basic/

Label Generation Priority

For link labels, the system checks (in order):

  1. frontmatter.title
  2. frontmatter.page
  3. frontmatter.name
  4. Filename (as fallback)
---
title: "This Will Be Used"  # ← Highest priority
page: "This Is Ignored"
name: "This Is Also Ignored"
---

Styling and Theming

Light Theme Design

The sidebar uses a light theme optimized for readability:

Colors:

  • Background: bg-gray-50
  • Borders: border-gray-200
  • Text: text-gray-800
  • Active links: text-blue-700 with bg-blue-50
  • Hover states: hover:bg-gray-100

Page-Level Navigation Styling

Page-level navigation has distinct styling:

.page-level {
  border-bottom: 2px solid #e5e7eb;
  padding-bottom: 1rem;
  margin-bottom: 1.5rem;
}

.page-level .sidebar-link {
  color: #1e40af;
  font-weight: 500;
  background-color: #f0f9ff;
  border-radius: 0.375rem;
}

Customization

All styles are in src/styles/global.css under the @layer components section. Key classes:

  • .sidebar-wrapper - Main container
  • .sidebar-nav - Navigation wrapper
  • .sidebar-group - Group containers
  • .sidebar-link - Individual links
  • .sidebar-link.current - Active page styling

Troubleshooting

Common Issues

1. Pages not appearing in sidebar

  • Check if the content collection exists
  • Verify the directory name matches the config
  • Ensure frontmatter doesn’t have sidebar.hide: true

2. URLs not working

  • Verify the content collection is properly configured in src/content/config.ts
  • Check that the dynamic route file exists (e.g., [...slug].astro)
  • Ensure clean URLs are being generated correctly

3. Sidebar not showing

  • Check that the layout includes the sidebar components
  • Verify the getSidebarConfig() function is imported
  • Ensure proper CSS classes are applied

4. Mobile sidebar not working

  • Check that MobileToggle component is included
  • Verify JavaScript for mobile toggle is working
  • Ensure proper z-index stacking

5. TOC not highlighting correctly

  • Verify headings have proper id attributes
  • Check that the IntersectionObserver script is loaded
  • Ensure headings are being passed to the component

Debug Tips

1. Check console for errors:

// Browser dev tools console
console.log('Sidebar config:', sidebarConfig);

2. Verify content collection:

// In Astro component
const entries = await getCollection('resources');
console.log('Found entries:', entries.length);

3. Check CSS loading:

/* Add temporary styles to verify CSS is loading */
.sidebar-wrapper {
  border: 2px solid red !important;
}

Architecture

File Structure

src/
├── components/sidebar/
│   ├── Sidebar.astro              # Main sidebar component
│   ├── SidebarGroup.astro         # Group/section component
│   ├── MobileToggle.astro         # Mobile hamburger menu
│   ├── TableOfContents.astro      # TOC component
│   ├── TableOfContentsWithScroll.astro # TOC with scroll tracking
│   ├── types.ts                   # TypeScript interfaces
│   └── utils.ts                   # Core logic and utilities
├── config/
│   └── sidebar.ts                 # Configuration management
├── layouts/
│   └── Resources.astro            # Example layout using sidebar
└── styles/
    └── global.css                 # All sidebar styles

Key Components

utils.ts - Core functionality:

  • generateLinksFromDirectoryWithConfig() - Autogeneration logic
  • processSidebarGroup() - Configuration processing
  • isPageHidden() - Hide functionality
  • createSidebarLink() - URL and label generation

types.ts - Type definitions:

  • SidebarLink - Individual navigation links
  • SidebarGroup - Navigation groups/sections
  • SidebarConfig - Overall configuration structure

Sidebar.astro - Main component orchestrating:

  • Global navigation rendering
  • Page-level navigation integration
  • Table of contents inclusion
  • Mobile responsiveness

Performance Considerations

Build Time

  • Autogeneration happens at build time
  • Content collections are cached by Astro
  • Minimal impact on build performance

Runtime

  • Static navigation structure
  • No client-side JavaScript for basic navigation
  • TOC scroll tracking uses efficient IntersectionObserver
  • Mobile toggle uses minimal JavaScript

Memory Usage

  • Sidebar configuration loaded once per page
  • Content collection entries processed efficiently
  • No large client-side bundles

Future Enhancements

Planned Features

  • Search functionality within sidebar
  • Collapsible state persistence
  • Custom ordering for autogenerated items
  • Multi-language support
  • Custom icons for navigation items

Extension Points

  • Custom link processors in utils.ts
  • Additional styling hooks in global.css
  • Plugin system for custom autogeneration logic
  • Integration with external navigation systems

This documentation covers version 1.0 of the sidebar system. For updates and additional features, check the latest codebase.