11---
22import { NAV_ITEMS , type NavItem } from " @/types/site" ;
3- import rawLogoSvg from " @/assets/goude-se-logo.svg?raw" ;
4- import { SWATCH_TO_CSS_VAR } from " @/styles/swatches" ;
5-
6- function mapInkscapeSwatches(svg : string ) {
7- let out = svg ;
8-
9- // Hard override: currentColor is always literal currentColor at runtime
10- const currentColorRe = new RegExp (
11- ' (inkscape:label="currentColor"[\\ s\\ S]*?<stop[^>]+stop-color:)[^;"]+' ,
12- " g"
13- );
14-
15- out = out .replace (currentColorRe , " $1currentColor" );
16-
17- // All other swatches map to CSS vars
18- for (const [label, cssVar] of Object .entries (SWATCH_TO_CSS_VAR )) {
19- if (label === " currentColor" ) continue ;
20-
21- const re = new RegExp (
22- ` (inkscape:label="${label }"[\\ s\\ S]*?<stop[^>]+stop-color:)[^;"]+ ` ,
23- " g"
24- );
25- out = out .replace (re , ` $1var(${cssVar }) ` );
26- }
27-
28- return out ;
29- }
30-
31- const logoSvg = mapInkscapeSwatches (rawLogoSvg );
3+ import SiteLogo from " @/components/SiteLogo.astro" ;
4+ import ThemeToggle from " @/components/ThemeToggle.astro" ;
5+ import ModeToggle from " @/components/ModeToggle.astro" ;
326
337interface Props {
348 current? : string | undefined ;
@@ -45,15 +19,7 @@ const navRight = NAV_ITEMS.filter((item) => item.external);
4519---
4620
4721<header class =" site-header" >
48- <!-- Logo / Home -->
49- <a
50- href =" /"
51- aria-label =" Home"
52- class:list ={ [" logo" , " nav-action" , { selected: current === " " }]}
53- title =" Guard what you give your attention to. It quietly becomes who you are."
54- >
55- <span class =" logo-svg" aria-hidden =" true" set:html ={ logoSvg } />
56- </a >
22+ <SiteLogo isSelected ={ current === " " } />
5723
5824 <!-- Hamburger (mobile only) -->
5925 <button
@@ -117,36 +83,8 @@ const navRight = NAV_ITEMS.filter((item) => item.external);
11783 }
11884 </nav >
11985
120- <button
121- class =" mode-toggle nav-action icon-only"
122- id =" mode-toggle"
123- type =" button"
124- aria-label =" Toggle content detail level"
125- >
126- <i class =" fa-solid fa-water" data-mode-icon =" low" aria-hidden =" true" ></i >
127- <i class =" fa-solid fa-wind" data-mode-icon =" medium" aria-hidden =" true"
128- ></i >
129- <i class =" fa-solid fa-fire" data-mode-icon =" high" aria-hidden =" true" ></i >
130- <span class =" tooltip" data-mode-tooltip =" low" >Low Detail</span >
131- <span class =" tooltip" data-mode-tooltip =" medium" >Medium Detail</span >
132- <span class =" tooltip" data-mode-tooltip =" high" >High Detail</span >
133- </button >
134-
135- <button
136- class =" theme-toggle nav-action icon-only tooltip-right"
137- id =" theme-toggle"
138- type =" button"
139- aria-label =" Toggle theme"
140- >
141- <i class =" fa-regular fa-sun" id =" icon-light" aria-hidden =" true" ></i >
142- <i class =" fa-solid fa-moon" id =" icon-dark" aria-hidden =" true" ></i >
143- <span class =" tooltip" data-theme-tooltip =" light"
144- >The Cleonic Theme of Brother Day</span
145- >
146- <span class =" tooltip" data-theme-tooltip =" dark"
147- >The Cleonic Theme of Brother Dusk</span
148- >
149- </button >
86+ <ModeToggle variant =" desktop" />
87+ <ThemeToggle variant =" desktop" />
15088 </div >
15189
15290 <!-- Mobile pancake menu -->
@@ -179,23 +117,8 @@ const navRight = NAV_ITEMS.filter((item) => item.external);
179117 ))
180118 }
181119
182- <button class =" menu-item menu-action" id =" mode-toggle-menu" type =" button" >
183- <i class =" fa-solid fa-water" data-mode-icon =" low" aria-hidden =" true" ></i >
184- <i class =" fa-solid fa-wind" data-mode-icon =" medium" aria-hidden =" true"
185- ></i >
186- <i class =" fa-solid fa-fire" data-mode-icon =" high" aria-hidden =" true" ></i >
187- <span data-mode-label =" low" >Low Detail</span >
188- <span data-mode-label =" medium" >Medium Detail</span >
189- <span data-mode-label =" high" >High Detail</span >
190- </button >
191-
192- <button class =" menu-item menu-action" id =" theme-toggle-menu" type =" button" >
193- <i class =" fa-regular fa-sun" data-theme-icon =" light" aria-hidden =" true"
194- ></i >
195- <i class =" fa-solid fa-moon" data-theme-icon =" dark" aria-hidden =" true" ></i >
196- <span data-theme-label =" light" >Brother Day</span >
197- <span data-theme-label =" dark" >Brother Dusk</span >
198- </button >
120+ <ModeToggle variant =" menu" />
121+ <ThemeToggle variant =" menu" />
199122 </nav >
200123</header >
201124
@@ -236,82 +159,6 @@ const navRight = NAV_ITEMS.filter((item) => item.external);
236159 opacity: 0.7;
237160 }
238161
239- /* ---------- Unified nav item styling ---------- */
240- .nav-action {
241- display: inline-flex;
242- align-items: center;
243- gap: 0.35rem;
244- padding: 0.25rem 0.6rem;
245- border-radius: 999px;
246- text-decoration: none;
247- color: inherit;
248-
249- font-family: var(--font-ui);
250- font-weight: 700;
251- letter-spacing: 0.08em;
252- white-space: nowrap;
253-
254- background: none;
255- border: none;
256- cursor: pointer;
257-
258- transition:
259- background-color 0.15s ease,
260- color 0.15s ease,
261- opacity 0.15s ease;
262- }
263-
264- .nav-action:hover {
265- opacity: 0.7;
266- }
267-
268- .nav-action i {
269- font-size: 1.1em;
270- }
271-
272- /* CSS animation for rotating icons */
273- @keyframes icon-swap {
274- 0% {
275- opacity: 1;
276- }
277- 40% {
278- opacity: 0;
279- }
280- 60% {
281- opacity: 0;
282- }
283- 100% {
284- opacity: 1;
285- }
286- }
287- .nav-action i[data-icon-rotate].rotating {
288- animation: icon-swap 0.35s ease forwards;
289- }
290-
291- /* Shared selected style */
292- .selected {
293- background: var(--fg);
294- color: var(--bg);
295- }
296-
297- /* ---------- Logo ---------- */
298- .logo {
299- flex-shrink: 0;
300- }
301-
302- .logo-svg {
303- display: flex;
304- align-items: center;
305- height: 1.4em;
306- line-height: 1;
307- }
308-
309- .logo-svg :global(svg) {
310- display: block;
311- height: 100%;
312- width: auto;
313- }
314-
315162 /* Desktop nav containers */
316163 .main-nav {
317164 display: flex;
@@ -329,103 +176,11 @@ const navRight = NAV_ITEMS.filter((item) => item.external);
329176 gap: 0.25rem;
330177 }
331178
332- /* ---------- Icon-only with tooltip ---------- */
333- .icon-only {
334- position: relative;
335- }
336-
337- .icon-only .tooltip {
338- position: absolute;
339- top: 100%;
340- left: 50%;
341- transform: translateX(-50%) translateY(0.25rem);
342- padding: 0.25rem 0.5rem;
343- border-radius: 4px;
344- background: var(--fg);
345- color: var(--bg);
346- font-size: 0.75em;
347- font-weight: 700;
348- letter-spacing: 0.04em;
349- white-space: nowrap;
350- opacity: 0;
351- pointer-events: none;
352- transition:
353- opacity 0.15s ease,
354- transform 0.15s ease;
355- z-index: 100;
356- }
357-
358- .icon-only:hover .tooltip,
359- .icon-only:focus-visible .tooltip {
360- opacity: 1;
361- transform: translateX(-50%) translateY(0.4rem);
362- }
363-
364- /* Right-aligned tooltip for rightmost item to prevent cutoff */
365- .icon-only.tooltip-right .tooltip {
366- left: auto;
367- right: 0;
368- transform: translateX(0) translateY(0.25rem);
369- }
370-
371- .icon-only.tooltip-right:hover .tooltip,
372- .icon-only.tooltip-right:focus-visible .tooltip {
373- transform: translateX(0) translateY(0.4rem);
374- }
375-
376- .external-icon {
377- margin-left: 0.3em;
378- font-size: 0.85em;
379- opacity: 0.7;
380- }
381-
382179 /* Hamburger positioning (mobile top row) */
383180 .menu-toggle {
384181 margin-left: auto;
385182 }
386183
387- /* Theme icons (desktop) */
388- #icon-dark {
389- display: none;
390- }
391- :global([data-theme-dark]) #icon-light {
392- display: none;
393- }
394- :global([data-theme-dark]) #icon-dark {
395- display: inline;
396- }
397-
398- /* Theme tooltips (desktop) */
399- .theme-toggle [data-theme-tooltip="dark"] {
400- display: none;
401- }
402- :global([data-theme-dark]) .theme-toggle [data-theme-tooltip="light"] {
403- display: none;
404- }
405- :global([data-theme-dark]) .theme-toggle [data-theme-tooltip="dark"] {
406- display: block;
407- }
408-
409- /* Mode icons (desktop) */
410- .mode-toggle [data-mode-icon] {
411- display: none;
412- }
413- :global([data-mode="low"]) .mode-toggle [data-mode-icon="low"],
414- :global([data-mode="medium"]) .mode-toggle [data-mode-icon="medium"],
415- :global([data-mode="high"]) .mode-toggle [data-mode-icon="high"] {
416- display: inline;
417- }
418-
419- /* Mode tooltips (desktop) */
420- .mode-toggle [data-mode-tooltip] {
421- display: none;
422- }
423- :global([data-mode="low"]) .mode-toggle [data-mode-tooltip="low"],
424- :global([data-mode="medium"]) .mode-toggle [data-mode-tooltip="medium"],
425- :global([data-mode="high"]) .mode-toggle [data-mode-tooltip="high"] {
426- display: block;
427- }
428-
429184 /* Mobile menu defaults */
430185 .menu-toggle,
431186 .menu-panel {
@@ -500,48 +255,6 @@ const navRight = NAV_ITEMS.filter((item) => item.external);
500255 background: currentColor;
501256 margin: 0.15rem 0.6rem;
502257 }
503-
504- /* Theme icons (mobile menu) */
505- .menu-panel [data-theme-icon="dark"] {
506- display: none;
507- }
508- :global([data-theme-dark]) .menu-panel [data-theme-icon="light"] {
509- display: none;
510- }
511- :global([data-theme-dark]) .menu-panel [data-theme-icon="dark"] {
512- display: inline;
513- }
514-
515- /* Theme labels (mobile menu) */
516- .menu-panel [data-theme-label="dark"] {
517- display: none;
518- }
519- :global([data-theme-dark]) .menu-panel [data-theme-label="light"] {
520- display: none;
521- }
522- :global([data-theme-dark]) .menu-panel [data-theme-label="dark"] {
523- display: inline;
524- }
525-
526- /* Mode icons (mobile menu) */
527- .menu-panel [data-mode-icon] {
528- display: none;
529- }
530- :global([data-mode="low"]) .menu-panel [data-mode-icon="low"],
531- :global([data-mode="medium"]) .menu-panel [data-mode-icon="medium"],
532- :global([data-mode="high"]) .menu-panel [data-mode-icon="high"] {
533- display: inline;
534- }
535-
536- /* Mode labels (mobile menu) */
537- .menu-panel [data-mode-label] {
538- display: none;
539- }
540- :global([data-mode="low"]) .menu-panel [data-mode-label="low"],
541- :global([data-mode="medium"]) .menu-panel [data-mode-label="medium"],
542- :global([data-mode="high"]) .menu-panel [data-mode-label="high"] {
543- display: inline;
544- }
545258 }
546259</style >
547260
0 commit comments