File size: 4,371 Bytes
dda1e85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
class CustomNavbar extends HTMLElement {
  connectedCallback() {
    this.attachShadow({ mode: 'open' });
    this.shadowRoot.innerHTML = `
      <style>
        .nav-link {
          position: relative;
        }
        .nav-link::after {
          content: '';
          position: absolute;
          bottom: -2px;
          left: 0;
          width: 0;
          height: 2px;
          background-color: #7c3aed;
          transition: width 0.3s ease;
        }
        .nav-link:hover::after {
          width: 100%;
        }
      </style>
      <nav class="bg-gray-800 border-b border-gray-700">
        <div class="container mx-auto px-4">
          <div class="flex justify-between items-center py-4">
            <a href="/" class="flex items-center space-x-2">
              <span class="text-2xl font-bold bg-gradient-to-r from-primary-500 to-secondary-500 bg-clip-text text-transparent">ShadowStack</span>
            </a>
            
            <div class="hidden md:flex items-center space-x-8">
              <a href="/" class="nav-link text-gray-300 hover:text-white">Home</a>
              <a href="/services" class="nav-link text-gray-300 hover:text-white">Services</a>
              <a href="/projects" class="nav-link text-gray-300 hover:text-white">Projects</a>
              <a href="/about" class="nav-link text-gray-300 hover:text-white">About</a>
              <a href="/contact" class="nav-link text-gray-300 hover:text-white">Contact</a>
              
              <button id="themeToggle" class="p-2 rounded-full hover:bg-gray-700">
                <i data-feather="moon" class="text-gray-300"></i>
              </button>
            </div>
            
            <button class="md:hidden p-2 rounded-full hover:bg-gray-700" id="mobileMenuButton">
              <i data-feather="menu" class="text-gray-300"></i>
            </button>
          </div>
          
          <!-- Mobile menu -->
          <div class="md:hidden hidden py-4 border-t border-gray-700" id="mobileMenu">
            <div class="flex flex-col space-y-4">
              <a href="/" class="text-gray-300 hover:text-white">Home</a>
              <a href="/services" class="text-gray-300 hover:text-white">Services</a>
              <a href="/projects" class="text-gray-300 hover:text-white">Projects</a>
              <a href="/about" class="text-gray-300 hover:text-white">About</a>
              <a href="/contact" class="text-gray-300 hover:text-white">Contact</a>
              
              <div class="flex justify-between items-center pt-4 border-t border-gray-700">
                <span>Dark Mode</span>
                <button id="mobileThemeToggle" class="p-2 rounded-full hover:bg-gray-700">
                  <i data-feather="moon" class="text-gray-300"></i>
                </button>
              </div>
            </div>
          </div>
        </div>
      </nav>
    `;
    
    // Add event listeners after rendering
    setTimeout(() => {
      const themeToggle = this.shadowRoot.getElementById('themeToggle');
      const mobileThemeToggle = this.shadowRoot.getElementById('mobileThemeToggle');
      const mobileMenuButton = this.shadowRoot.getElementById('mobileMenuButton');
      const mobileMenu = this.shadowRoot.getElementById('mobileMenu');
      
      if (themeToggle) {
        themeToggle.addEventListener('click', this.toggleTheme);
      }
      
      if (mobileThemeToggle) {
        mobileThemeToggle.addEventListener('click', this.toggleTheme);
      }
      
      if (mobileMenuButton) {
        mobileMenuButton.addEventListener('click', () => {
          mobileMenu.classList.toggle('hidden');
          feather.replace();
        });
      }
    }, 0);
  }
  
  toggleTheme() {
    const html = document.documentElement;
    html.classList.toggle('dark');
    
    // Save preference to localStorage
    const isDark = html.classList.contains('dark');
    localStorage.setItem('darkMode', isDark);
    
    // Update icons
    const icons = this.shadowRoot.querySelectorAll('[data-feather]');
    icons.forEach(icon => {
      if (icon.dataset.feather === 'moon' && !isDark) {
        icon.dataset.feather = 'sun';
      } else if (icon.dataset.feather === 'sun' && isDark) {
        icon.dataset.feather = 'moon';
      }
    });
    feather.replace();
  }
}

customElements.define('custom-navbar', CustomNavbar);