@@ -5,51 +5,132 @@ export function renderHeader() {
55
66 return `
77 <header class="border-b border-[var(--color-border)] bg-[var(--color-bg)] transition-colors duration-300">
8- <nav class="mx-auto max-w-7xl px-4 py-3 sm:px-6 lg:px-8">
9- <div class="flex items-center justify-between">
10- <div class="flex items-center gap-6">
11- <h1 class="text-xl font-bold text-[var(--color-text)]">
12- <a href="#/" class="no-underline text-inherit hover:text-[var(--color-primary)] transition-colors flex items-center gap-2" data-i18n="app.title">
13- <img src="${ import . meta. env . BASE_URL } icon.png" alt="" class="h-8 w-8" aria-hidden="true" />
14- Semantic Anchors
15- </a>
16- </h1>
17- <div class="hidden sm:flex items-center gap-4 text-sm">
18- <a href="#/" class="nav-link text-[var(--color-text-secondary)] hover:text-[var(--color-text)] transition-colors" data-route="/" data-i18n="nav.catalog">${ i18n . t ( 'nav.catalog' ) } </a>
19- <a href="#/about" class="nav-link text-[var(--color-text-secondary)] hover:text-[var(--color-text)] transition-colors" data-route="/about" data-i18n="nav.about">${ i18n . t ( 'nav.about' ) } </a>
20- <a href="#/contributing" class="nav-link text-[var(--color-text-secondary)] hover:text-[var(--color-text)] transition-colors" data-route="/contributing" data-i18n="nav.contributing">${ i18n . t ( 'nav.contributing' ) } </a>
21- </div>
22- </div>
23- <div class="flex items-center gap-3">
24- <button
25- id="lang-toggle"
26- class="rounded-md px-2 py-1 text-sm font-medium text-[var(--color-text-secondary)] hover:text-[var(--color-text)] hover:bg-[var(--color-bg-secondary)] transition-colors"
27- aria-label="Toggle language"
28- >${ langLabel } </button>
29- <button
30- id="theme-toggle"
31- class="rounded-md p-2 text-[var(--color-text-secondary)] hover:text-[var(--color-text)] hover:bg-[var(--color-bg-secondary)] transition-colors"
32- data-i18n-aria="header.themeToggle.dark"
33- aria-label="Switch to dark mode"
34- >
35- <svg id="theme-icon-moon" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
36- <path stroke-linecap="round" stroke-linejoin="round" d="M21.752 15.002A9.718 9.718 0 0118 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 003 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 009.002-5.998z" />
37- </svg>
38- <svg id="theme-icon-sun" class="h-5 w-5 hidden" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
39- <path stroke-linecap="round" stroke-linejoin="round" d="M12 3v2.25m6.364.386l-1.591 1.591M21 12h-2.25m-.386 6.364l-1.591-1.591M12 18.75V21m-4.773-4.227l-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0z" />
40- </svg>
41- </button>
8+ <nav class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-3">
9+ <!-- Desktop: Logo spanning two rows, right side has nav + search -->
10+ <div class="hidden sm:flex items-stretch gap-6">
11+ <!-- Logo left, spanning both rows -->
12+ <div class="flex items-center">
13+ <a href="#/" class="no-underline flex flex-col items-start">
14+ <img src="${ import . meta. env . BASE_URL } logo.png" alt="Semantic Anchors" class="max-h-24" />
15+ <span class="text-xs text-[var(--color-text-secondary)] leading-tight" data-i18n="header.slogan">${ i18n . t ( 'header.slogan' ) } </span>
16+ </a>
4217 <button
43- id="mobile-menu-toggle"
44- class="sm:hidden rounded-md p-2 text-[var(--color-text-secondary)] hover:text-[var(--color-text)] hover:bg-[var(--color-bg-secondary)] transition-colors"
45- aria-label="Toggle menu"
46- aria-expanded="false"
18+ id="onboarding-info-btn"
19+ class="self-start mt-1 rounded-full p-1 text-[var(--color-text-secondary)] hover:text-[var(--color-primary)] hover:bg-[var(--color-bg-secondary)] transition-colors"
20+ data-i18n-aria="onboarding.infoButton"
21+ data-i18n-title="onboarding.infoButton"
22+ aria-label="${ i18n . t ( 'onboarding.infoButton' ) } "
23+ title="${ i18n . t ( 'onboarding.infoButton' ) } "
4724 >
48- <svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
49- <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
25+ <svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
26+ <path stroke-linecap="round" stroke-linejoin="round" d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
27+ <path stroke-linecap="round" stroke-linejoin="round" d="M15.91 11.672a.375.375 0 010 .656l-5.603 3.113a.375.375 0 01-.557-.328V8.887c0-.286.307-.466.557-.327l5.603 3.112z" />
5028 </svg>
5129 </button>
5230 </div>
31+
32+ <!-- Right side: two rows -->
33+ <div class="flex-1 flex flex-col justify-center gap-2">
34+ <!-- Row 1: Navigation + Language/Theme -->
35+ <div class="flex items-center justify-between">
36+ <div class="flex items-center gap-6 text-2xl">
37+ <a href="#/" class="nav-link text-[var(--color-text-secondary)] hover:text-[var(--color-text)] transition-colors" data-route="/" data-i18n="nav.catalog">${ i18n . t ( 'nav.catalog' ) } </a>
38+ <a href="#/about" class="nav-link text-[var(--color-text-secondary)] hover:text-[var(--color-text)] transition-colors" data-route="/about" data-i18n="nav.about">${ i18n . t ( 'nav.about' ) } </a>
39+ <a href="#/contributing" class="nav-link text-[var(--color-text-secondary)] hover:text-[var(--color-text)] transition-colors" data-route="/contributing" data-i18n="nav.contributing">${ i18n . t ( 'nav.contributing' ) } </a>
40+ </div>
41+ <div class="flex items-center gap-3">
42+ <button
43+ id="lang-toggle"
44+ class="rounded-md px-2 py-1 text-sm font-medium text-[var(--color-text-secondary)] hover:text-[var(--color-text)] hover:bg-[var(--color-bg-secondary)] transition-colors"
45+ aria-label="Toggle language"
46+ >${ langLabel } </button>
47+ <button
48+ id="theme-toggle"
49+ class="rounded-md p-2 text-[var(--color-text-secondary)] hover:text-[var(--color-text)] hover:bg-[var(--color-bg-secondary)] transition-colors"
50+ data-i18n-aria="header.themeToggle.dark"
51+ aria-label="Switch to dark mode"
52+ >
53+ <svg id="theme-icon-moon" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
54+ <path stroke-linecap="round" stroke-linejoin="round" d="M21.752 15.002A9.718 9.718 0 0118 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 003 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 009.002-5.998z" />
55+ </svg>
56+ <svg id="theme-icon-sun" class="h-5 w-5 hidden" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
57+ <path stroke-linecap="round" stroke-linejoin="round" d="M12 3v2.25m6.364.386l-1.591 1.591M21 12h-2.25m-.386 6.364l-1.591-1.591M12 18.75V21m-4.773-4.227l-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0z" />
58+ </svg>
59+ </button>
60+ </div>
61+ </div>
62+ <!-- Row 2: Search + Role filter + Anchor count -->
63+ <div class="flex items-center gap-3">
64+ <input
65+ id="header-search-input"
66+ type="search"
67+ data-i18n-placeholder="search.placeholder"
68+ placeholder="${ i18n . t ( 'search.placeholder' ) } "
69+ class="w-48 lg:w-64 rounded-lg border-2 border-[var(--color-border)] bg-[var(--color-bg)] px-4 py-2 text-base text-[var(--color-text)] placeholder-[var(--color-text-secondary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] focus:border-[var(--color-primary)] transition-colors duration-300"
70+ />
71+ <select
72+ id="header-role-filter"
73+ class="rounded-lg border-2 border-[var(--color-border)] bg-[var(--color-bg)] px-4 py-2 text-base text-[var(--color-text)] focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] focus:border-[var(--color-primary)] transition-colors duration-300"
74+ >
75+ <option value="" data-i18n="filter.allRoles">${ i18n . t ( 'filter.allRoles' ) } </option>
76+ </select>
77+ <span id="anchor-count" class="text-sm text-[var(--color-text-secondary)] ml-auto">
78+ <span id="visible-count">0</span> / <span id="total-count">0</span> <span data-i18n="filter.anchors">${ i18n . t ( 'filter.anchors' ) } </span>
79+ </span>
80+ </div>
81+ </div>
82+ </div>
83+
84+ <!-- Mobile: stacked layout -->
85+ <div class="sm:hidden">
86+ <div class="flex items-center justify-between">
87+ <a href="#/" class="no-underline flex flex-col items-start">
88+ <img src="${ import . meta. env . BASE_URL } logo.png" alt="Semantic Anchors" class="max-h-16" />
89+ <span class="text-xs text-[var(--color-text-secondary)] leading-tight" data-i18n="header.slogan">${ i18n . t ( 'header.slogan' ) } </span>
90+ </a>
91+ <div class="flex items-center gap-3">
92+ <button
93+ id="onboarding-info-btn-mobile"
94+ class="rounded-full p-1 text-[var(--color-text-secondary)] hover:text-[var(--color-primary)] hover:bg-[var(--color-bg-secondary)] transition-colors"
95+ data-i18n-aria="onboarding.infoButton"
96+ data-i18n-title="onboarding.infoButton"
97+ aria-label="${ i18n . t ( 'onboarding.infoButton' ) } "
98+ title="${ i18n . t ( 'onboarding.infoButton' ) } "
99+ >
100+ <svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
101+ <path stroke-linecap="round" stroke-linejoin="round" d="M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z" />
102+ </svg>
103+ </button>
104+ <button
105+ id="lang-toggle-mobile"
106+ class="rounded-md px-2 py-1 text-sm font-medium text-[var(--color-text-secondary)] hover:text-[var(--color-text)] hover:bg-[var(--color-bg-secondary)] transition-colors"
107+ aria-label="Toggle language"
108+ >${ langLabel } </button>
109+ <button
110+ id="theme-toggle-mobile"
111+ class="rounded-md p-2 text-[var(--color-text-secondary)] hover:text-[var(--color-text)] hover:bg-[var(--color-bg-secondary)] transition-colors"
112+ data-i18n-aria="header.themeToggle.dark"
113+ aria-label="Switch to dark mode"
114+ >
115+ <svg id="theme-icon-moon-mobile" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
116+ <path stroke-linecap="round" stroke-linejoin="round" d="M21.752 15.002A9.718 9.718 0 0118 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 003 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 009.002-5.998z" />
117+ </svg>
118+ <svg id="theme-icon-sun-mobile" class="h-5 w-5 hidden" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
119+ <path stroke-linecap="round" stroke-linejoin="round" d="M12 3v2.25m6.364.386l-1.591 1.591M21 12h-2.25m-.386 6.364l-1.591-1.591M12 18.75V21m-4.773-4.227l-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0z" />
120+ </svg>
121+ </button>
122+ <button
123+ id="mobile-menu-toggle"
124+ class="rounded-md p-2 text-[var(--color-text-secondary)] hover:text-[var(--color-text)] hover:bg-[var(--color-bg-secondary)] transition-colors"
125+ aria-label="Toggle menu"
126+ aria-expanded="false"
127+ >
128+ <svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
129+ <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
130+ </svg>
131+ </button>
132+ </div>
133+ </div>
53134 </div>
54135
55136 <!-- Mobile menu -->
0 commit comments