Developer Docs
Quick reference guides with props tables, usage examples, and best practices for rapid development
NavigationDrawer
Slide-out navigation drawer with user profile, quick actions, statistics, and trending content
NavigationDrawer
Slide-out navigation drawer that appears from the left side. Features organized navigation sections, quick links, and auto-close on navigation. Typically triggered by hamburger menu in NavigationHeader.
Try It Live
Click the button below to see the NavigationDrawer in action:
Key Features
✓Slides in from left with smooth animation
✓Dark overlay with auto-close on click
✓Organized navigation sections (Learn, Build, Resources)
✓Quick links grid for common pages
✓Auto-closes after navigation
✓Mobile-optimized 280px width
✓Z-index hierarchy (overlay 998, drawer 999)
✓Scrollable content area
🔧 Props Reference
NavigationDrawer accepts a single prop for controlling visibility:
| Prop | Type | Default | Description |
|---|---|---|---|
| isOpen | van.State<boolean> | required | VanJS state controlling drawer visibility |
Returns: [overlay, drawer] - Array of two sibling elements (spread in parent)
💻 Basic Usage
Simple example showing how to integrate NavigationDrawer with a toggle button:
import { NavigationDrawer } from 'shared-components/layout/NavigationDrawer.js';
// Create state
const isDrawerOpen = van.state(false);
// Render drawer (spread the array!)
div(
// Hamburger button
button({
onclick: () => isDrawerOpen.val = true
}, '☰ Menu'),
// Drawer (returns [overlay, drawer])
...NavigationDrawer({
isOpen: isDrawerOpen
}),
// Main content
main(/* content */)
)🔗 Integration with NavigationHeader
NavigationDrawer shares state with NavigationHeader for seamless integration:
import { NavigationHeader } from 'shared-components/layout/NavigationHeader.js';
// NavigationHeader already includes NavigationDrawer!
div(
// Spread NavigationHeader (which returns [drawer, header])
...NavigationHeader({
navLinks,
dsktpNavLinks
}),
main(/* content */)
)
// The hamburger button in NavigationHeader controls the drawer
// No need to create separate isOpen state📁 Navigation Structure
NavigationDrawer has a built-in navigation structure with 3 sections:
1. Learn Section
✓Overview
✓Authentication
✓Database
✓Routing
✓Framework Docs
2. Build Section
✓Components Hub
✓Forms
✓Buttons
✓Display
✓Feedback
✓Layout
✓Navigation
✓Playground
3. Resources Section
✓API Docs
✓Colors
✓Icons
✓Developer Tools
⚡ Quick Links
Top section shows 3 quick access links in a grid:
✓Home → /
✓Showcase → /showcase
✓Playground → /playground
🎨 Customization
To customize the navigation structure, edit the component source:
// In NavigationDrawer.js (lines 40-77)
const navigationSections = {
mySection: {
title: 'My Section',
icon: 'oj-ux-ico-folder',
items: [
{ label: 'Item 1', path: '/item1', icon: 'oj-ux-ico-page' },
{ label: 'Item 2', path: '/item2', icon: 'oj-ux-ico-page' }
]
}
};
// Quick links customization (lines 79-83)
const quickLinks = [
{ label: 'Dashboard', icon: 'oj-ux-ico-home', path: '/dashboard' },
{ label: 'Services', icon: 'oj-ux-ico-grid', path: '/services' }
];🚪 Auto-Close Behavior
NavigationDrawer automatically closes in several scenarios:
Drawer Closes On:
✓Clicking any navigation item
✓Clicking overlay (dark background)
✓Clicking X button in NavigationHeader
✓Programmatic state change (isOpen.val = false)
Implementation
const handleClose = () => {
isOpen.val = false;
};
// Navigation items call handleClose + navigate
button({
onclick: () => {
handleClose();
navigateTo(item.path);
}
}, item.label)✨ Animation Details
NavigationDrawer uses CSS transitions for smooth slide and fade animations:
Slide Animation
// Drawer slides from left
// Closed: -translate-x-full (off-screen left)
// Open: translate-x-0 (visible)
// Overlay fades in/out
// Closed: opacity-0 pointer-events-none
// Open: opacity-100
// Both use transition-transform/transition-opacityZ-Index Hierarchy
// Overlay: z-[998] (below drawer, above content)
// Drawer: z-[999] (topmost)
// Header: z-50 (below both)
// This ensures proper stacking:
// 1. Page content (z-0)
// 2. Header (z-50)
// 3. Drawer overlay (z-998)
// 4. Drawer (z-999)✅ Best Practices
Follow these guidelines for optimal NavigationDrawer implementation:
✓ Do This
✓Spread the returned array
✓Use with NavigationHeader
✓Organize navigation into sections
✓Keep items short and scannable
✓Use icons for visual scanning
✓Auto-close on navigation
✓Test scroll on long lists
✗ Avoid This
✗Nest the returned array
✗Forget to spread in parent
✗Have too many sections (>4)
✗Use long navigation labels
✗Forget mobile testing
✗Modify z-index without hierarchy
✗Remove auto-close behavior
🎮 Programmatic Control
Control NavigationDrawer programmatically by updating the state:
const isDrawerOpen = van.state(false);
// Open drawer
isDrawerOpen.val = true;
// Close drawer
isDrawerOpen.val = false;
// Toggle drawer
isDrawerOpen.val = !isDrawerOpen.val;
// React to state changes
van.derive(() => {
console.log('Drawer is', isDrawerOpen.val ? 'open' : 'closed');
});📦 Complete Example
Full implementation example with hamburger button and navigation drawer:
import van from 'vanjs-core';
import { NavigationDrawer } from 'shared-components/layout/NavigationDrawer.js';
import { Button } from 'shared-components/forms/Button.js';
const { div, main } = van.tags;
export const App = () => {
// Create drawer state
const isDrawerOpen = van.state(false);
return div(
// Header with menu button
div(
{ class: 'bg-white border-b border-mist p-4 flex items-center gap-4' },
// Hamburger button
Button({
class: 'vwfcolor-sky ghost',
onclick: () => isDrawerOpen.val = true
}, '☰'),
div({ class: 'text-xl font-bold' }, 'My App')
),
// Navigation drawer (spread array!)
...NavigationDrawer({
isOpen: isDrawerOpen
}),
// Main content
main(
{ class: 'container mx-auto p-4' },
'Page content here'
)
);
};🔧 Common Issues & Solutions
Solutions to common NavigationDrawer integration problems:
Issue: Drawer not appearing
// Check these:
// 1. Are you spreading the array?
...NavigationDrawer({ isOpen }) // ✓ Correct
// 2. Is isOpen actually changing?
console.log('isOpen:', isOpen.val);
// 3. Is it behind other elements?
// Check z-index of parent elementsIssue: Overlay not closing drawer
// Overlay already has handleClose on click
// If not working, check for:
// 1. Elements with higher z-index blocking overlay
// 2. CSS pointer-events: none on overlayIssue: Navigation not working
// Ensure navigateTo is imported and working:
import { navigateTo } from 'utils/fileBasedRouterV2.js';
// Test navigation separately:
navigateTo('/test-page');Explore More Components
Browse other component categories