Sidebar Navigation
MediumCollapsible sidebar navigation with nested menu items and icons
Live Demo
Basic Sidebar
Simple sidebar with menu items and icons
Main Content Area
This is the main content area next to the sidebar. Click on sidebar items to see navigation in action.
Selected: Components
Resize to see how the component adapts to different screen sizes
📖 Basic Sidebar Overview
Simple sidebar with menu items and icons
💡 Key Features
- • Basic Sidebar functionality with Stimulus controller
- • Navigation bars, sidebars, breadcrumbs, and layout components
- • Responsive design optimized for all screen sizes
- • Accessible markup with proper semantic HTML
- • Modern CSS transitions and interactive effects
- • Enhanced with sidebar capabilities
- • Enhanced with navigation capabilities
- • Enhanced with collapsible capabilities
- • Enhanced with nested capabilities
- • Enhanced with icons capabilities
🏗️ Basic Sidebar HTML Structure
This basic sidebar component uses semantic HTML structure with Stimulus data attributes to connect HTML elements to JavaScript functionality.
📋 Stimulus Data Attributes
data-controller="navigation-sidebars-basic"
Connects this HTML element to the Basic Sidebar Stimulus controller
data-action="click->navigation-sidebars-basic#method"
Defines click events that trigger basic sidebar controller methods
data-navigation-sidebars-basic-target="element"
Identifies elements that the Basic Sidebar controller can reference and manipulate
♿ Accessibility Features
- • Semantic HTML elements provide screen reader context
- • ARIA attributes enhance basic sidebar accessibility
- • Keyboard navigation fully supported
- • Focus management for interactive elements
🎨 Basic Sidebar Tailwind Classes
This basic sidebar component uses Tailwind CSS utility classes with the forest theme color palette for styling and responsive design.
🎨 Navigation & Layout Colors
bg-moss-600
Primary
bg-moss-100
Light
bg-honey-400
Accent
📐 Layout & Spacing
p-4 - Padding for basic sidebar contentmb-4 - Margin bottom between elementsspace-y-2 - Vertical spacing in listsrounded-lg - Rounded corners for modern look📱 Responsive Basic Sidebar Design
- •
sm:- Small screens (640px+) optimized for basic sidebar - •
md:- Medium screens (768px+) enhanced layout - •
lg:- Large screens (1024px+) full functionality - • Mobile-first approach ensures basic sidebar works on all devices
⚡ Basic Sidebar JavaScript Logic
The Basic Sidebar component uses a dedicated Stimulus controller (navigation-sidebars-basic) to handle basic sidebar interactions and manage component state.
🎯 Basic Sidebar Controller Features
Targets
DOM elements the basic sidebar controller can reference and manipulate
Values
Configuration data for basic sidebar behavior passed from HTML
Actions
Methods triggered by basic sidebar user events and interactions
Lifecycle
Setup and cleanup methods for basic sidebar initialization
🔄 Basic Sidebar Event Flow
- 1. User interacts with basic sidebar element (click, hover, input, etc.)
- 2. Stimulus detects event through
data-actionattribute - 3. Basic Sidebar controller method executes with access to targets and values
- 4. Controller updates DOM with new basic sidebar state or visual changes
- 5. CSS transitions provide smooth visual feedback for basic sidebar interactions
<div class="flex h-96 bg-green-50 rounded-lg overflow-hidden" data-controller="sidebars-basic">
<!-- Sidebar -->
<aside class="w-64 bg-white border-r border-green-200" data-sidebars-basic-target="sidebar">
<!-- Sidebar Header -->
<div class="p-4 border-b border-green-200">
<h2 class="text-lg font-semibold text-green-900">Navigation</h2>
</div>
<!-- Navigation Menu -->
<nav class="p-2">
<ul class="space-y-1">
<li>
<a href="#" class="flex items-center px-3 py-2 text-sm font-medium text-green-700 rounded-lg hover:bg-green-100 hover:text-green-900 transition-colors duration-200"
data-action="click->sidebars-basic#navigate">
<svg class="w-5 h-5 mr-3 text-green-500" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="m2.25 12 8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" />
</svg>
Dashboard
</a>
</li>
<li>
<a href="#" class="flex items-center px-3 py-2 text-sm font-medium text-green-700 rounded-lg hover:bg-green-100 hover:text-green-900 transition-colors duration-200 bg-green-100 text-green-900"
data-action="click->sidebars-basic#navigate">
<svg class="w-5 h-5 mr-3 text-green-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M21 7.5l-9-5.25L3 7.5m18 0l-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9" />
</svg>
Components
</a>
</li>
<li>
<a href="#" class="flex items-center px-3 py-2 text-sm font-medium text-green-700 rounded-lg hover:bg-green-100 hover:text-green-900 transition-colors duration-200"
data-action="click->sidebars-basic#navigate">
<svg class="w-5 h-5 mr-3 text-green-500" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-4.5B7.125 8.25 5.25 10.125 5.25 13.5v2.625m14.25-2.625v2.625A2.625 2.625 0 0 1 17.25 18H6.75A2.625 2.625 0 0 1 4.125 15.375V12.75" />
</svg>
Documentation
</a>
</li>
<li>
<a href="#" class="flex items-center px-3 py-2 text-sm font-medium text-green-700 rounded-lg hover:bg-green-100 hover:text-green-900 transition-colors duration-200"
data-action="click->sidebars-basic#navigate">
<svg class="w-5 h-5 mr-3 text-green-500" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.325.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a6.759 6.759 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z" />
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
</svg>
Settings
</a>
</li>
<!-- Section Divider -->
<li class="pt-4">
<div class="border-t border-green-200 mb-4"></div>
<p class="px-3 text-xs font-semibold text-green-500 uppercase tracking-wider">Tools</p>
</li>
<li>
<a href="#" class="flex items-center px-3 py-2 text-sm font-medium text-green-700 rounded-lg hover:bg-green-100 hover:text-green-900 transition-colors duration-200"
data-action="click->sidebars-basic#navigate">
<svg class="w-5 h-5 mr-3 text-green-500" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z" />
</svg>
Search
</a>
</li>
<li>
<a href="#" class="flex items-center px-3 py-2 text-sm font-medium text-green-700 rounded-lg hover:bg-green-100 hover:text-green-900 transition-colors duration-200"
data-action="click->sidebars-basic#navigate">
<svg class="w-5 h-5 mr-3 text-green-500" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 0 1 3 19.875v-6.75ZM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V8.625ZM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V4.125Z" />
</svg>
Analytics
</a>
</li>
</ul>
</nav>
</aside>
<!-- Main Content Area -->
<main class="flex-1 p-6">
<div class="mb-4">
<h1 class="text-xl font-semibold text-green-900">Main Content Area</h1>
<p class="text-green-600 mt-2">This is the main content area next to the sidebar. Click on sidebar items to see navigation in action.</p>
</div>
<div class="bg-white rounded-lg border border-green-200 p-4">
<div class="text-center text-green-500">
<div class="w-16 h-16 mx-auto mb-4 bg-green-100 rounded-full flex items-center justify-center">
<svg class="w-8 h-8 text-green-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M21 7.5l-9-5.25L3 7.5m18 0l-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9" />
</svg>
</div>
<p>Selected: <span class="font-semibold text-green-900" data-sidebars-basic-target="selectedItem">Components</span></p>
</div>
</div>
</main>
</div>
import { Controller } from "@hotwired/stimulus"
// Basic Sidebar Controller
// Handles sidebar navigation with active state management
export default class extends Controller {
static targets = ["sidebar", "selectedItem"]
connect() {
console.log("Basic sidebar connected!")
this.currentActive = null
this.initializeActiveState()
}
initializeActiveState() {
// Find the currently active menu item
const activeLink = this.sidebarTarget.querySelector('a.bg-green-100')
if (activeLink) {
this.currentActive = activeLink
this.updateSelectedDisplay(activeLink)
}
}
navigate(event) {
event.preventDefault()
const clickedLink = event.currentTarget
const itemName = this.extractItemName(clickedLink)
console.log(`Sidebar navigation: ${itemName}`)
// Remove active state from current active item
if (this.currentActive) {
this.deactivateMenuItem(this.currentActive)
}
// Add active state to clicked item
this.activateMenuItem(clickedLink)
this.currentActive = clickedLink
// Update the selected item display
this.updateSelectedDisplay(clickedLink)
// Add click animation
this.addClickAnimation(clickedLink)
}
extractItemName(linkElement) {
// Get the text content, removing any whitespace and icon content
const textContent = linkElement.textContent.trim()
return textContent
}
activateMenuItem(menuItem) {
// Add active styles
menuItem.classList.add('bg-green-100', 'text-green-900')
menuItem.classList.remove('hover:bg-green-100', 'hover:text-green-900')
// Update icon color
const icon = menuItem.querySelector('svg')
if (icon) {
icon.classList.add('text-green-600')
icon.classList.remove('text-green-500')
}
}
deactivateMenuItem(menuItem) {
// Remove active styles
menuItem.classList.remove('bg-green-100', 'text-green-900')
menuItem.classList.add('hover:bg-green-100', 'hover:text-green-900')
// Reset icon color
const icon = menuItem.querySelector('svg')
if (icon) {
icon.classList.add('text-green-500')
icon.classList.remove('text-green-600')
}
}
updateSelectedDisplay(menuItem) {
if (this.hasSelectedItemTarget) {
const itemName = this.extractItemName(menuItem)
this.selectedItemTarget.textContent = itemName
// Add a brief highlight animation
this.selectedItemTarget.classList.add('text-green-600')
setTimeout(() => {
this.selectedItemTarget.classList.remove('text-green-600')
}, 300)
}
}
addClickAnimation(menuItem) {
// Add a brief scale animation
menuItem.classList.add('transform', 'scale-95', 'transition-transform', 'duration-100')
setTimeout(() => {
menuItem.classList.remove('transform', 'scale-95')
menuItem.classList.add('scale-100')
setTimeout(() => {
menuItem.classList.remove('scale-100', 'transition-transform', 'duration-100')
}, 100)
}, 100)
}
// Method to programmatically set active menu item
setActiveItem(itemName) {
const menuItems = this.sidebarTarget.querySelectorAll('a')
menuItems.forEach(item => {
if (this.extractItemName(item).toLowerCase() === itemName.toLowerCase()) {
// Deactivate current active item
if (this.currentActive) {
this.deactivateMenuItem(this.currentActive)
}
// Activate the target item
this.activateMenuItem(item)
this.currentActive = item
this.updateSelectedDisplay(item)
console.log(`Programmatically activated: ${itemName}`)
}
})
}
// Method to get current active item
getCurrentActive() {
return this.currentActive ? this.extractItemName(this.currentActive) : null
}
// Handle keyboard navigation
handleKeydown(event) {
const menuItems = Array.from(this.sidebarTarget.querySelectorAll('a'))
const currentIndex = menuItems.indexOf(this.currentActive)
switch (event.key) {
case 'ArrowUp':
event.preventDefault()
const prevIndex = currentIndex > 0 ? currentIndex - 1 : menuItems.length - 1
this.setActiveByIndex(menuItems, prevIndex)
break
case 'ArrowDown':
event.preventDefault()
const nextIndex = currentIndex < menuItems.length - 1 ? currentIndex + 1 : 0
this.setActiveByIndex(menuItems, nextIndex)
break
case 'Enter':
case ' ':
event.preventDefault()
if (this.currentActive) {
this.navigate({ currentTarget: this.currentActive, preventDefault: () => {} })
}
break
}
}
setActiveByIndex(menuItems, index) {
if (menuItems[index]) {
const targetItem = menuItems[index]
// Deactivate current
if (this.currentActive) {
this.deactivateMenuItem(this.currentActive)
}
// Activate new item
this.activateMenuItem(targetItem)
this.currentActive = targetItem
this.updateSelectedDisplay(targetItem)
// Focus the item
targetItem.focus()
}
}
}
Collapsible Sidebar
Sidebar that can be collapsed to icon-only view
Example demo coming soon
Resize to see how the component adapts to different screen sizes
📖 Collapsible Sidebar Overview
Sidebar that can be collapsed to icon-only view
💡 Key Features
- • Collapsible Sidebar functionality with Stimulus controller
- • Navigation bars, sidebars, breadcrumbs, and layout components
- • Responsive design optimized for all screen sizes
- • Accessible markup with proper semantic HTML
- • Modern CSS transitions and interactive effects
- • Enhanced with sidebar capabilities
- • Enhanced with navigation capabilities
- • Enhanced with collapsible capabilities
- • Enhanced with nested capabilities
- • Enhanced with icons capabilities
🏗️ Collapsible Sidebar HTML Structure
This collapsible sidebar component uses semantic HTML structure with Stimulus data attributes to connect HTML elements to JavaScript functionality.
📋 Stimulus Data Attributes
data-controller="navigation-sidebars-collapsible"
Connects this HTML element to the Collapsible Sidebar Stimulus controller
data-action="click->navigation-sidebars-collapsible#method"
Defines click events that trigger collapsible sidebar controller methods
data-navigation-sidebars-collapsible-target="element"
Identifies elements that the Collapsible Sidebar controller can reference and manipulate
♿ Accessibility Features
- • Semantic HTML elements provide screen reader context
- • ARIA attributes enhance collapsible sidebar accessibility
- • Keyboard navigation fully supported
- • Focus management for interactive elements
🎨 Collapsible Sidebar Tailwind Classes
This collapsible sidebar component uses Tailwind CSS utility classes with the forest theme color palette for styling and responsive design.
🎨 Navigation & Layout Colors
bg-moss-600
Primary
bg-moss-100
Light
bg-honey-400
Accent
📐 Layout & Spacing
p-4 - Padding for collapsible sidebar contentmb-4 - Margin bottom between elementsspace-y-2 - Vertical spacing in listsrounded-lg - Rounded corners for modern look📱 Responsive Collapsible Sidebar Design
- •
sm:- Small screens (640px+) optimized for collapsible sidebar - •
md:- Medium screens (768px+) enhanced layout - •
lg:- Large screens (1024px+) full functionality - • Mobile-first approach ensures collapsible sidebar works on all devices
⚡ Collapsible Sidebar JavaScript Logic
The Collapsible Sidebar component uses a dedicated Stimulus controller (navigation-sidebars-collapsible) to handle collapsible sidebar interactions and manage component state.
🎯 Collapsible Sidebar Controller Features
Targets
DOM elements the collapsible sidebar controller can reference and manipulate
Values
Configuration data for collapsible sidebar behavior passed from HTML
Actions
Methods triggered by collapsible sidebar user events and interactions
Lifecycle
Setup and cleanup methods for collapsible sidebar initialization
🔄 Collapsible Sidebar Event Flow
- 1. User interacts with collapsible sidebar element (click, hover, input, etc.)
- 2. Stimulus detects event through
data-actionattribute - 3. Collapsible Sidebar controller method executes with access to targets and values
- 4. Controller updates DOM with new collapsible sidebar state or visual changes
- 5. CSS transitions provide smooth visual feedback for collapsible sidebar interactions
<!-- ERB template not found for navigation/sidebars/collapsible -->
// Stimulus controller not found for navigation/sidebars/collapsible
Nested Menu Sidebar
Sidebar with nested menu items and sub-navigation
Example demo coming soon
Resize to see how the component adapts to different screen sizes
📖 Nested Menu Sidebar Overview
Sidebar with nested menu items and sub-navigation
💡 Key Features
- • Nested Menu Sidebar functionality with Stimulus controller
- • Navigation bars, sidebars, breadcrumbs, and layout components
- • Responsive design optimized for all screen sizes
- • Accessible markup with proper semantic HTML
- • Modern CSS transitions and interactive effects
- • Enhanced with sidebar capabilities
- • Enhanced with navigation capabilities
- • Enhanced with collapsible capabilities
- • Enhanced with nested capabilities
- • Enhanced with icons capabilities
🏗️ Nested Menu Sidebar HTML Structure
This nested menu sidebar component uses semantic HTML structure with Stimulus data attributes to connect HTML elements to JavaScript functionality.
📋 Stimulus Data Attributes
data-controller="navigation-sidebars-nested"
Connects this HTML element to the Nested Menu Sidebar Stimulus controller
data-action="click->navigation-sidebars-nested#method"
Defines click events that trigger nested menu sidebar controller methods
data-navigation-sidebars-nested-target="element"
Identifies elements that the Nested Menu Sidebar controller can reference and manipulate
♿ Accessibility Features
- • Semantic HTML elements provide screen reader context
- • ARIA attributes enhance nested menu sidebar accessibility
- • Keyboard navigation fully supported
- • Focus management for interactive elements
🎨 Nested Menu Sidebar Tailwind Classes
This nested menu sidebar component uses Tailwind CSS utility classes with the forest theme color palette for styling and responsive design.
🎨 Navigation & Layout Colors
bg-moss-600
Primary
bg-moss-100
Light
bg-honey-400
Accent
📐 Layout & Spacing
p-4 - Padding for nested menu sidebar contentmb-4 - Margin bottom between elementsspace-y-2 - Vertical spacing in listsrounded-lg - Rounded corners for modern look📱 Responsive Nested Menu Sidebar Design
- •
sm:- Small screens (640px+) optimized for nested menu sidebar - •
md:- Medium screens (768px+) enhanced layout - •
lg:- Large screens (1024px+) full functionality - • Mobile-first approach ensures nested menu sidebar works on all devices
⚡ Nested Menu Sidebar JavaScript Logic
The Nested Menu Sidebar component uses a dedicated Stimulus controller (navigation-sidebars-nested) to handle nested menu sidebar interactions and manage component state.
🎯 Nested Menu Sidebar Controller Features
Targets
DOM elements the nested menu sidebar controller can reference and manipulate
Values
Configuration data for nested menu sidebar behavior passed from HTML
Actions
Methods triggered by nested menu sidebar user events and interactions
Lifecycle
Setup and cleanup methods for nested menu sidebar initialization
🔄 Nested Menu Sidebar Event Flow
- 1. User interacts with nested menu sidebar element (click, hover, input, etc.)
- 2. Stimulus detects event through
data-actionattribute - 3. Nested Menu Sidebar controller method executes with access to targets and values
- 4. Controller updates DOM with new nested menu sidebar state or visual changes
- 5. CSS transitions provide smooth visual feedback for nested menu sidebar interactions
<!-- ERB template not found for navigation/sidebars/nested -->
// Stimulus controller not found for navigation/sidebars/nested
Installation & Usage
Copy the ERB template
Copy the ERB code from the template tab above and paste it into your Rails view file.
Add the Stimulus controller
Create the Stimulus controller file in your JavaScript controllers directory.