Sidebar Navigation System
6 Minuten lesen
By System Documentation December 19, 2024Complete guide to the custom sidebar navigation system with autogeneration, nested menus, page-level navigation, and hiding functionality.
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
Global Sidebar 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
Option | Type | Default | Description |
---|---|---|---|
directory | string | - | Content collection directory to scan |
collapsed | boolean | false | Whether subgroups are collapsed by default |
maxDepth | number | 2 | Maximum 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:
File | Generated 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):
frontmatter.title
frontmatter.page
frontmatter.name
- 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
withbg-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 logicprocessSidebarGroup()
- Configuration processingisPageHidden()
- Hide functionalitycreateSidebarLink()
- URL and label generation
types.ts
- Type definitions:
SidebarLink
- Individual navigation linksSidebarGroup
- Navigation groups/sectionsSidebarConfig
- 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.