Skip to content

Sidebar Component

Version: 0.6.0
Last Updated: January 3, 2026
Location: src/templates/partials/sidebar.html

The sidebar provides the primary navigation structure for Arctyk ITSM. It displays main application sections (Dashboard, Tickets, Projects, Users, Inventory) with active state indication and collapsible sections.


Overview

The sidebar includes:

  • Main navigation menu items
  • Active state highlighting
  • Icon indicators
  • Optional submenu items
  • Responsive collapse on mobile
  • User profile section

Basic Structure

<aside class="sidebar">
  <nav class="navbar-vertical navbar-expand-lg">
    <!-- Sidebar Header -->
    <div class="navbar-brand">
      <a href="/"><strong>Arctyk</strong> ITSM</a>
    </div>

    <!-- Navigation Items -->
    <ul class="navbar-nav">
      <li class="nav-item">
        <a class="nav-link active" href="/dashboard/">
          <i class="bi bi-speedometer2"></i>
          <span>Dashboard</span>
        </a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="/tickets/">
          <i class="bi bi-ticket"></i>
          <span>Tickets</span>
        </a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="/projects/">
          <i class="bi bi-folder"></i>
          <span>Projects</span>
        </a>
      </li>
    </ul>

    <!-- User Section -->
    <div class="sidebar-footer">
      <div class="d-flex align-items-center">
        <img
          src="{{ user.profile.avatar.url }}"
          alt="Avatar"
          class="rounded-circle"
        />
        <div class="ms-2">
          <div class="fw-bold">{{ user.first_name }}</div>
          <small class="text-muted">{{ user.get_role_display }}</small>
        </div>
      </div>
    </div>
  </nav>
</aside>

Active States

Implementation

from django.views.generic import TemplateView

class DashboardView(TemplateView):
    template_name = 'dashboard/dashboard.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['active_nav'] = 'dashboard'
        return context

Template Usage

<li class="nav-item">
    <a class="nav-link {% if active_nav == 'dashboard' %}active{% endif %}" href="{% url 'dashboard' %}">
        <i class="bi bi-speedometer2"></i>
        <span>Dashboard</span>
    </a>
</li>

Custom Template Tag

# src/config/templatetags/nav_tags.py
from django import template

register = template.Library()

@register.simple_tag
def nav_active(request, app_label):
    if request.resolver_match and request.resolver_match.app_name == app_label:
        return 'active'
    return ''

Usage:

<a class="nav-link {% nav_active request 'tickets' %}" href="{% url 'tickets:ticket_list' %}">
    Tickets
</a>

Collapsible Sections

Multi-Level Navigation

<li class="nav-item">
  <a class="nav-link collapsed" href="#submenu" data-bs-toggle="collapse">
    <i class="bi bi-gear"></i>
    <span>Settings</span>
    <i class="bi bi-chevron-down ms-auto"></i>
  </a>
  <div class="collapse" id="submenu">
    <ul class="nav flex-column ms-3">
      <li class="nav-item">
        <a class="nav-link" href="{% url 'config:settings' %}"> General </a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="{% url 'users:user_list' %}"> Users </a>
      </li>
    </ul>
  </div>
</li>

Styling

CSS Classes

.sidebar {
  background-color: #f8f9fa;
  border-right: 1px solid #dee2e6;
  min-height: 100vh;
  padding: 1rem 0;
}

.nav-link {
  color: #495057;
  padding: 0.75rem 1rem;
  transition: all 0.2s ease;
}

.nav-link:hover {
  background-color: #e9ecef;
  color: #212529;
}

.nav-link.active {
  background-color: #0d6efd;
  color: #fff;
  border-left: 3px solid #0d6efd;
}

Custom Styling

// SCSS example
.sidebar {
  $bg-color: #f8f9fa;
  $active-color: #0d6efd;
  $hover-color: #e9ecef;

  background-color: $bg-color;

  .nav-link {
    &:hover {
      background-color: $hover-color;
    }

    &.active {
      background-color: $active-color;
      color: white;
    }
  }
}

Responsive Behavior

Mobile Toggle

<button
  class="navbar-toggler"
  type="button"
  data-bs-toggle="collapse"
  data-bs-target="#navbarVertical"
  aria-controls="navbarVertical"
  aria-expanded="false"
  aria-label="Toggle navigation"
>
  <span class="navbar-toggler-icon"></span>
</button>

<div class="collapse navbar-collapse" id="navbarVertical">
  <!-- Sidebar content -->
</div>

CSS Media Queries

@media (max-width: 768px) {
  .sidebar {
    position: fixed;
    left: 0;
    top: 0;
    height: 100%;
    width: 250px;
    z-index: 1000;
    transform: translateX(-100%);
    transition: transform 0.3s ease;
  }

  .sidebar.show {
    transform: translateX(0);
  }
}

Testing

Unit Tests

from django.test import TestCase, Client
from django.contrib.auth.models import User

class SidebarNavigationTest(TestCase):
    def setUp(self):
        self.user = User.objects.create_user(
            username='testuser',
            password='testpass'
        )
        self.client = Client()

    def test_sidebar_renders(self):
        self.client.login(username='testuser', password='testpass')
        response = self.client.get('/dashboard/')
        self.assertContains(response, 'sidebar')
        self.assertContains(response, 'Dashboard')

    def test_active_state(self):
        self.client.login(username='testuser', password='testpass')
        response = self.client.get('/tickets/')
        self.assertContains(response, 'nav-link active')

Accessibility

<nav class="sidebar" aria-label="Main navigation">
  <ul class="nav">
    <li class="nav-item">
      <a class="nav-link" href="/dashboard/" aria-current="page">
        <i class="bi bi-speedometer2" aria-hidden="true"></i>
        <span>Dashboard</span>
      </a>
    </li>
  </ul>
</nav>

Best Practices

✅ Use semantic HTML (<nav>, <ul>, <li>)
✅ Indicate active page with aria-current="page"
✅ Include icons with aria-hidden="true"
✅ Provide clear visual active state
✅ Support keyboard navigation
✅ Collapse on mobile automatically
❌ Don't use nested links
❌ Don't make sidebar too wide (>250px recommended)
❌ Don't hide navigation without toggle


Resources

Implementation

See Partials Guide for details.