@gsa-tts/graymatter-ui 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/images/ai-icons/chevron-up-down.svg +4 -0
- package/dist/graymatter-ui.js +4082 -0
- package/dist/graymatter-ui.umd.cjs +40 -0
- package/index.ts +1 -0
- package/package.json +7 -5
- package/src/components/Button.svelte +11 -23
- package/src/components/Button.webcomponent.svelte +44 -0
- package/src/components/DesktopHeader.svelte +30 -18
- package/src/components/DesktopHeader.webcomponent.svelte +17 -0
- package/src/components/DesktopSideNav.svelte +327 -57
- package/src/components/DesktopSideNav.webcomponent.svelte +19 -0
- package/src/components/Logo.webcomponent.svelte +26 -0
- package/src/components/MobileBottomNav.svelte +57 -11
- package/src/components/MobileBottomNav.webcomponent.svelte +14 -0
- package/src/components/MobileSideMenu.svelte +69 -14
- package/src/components/MobileSideMenu.webcomponent.svelte +11 -0
- package/src/components/MobileTopNav.svelte +136 -2
- package/src/components/MobileTopNav.webcomponent.svelte +14 -0
- package/src/index.ts +16 -0
- package/src/layouts/GlobalAppLayout.astro +24 -15
- package/src/stores/navigationStore.ts +0 -15
- package/src/styles/components/globalAppLayout.css +9 -12
- package/src/styles/components/globalAppNav.css +30 -483
- package/src/utils/getAppUrls.ts +29 -0
- package/src/utils/index.ts +1 -0
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
* - If not provided, the navigation will default to expanded/open on SSR.
|
|
7
7
|
*/
|
|
8
8
|
import { onMount } from 'svelte';
|
|
9
|
-
import Logo from './Logo.svelte';
|
|
10
9
|
import {
|
|
11
10
|
isExpanded,
|
|
12
11
|
selectedItem,
|
|
@@ -19,6 +18,8 @@
|
|
|
19
18
|
import ConsoleIcon from './icons/ConsoleIcon.svelte';
|
|
20
19
|
import ApiIcon from './icons/ApiIcon.svelte';
|
|
21
20
|
import MenuIcon from './icons/MenuIcon.svelte';
|
|
21
|
+
import { getAppUrls } from '../utils/getAppUrls';
|
|
22
|
+
const urls = getAppUrls();
|
|
22
23
|
|
|
23
24
|
const { ssrSelectedItem = undefined, onNavToggle = undefined, onNavItemClick = undefined, onProfileClick = undefined, children } = $props();
|
|
24
25
|
|
|
@@ -75,22 +76,17 @@
|
|
|
75
76
|
const handleLayoutTransition = (event: Event) => {
|
|
76
77
|
const customEvent = event as CustomEvent;
|
|
77
78
|
const { isMobile } = customEvent.detail;
|
|
78
|
-
console.log('[DesktopSideNav] Layout transition detected:', { isMobile });
|
|
79
79
|
|
|
80
80
|
if (isMobile) {
|
|
81
81
|
// Switching to mobile: close navigation
|
|
82
|
-
console.log('[DesktopSideNav] Closing navigation for mobile');
|
|
83
82
|
navigationStore.setExpanded(false);
|
|
84
83
|
} else {
|
|
85
84
|
// Switching to desktop: open navigation if on non-discover page
|
|
86
85
|
const currentItem = $selectedItem;
|
|
87
|
-
console.log('[DesktopSideNav] Desktop transition - current item:', currentItem);
|
|
88
86
|
|
|
89
87
|
if (currentItem && currentItem !== 'discover') {
|
|
90
|
-
console.log('[DesktopSideNav] Opening navigation for desktop (non-discover page)');
|
|
91
88
|
navigationStore.setExpanded(true);
|
|
92
89
|
} else {
|
|
93
|
-
console.log('[DesktopSideNav] Keeping navigation closed for desktop (discover page or no selection)');
|
|
94
90
|
navigationStore.setExpanded(false);
|
|
95
91
|
}
|
|
96
92
|
}
|
|
@@ -110,13 +106,10 @@
|
|
|
110
106
|
onNavToggle?.({ expanded: $isExpanded });
|
|
111
107
|
}
|
|
112
108
|
|
|
113
|
-
function handleNavItemClick(item: NavigationItem) {
|
|
114
|
-
console.log('[DesktopSideNav] handleNavItemClick called for:', item, 'at:', Date.now());
|
|
115
|
-
|
|
109
|
+
function handleNavItemClick(item: NavigationItem) {
|
|
116
110
|
// Set navigation flag immediately to prevent header restoration
|
|
117
111
|
if (item !== 'discover' && typeof window !== 'undefined') {
|
|
118
112
|
sessionStorage.setItem('navigatingToMainNav', 'true');
|
|
119
|
-
console.log('[DesktopSideNav] Set navigation flag for:', item, 'at:', Date.now());
|
|
120
113
|
}
|
|
121
114
|
|
|
122
115
|
navigationStore.setSelectedItem(item);
|
|
@@ -139,7 +132,6 @@
|
|
|
139
132
|
const firstSection = mainContent.querySelector('h2[id], h3[id], h4[id], h5[id], h6[id]');
|
|
140
133
|
if (firstSection && firstSection.textContent) {
|
|
141
134
|
const firstSectionTitle = firstSection.textContent.trim();
|
|
142
|
-
console.log('[DesktopSideNav] Setting default header for', item, ':', firstSectionTitle);
|
|
143
135
|
selectedSubNavItemTitle.set(firstSectionTitle);
|
|
144
136
|
if (typeof window !== 'undefined') {
|
|
145
137
|
sessionStorage.setItem('subNav-selectedTitle', JSON.stringify(firstSectionTitle));
|
|
@@ -185,9 +177,10 @@
|
|
|
185
177
|
class="side-nav-container"
|
|
186
178
|
class:expanded={sideNavExpanded()}
|
|
187
179
|
bind:this={navContainer}
|
|
180
|
+
part="side-nav-container"
|
|
188
181
|
>
|
|
189
182
|
<div class="nav-content">
|
|
190
|
-
<div class="nav-main">
|
|
183
|
+
<div class="nav-main" part="nav-main">
|
|
191
184
|
<div class="menu-section">
|
|
192
185
|
<button
|
|
193
186
|
class="menu-button"
|
|
@@ -211,9 +204,9 @@
|
|
|
211
204
|
</button>
|
|
212
205
|
</div>
|
|
213
206
|
|
|
214
|
-
<div class="nav-items">
|
|
207
|
+
<div class="nav-items" part="nav-items">
|
|
215
208
|
<a
|
|
216
|
-
href=
|
|
209
|
+
href={urls.discover}
|
|
217
210
|
class="nav-item discover-item"
|
|
218
211
|
class:selected={isNavSelected('discover')}
|
|
219
212
|
class:hovered={isNavHovered('discover')}
|
|
@@ -232,7 +225,7 @@
|
|
|
232
225
|
<span class="nav-text">Discover</span>
|
|
233
226
|
</a>
|
|
234
227
|
<a
|
|
235
|
-
href=
|
|
228
|
+
href={urls.chat}
|
|
236
229
|
class="nav-item chat-item"
|
|
237
230
|
class:selected={isNavSelected('chat')}
|
|
238
231
|
class:hovered={isNavHovered('chat')}
|
|
@@ -252,7 +245,7 @@
|
|
|
252
245
|
</a>
|
|
253
246
|
|
|
254
247
|
<a
|
|
255
|
-
href=
|
|
248
|
+
href={urls.console}
|
|
256
249
|
class="nav-item console-item"
|
|
257
250
|
class:selected={isNavSelected('console')}
|
|
258
251
|
class:hovered={isNavHovered('console')}
|
|
@@ -272,7 +265,7 @@
|
|
|
272
265
|
</a>
|
|
273
266
|
|
|
274
267
|
<a
|
|
275
|
-
href=
|
|
268
|
+
href={urls.api}
|
|
276
269
|
class="nav-item api-item"
|
|
277
270
|
class:selected={isNavSelected('api')}
|
|
278
271
|
class:hovered={isNavHovered('api')}
|
|
@@ -293,7 +286,7 @@
|
|
|
293
286
|
</div>
|
|
294
287
|
</div>
|
|
295
288
|
|
|
296
|
-
<div class="nav-footer">
|
|
289
|
+
<div class="nav-footer" part="nav-footer">
|
|
297
290
|
<button
|
|
298
291
|
class="user-profile-button"
|
|
299
292
|
tabindex="0"
|
|
@@ -306,7 +299,7 @@
|
|
|
306
299
|
}}
|
|
307
300
|
>
|
|
308
301
|
<div class="user-profile-container">
|
|
309
|
-
<div class="user-profile-icon">
|
|
302
|
+
<div class="user-profile-icon" part="user-profile-icon">
|
|
310
303
|
<span class="user-initials">ZW</span>
|
|
311
304
|
</div>
|
|
312
305
|
</div>
|
|
@@ -314,62 +307,339 @@
|
|
|
314
307
|
</div>
|
|
315
308
|
</div>
|
|
316
309
|
|
|
317
|
-
<div class="expanded-content drawer-anim" class:open={sideNavExpanded()}>
|
|
318
|
-
|
|
319
|
-
<div class="
|
|
320
|
-
<div class="logo-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
</div>
|
|
325
|
-
</div>
|
|
326
|
-
</div>
|
|
310
|
+
<div class="expanded-content drawer-anim" class:open={sideNavExpanded()} part="expanded-content">
|
|
311
|
+
{#if sideNavExpanded()}
|
|
312
|
+
<div class="drawer-content" part="drawer-content">
|
|
313
|
+
<div class="logo-placeholder"></div>
|
|
314
|
+
<nav aria-label="Sub navigation">
|
|
315
|
+
{@render children?.()}
|
|
316
|
+
</nav>
|
|
327
317
|
</div>
|
|
328
|
-
|
|
329
|
-
{@render children?.()}
|
|
330
|
-
</nav>
|
|
331
|
-
</div>
|
|
318
|
+
{/if}
|
|
332
319
|
</div>
|
|
333
320
|
</div>
|
|
334
321
|
|
|
335
322
|
<style>
|
|
336
323
|
.expanded-content.drawer-anim {
|
|
337
|
-
width: 0;
|
|
338
|
-
min-width: 0;
|
|
339
324
|
max-width: 0;
|
|
340
325
|
overflow: hidden;
|
|
341
|
-
opacity: 0.7;
|
|
342
326
|
pointer-events: none;
|
|
343
|
-
transition:
|
|
344
|
-
|
|
345
|
-
min-width 0.4s cubic-bezier(.4,0,.2,1),
|
|
346
|
-
max-width 0.4s cubic-bezier(.4,0,.2,1),
|
|
347
|
-
opacity 0.2s;
|
|
327
|
+
transition:
|
|
328
|
+
max-width 0.2s cubic-bezier(.4, 0, .2, 1);
|
|
348
329
|
}
|
|
330
|
+
|
|
349
331
|
.expanded-content.drawer-anim.open {
|
|
350
|
-
width: 12.5rem;
|
|
351
|
-
min-width: 12.5rem;
|
|
352
332
|
max-width: 12.5rem;
|
|
353
|
-
opacity: 1;
|
|
354
333
|
pointer-events: auto;
|
|
355
334
|
}
|
|
335
|
+
|
|
356
336
|
.drawer-content {
|
|
337
|
+
width: 12.5rem;
|
|
338
|
+
height: 100%;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.logo-placeholder {
|
|
342
|
+
height: var(--ai-size-72);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
.sr-only {
|
|
346
|
+
position: absolute;
|
|
347
|
+
width: 1px;
|
|
348
|
+
height: 1px;
|
|
349
|
+
padding: 0;
|
|
350
|
+
margin: -1px;
|
|
351
|
+
overflow: hidden;
|
|
352
|
+
clip: rect(0, 0, 0, 0);
|
|
353
|
+
border: 0;
|
|
354
|
+
white-space: nowrap;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.user-profile-container,
|
|
358
|
+
.user-profile-icon {
|
|
359
|
+
display: flex;
|
|
360
|
+
align-items: center;
|
|
361
|
+
justify-content: center;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
.menu-button {
|
|
365
|
+
display: flex;
|
|
366
|
+
align-items: center;
|
|
367
|
+
justify-content: center;
|
|
368
|
+
border: none;
|
|
369
|
+
background: none;
|
|
370
|
+
cursor: pointer;
|
|
371
|
+
border-radius: var(--ai-size-8);
|
|
372
|
+
transition: background-color 0.2s ease;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
.menu-button:disabled,
|
|
376
|
+
.menu-button.disabled {
|
|
377
|
+
cursor: not-allowed;
|
|
378
|
+
opacity: 0.5;
|
|
379
|
+
background-color: transparent;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
.user-profile-icon {
|
|
383
|
+
border-radius: var(--ai-size-6);
|
|
384
|
+
background: var(--ai-color-steel-700);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
.user-initials {
|
|
388
|
+
color: var(--ai-color-white);
|
|
389
|
+
text-align: center;
|
|
390
|
+
font-weight: 400;
|
|
391
|
+
line-height: 1.3;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
.side-nav-container {
|
|
395
|
+
display: flex;
|
|
396
|
+
flex-shrink: 0;
|
|
397
|
+
position: relative;
|
|
398
|
+
z-index: var(--ai-layer-2);
|
|
399
|
+
height: 100%;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
.side-nav-container.expanded {
|
|
403
|
+
width: 16.875rem;
|
|
404
|
+
min-width: 12.5rem;
|
|
405
|
+
max-width: 16.875rem;
|
|
406
|
+
height: 100%;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
.expanded-content {
|
|
410
|
+
display: flex;
|
|
411
|
+
width: 12.5rem;
|
|
412
|
+
opacity: 1;
|
|
413
|
+
flex: none;
|
|
414
|
+
height: 100%;
|
|
415
|
+
background: var(--ai-color-steel-100);
|
|
416
|
+
border-right: 0.0625rem solid var(--ai-color-steel-100);
|
|
417
|
+
overflow: hidden;
|
|
418
|
+
flex-direction: column;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
.side-nav-container.expanded .expanded-content {
|
|
422
|
+
width: 12.5rem;
|
|
423
|
+
opacity: 1;
|
|
424
|
+
overflow-y: auto;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
.side-nav-container:not(.expanded) .expanded-content {
|
|
428
|
+
width: 0;
|
|
357
429
|
opacity: 0;
|
|
358
|
-
transform: translateX(-10px);
|
|
359
|
-
transition:
|
|
360
|
-
opacity 0.4s 0.20s cubic-bezier(.4,0,.2,1),
|
|
361
|
-
transform 0.4s 0.20s cubic-bezier(.4,0,.2,1);
|
|
362
430
|
}
|
|
363
|
-
|
|
431
|
+
|
|
432
|
+
.nav-content {
|
|
433
|
+
display: flex;
|
|
434
|
+
width: var(--ai-size-72);
|
|
435
|
+
height: 100%;
|
|
436
|
+
padding-bottom: var(--ai-size-16);
|
|
437
|
+
flex-direction: column;
|
|
438
|
+
align-items: flex-start;
|
|
439
|
+
gap: var(--ai-size-4);
|
|
440
|
+
flex: none;
|
|
441
|
+
background: var(--ai-color-steel-200);
|
|
442
|
+
border-right: 0.0625rem solid var(--ai-color-steel-200);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
.nav-main {
|
|
446
|
+
display: flex;
|
|
447
|
+
flex-direction: column;
|
|
448
|
+
align-items: flex-start;
|
|
449
|
+
gap: var(--ai-size-4);
|
|
450
|
+
flex: 1 0 0;
|
|
451
|
+
align-self: stretch;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
.nav-footer {
|
|
455
|
+
display: flex;
|
|
456
|
+
padding: var(--ai-size-8) var(--ai-size-4);
|
|
457
|
+
flex-direction: column;
|
|
458
|
+
justify-content: center;
|
|
459
|
+
align-items: center;
|
|
460
|
+
gap: var(--ai-size-4);
|
|
461
|
+
align-self: stretch;
|
|
462
|
+
margin-top: auto;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
.user-profile-button {
|
|
466
|
+
background: none;
|
|
467
|
+
border: none;
|
|
468
|
+
padding: 0;
|
|
469
|
+
cursor: pointer;
|
|
470
|
+
display: flex;
|
|
471
|
+
justify-content: center;
|
|
472
|
+
align-items: center;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
.user-profile-button:focus {
|
|
476
|
+
outline: var(--ai-size-2) solid var(--ai-color-blue-600);
|
|
477
|
+
outline-offset: var(--ai-size-2);
|
|
478
|
+
border-radius: var(--ai-size-4);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
.user-profile-container {
|
|
482
|
+
width: var(--ai-size-40);
|
|
483
|
+
height: var(--ai-size-40);
|
|
484
|
+
aspect-ratio: 1/1;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
.user-profile-icon {
|
|
488
|
+
padding: 0.5556rem 0.4931rem 0.5694rem 0.3819rem;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
.user-initials {
|
|
492
|
+
font-size: var(--ai-size-16);
|
|
493
|
+
font-style: normal;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
.menu-section {
|
|
497
|
+
display: flex;
|
|
498
|
+
padding: var(--ai-size-4);
|
|
499
|
+
justify-content: center;
|
|
500
|
+
align-items: center;
|
|
501
|
+
align-self: stretch;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
.menu-button {
|
|
505
|
+
display: flex;
|
|
506
|
+
padding: var(--ai-size-4);
|
|
507
|
+
justify-content: center;
|
|
508
|
+
align-items: center;
|
|
509
|
+
background: none;
|
|
510
|
+
border: none;
|
|
511
|
+
cursor: pointer;
|
|
364
512
|
opacity: 1;
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
513
|
+
transition: opacity 0.2s ease;
|
|
514
|
+
will-change: opacity;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
.menu-button.disabled {
|
|
518
|
+
cursor: not-allowed;
|
|
519
|
+
opacity: 0.5;
|
|
520
|
+
will-change: opacity;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
.menu-button:focus,
|
|
524
|
+
.nav-item:focus {
|
|
525
|
+
outline: none;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
.menu-button:focus .icon-container,
|
|
529
|
+
.nav-item:focus .icon-container {
|
|
530
|
+
outline: var(--ai-size-2) solid var(--ai-color-blue-600);
|
|
531
|
+
outline-offset: var(--ai-size-2);
|
|
532
|
+
border-radius: var(--ai-size-4);
|
|
369
533
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
534
|
+
|
|
535
|
+
.nav-items {
|
|
536
|
+
display: flex;
|
|
537
|
+
width: var(--ai-size-72);
|
|
538
|
+
flex-direction: column;
|
|
539
|
+
align-items: flex-start;
|
|
540
|
+
gap: var(--ai-size-4);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
.nav-item {
|
|
544
|
+
display: flex;
|
|
545
|
+
height: 4.125rem;
|
|
546
|
+
padding: var(--ai-size-4);
|
|
547
|
+
flex-direction: column;
|
|
548
|
+
justify-content: center;
|
|
549
|
+
align-items: center;
|
|
550
|
+
gap: var(--ai-size-2);
|
|
551
|
+
align-self: stretch;
|
|
552
|
+
cursor: pointer;
|
|
553
|
+
text-decoration: none;
|
|
554
|
+
color: inherit;
|
|
555
|
+
position: relative;
|
|
556
|
+
flex-shrink: 0;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
.icon-container {
|
|
560
|
+
display: flex;
|
|
561
|
+
width: var(--ai-size-40);
|
|
562
|
+
height: var(--ai-size-40);
|
|
563
|
+
padding: var(--ai-size-8);
|
|
564
|
+
justify-content: center;
|
|
565
|
+
align-items: center;
|
|
566
|
+
flex-shrink: 0;
|
|
567
|
+
position: relative;
|
|
568
|
+
contain: layout style;
|
|
569
|
+
transition: background-color 0.3s ease,
|
|
570
|
+
border-radius 0.3s ease;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
.icon-wrapper {
|
|
574
|
+
display: flex;
|
|
575
|
+
width: var(--ai-size-28);
|
|
576
|
+
height: var(--ai-size-28);
|
|
577
|
+
justify-content: center;
|
|
578
|
+
align-items: center;
|
|
579
|
+
flex-shrink: 0;
|
|
580
|
+
aspect-ratio: 1/1;
|
|
581
|
+
position: relative;
|
|
582
|
+
overflow: hidden;
|
|
583
|
+
transition: transform 0.3s ease;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
.icon-wrapper :global(svg) {
|
|
587
|
+
width: var(--ai-size-24);
|
|
588
|
+
height: var(--ai-size-24);
|
|
589
|
+
flex-shrink: 0;
|
|
590
|
+
position: absolute;
|
|
591
|
+
top: 50%;
|
|
592
|
+
left: 50%;
|
|
593
|
+
transform: translate(-50%, -50%);
|
|
594
|
+
transition: all 0.3s ease;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
.icon-wrapper :global(svg path) {
|
|
598
|
+
stroke-width: 1.5;
|
|
599
|
+
vector-effect: non-scaling-stroke;
|
|
600
|
+
transition: stroke 0.3s ease,
|
|
601
|
+
fill 0.3s ease,
|
|
602
|
+
stroke-width 0.3s ease;
|
|
374
603
|
}
|
|
604
|
+
|
|
605
|
+
.nav-text {
|
|
606
|
+
font-size: var(--ai-size-12);
|
|
607
|
+
text-align: center;
|
|
608
|
+
color: var(--ai-color-neutral-900);
|
|
609
|
+
line-height: 1.3;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
.menu-button.disabled:hover .icon-container,
|
|
613
|
+
.menu-button:disabled:hover .icon-container {
|
|
614
|
+
background: none !important;
|
|
615
|
+
border-radius: var(--ai-size-4);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
.nav-item.hovered .icon-container,
|
|
619
|
+
.nav-item:active .icon-container,
|
|
620
|
+
.nav-item.selected .icon-container,
|
|
621
|
+
.nav-item.selected.hovered .icon-container,
|
|
622
|
+
.menu-button:hover .icon-container,
|
|
623
|
+
.menu-button:active .icon-container {
|
|
624
|
+
background-color: var(--ai-color-steel-300);
|
|
625
|
+
border-radius: var(--ai-size-4);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
.nav-item {
|
|
629
|
+
flex: 1;
|
|
630
|
+
display: flex;
|
|
631
|
+
flex-direction: column;
|
|
632
|
+
align-items: center;
|
|
633
|
+
justify-content: center;
|
|
634
|
+
padding: var(--ai-size-4);
|
|
635
|
+
text-decoration: none;
|
|
636
|
+
color: var(--ai-color-neutral-600);
|
|
637
|
+
transition: color 0.2s ease;
|
|
638
|
+
height: 100%;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
.nav-item:hover {
|
|
642
|
+
color: var(--ai-color-neutral-700);
|
|
643
|
+
}
|
|
644
|
+
|
|
375
645
|
</style>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<svelte:options customElement={{
|
|
2
|
+
tag: 'graymatter-desktop-side-nav'
|
|
3
|
+
}} />
|
|
4
|
+
|
|
5
|
+
<script lang="ts">
|
|
6
|
+
import DesktopSideNav from './DesktopSideNav.svelte';
|
|
7
|
+
|
|
8
|
+
// Props for the web component
|
|
9
|
+
let { ssrSelectedItem, onNavToggle, onNavItemClick, onProfileClick } = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<DesktopSideNav
|
|
13
|
+
{ssrSelectedItem}
|
|
14
|
+
{onNavToggle}
|
|
15
|
+
{onNavItemClick}
|
|
16
|
+
{onProfileClick}
|
|
17
|
+
>
|
|
18
|
+
<slot />
|
|
19
|
+
</DesktopSideNav>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<svelte:options customElement={{
|
|
2
|
+
tag: 'graymatter-logo',
|
|
3
|
+
props: {
|
|
4
|
+
isInverted: { reflect: true, type: 'Boolean', attribute: 'is-inverted' },
|
|
5
|
+
width: { reflect: true, type: 'Number', attribute: 'width' },
|
|
6
|
+
height: { reflect: true, type: 'Number', attribute: 'height' }
|
|
7
|
+
}
|
|
8
|
+
}} />
|
|
9
|
+
|
|
10
|
+
<script lang="ts">
|
|
11
|
+
import Logo from './Logo.svelte';
|
|
12
|
+
|
|
13
|
+
let {
|
|
14
|
+
isInverted = false,
|
|
15
|
+
width = undefined,
|
|
16
|
+
height = undefined,
|
|
17
|
+
...props
|
|
18
|
+
} = $props();
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<Logo
|
|
22
|
+
{isInverted}
|
|
23
|
+
{width}
|
|
24
|
+
{height}
|
|
25
|
+
{...props}
|
|
26
|
+
/>
|
|
@@ -5,23 +5,23 @@
|
|
|
5
5
|
import ChatIcon from './icons/ChatIcon.svelte';
|
|
6
6
|
import ConsoleIcon from './icons/ConsoleIcon.svelte';
|
|
7
7
|
import ApiIcon from './icons/ApiIcon.svelte';
|
|
8
|
+
import { getAppUrls } from '../utils/getAppUrls';
|
|
8
9
|
|
|
9
10
|
export let onNavItemClick: ((data: { item: NavigationItem; expanded: boolean }) => void) | undefined = undefined;
|
|
10
11
|
|
|
12
|
+
const urls = getAppUrls();
|
|
13
|
+
|
|
11
14
|
const navItems = [
|
|
12
|
-
{ id: 'discover', label: 'Discover', icon: DiscoverIcon, href:
|
|
13
|
-
{ id: 'chat', label: 'Chat', icon: ChatIcon, href:
|
|
14
|
-
{ id: 'console', label: 'Console', icon: ConsoleIcon, href:
|
|
15
|
-
{ id: 'api', label: 'API', icon: ApiIcon, href:
|
|
15
|
+
{ id: 'discover', label: 'Discover', icon: DiscoverIcon, href: urls.discover },
|
|
16
|
+
{ id: 'chat', label: 'Chat', icon: ChatIcon, href: urls.chat },
|
|
17
|
+
{ id: 'console', label: 'Console', icon: ConsoleIcon, href: urls.console },
|
|
18
|
+
{ id: 'api', label: 'API', icon: ApiIcon, href: urls.api }
|
|
16
19
|
] as const;
|
|
17
20
|
|
|
18
|
-
function handleNavItemClick(item: NavigationItem) {
|
|
19
|
-
console.log('[MobileBottomNav] handleNavItemClick called for:', item, 'at:', Date.now());
|
|
20
|
-
|
|
21
|
+
function handleNavItemClick(item: NavigationItem) {
|
|
21
22
|
// Set navigation flag immediately to prevent header restoration
|
|
22
23
|
if (item !== 'discover' && typeof window !== 'undefined') {
|
|
23
24
|
sessionStorage.setItem('navigatingToMainNav', 'true');
|
|
24
|
-
console.log('[MobileBottomNav] Set navigation flag for:', item, 'at:', Date.now());
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
navigationStore.setSelectedItem(item);
|
|
@@ -44,7 +44,6 @@
|
|
|
44
44
|
const firstSection = mainContent.querySelector('h2[id], h3[id], h4[id], h5[id], h6[id]');
|
|
45
45
|
if (firstSection && firstSection.textContent) {
|
|
46
46
|
const firstSectionTitle = firstSection.textContent.trim();
|
|
47
|
-
console.log('[MobileBottomNav] Setting default header for', item, ':', firstSectionTitle);
|
|
48
47
|
selectedSubNavItemTitle.set(firstSectionTitle);
|
|
49
48
|
if (typeof window !== 'undefined') {
|
|
50
49
|
sessionStorage.setItem('subNav-selectedTitle', JSON.stringify(firstSectionTitle));
|
|
@@ -79,21 +78,68 @@
|
|
|
79
78
|
}
|
|
80
79
|
</script>
|
|
81
80
|
|
|
82
|
-
<nav class="mobile-bottom-nav">
|
|
81
|
+
<nav class="mobile-bottom-nav" part="mobile-bottom-nav">
|
|
83
82
|
{#each navItems as navItem}
|
|
84
83
|
<a
|
|
85
84
|
href={navItem.href}
|
|
86
85
|
class="nav-item"
|
|
87
86
|
class:active={$selectedItem === navItem.id}
|
|
88
87
|
on:click={() => handleNavItemClick(navItem.id)}
|
|
88
|
+
part="nav-item"
|
|
89
89
|
>
|
|
90
90
|
<div class="icon">
|
|
91
91
|
<svelte:component
|
|
92
92
|
this={navItem.icon}
|
|
93
|
-
|
|
93
|
+
isSelected={$selectedItem === navItem.id}
|
|
94
94
|
/>
|
|
95
95
|
</div>
|
|
96
96
|
<span class="label">{navItem.label}</span>
|
|
97
97
|
</a>
|
|
98
98
|
{/each}
|
|
99
99
|
</nav>
|
|
100
|
+
|
|
101
|
+
<style>
|
|
102
|
+
.nav-item {
|
|
103
|
+
flex: 1;
|
|
104
|
+
display: flex;
|
|
105
|
+
flex-direction: column;
|
|
106
|
+
align-items: center;
|
|
107
|
+
justify-content: center;
|
|
108
|
+
padding: var(--ai-size-4);
|
|
109
|
+
text-decoration: none;
|
|
110
|
+
color: var(--ai-color-neutral-600);
|
|
111
|
+
transition: color 0.2s ease;
|
|
112
|
+
height: 100%;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.nav-item.active {
|
|
116
|
+
color: var(--ai-color-neutral-900);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.nav-item.active .icon {
|
|
120
|
+
background-color: var(--ai-color-neutral-200);
|
|
121
|
+
border-radius: var(--ai-size-8);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.nav-item:hover {
|
|
125
|
+
color: var(--ai-color-neutral-700);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.icon {
|
|
129
|
+
width: var(--ai-size-24);
|
|
130
|
+
height: var(--ai-size-24);
|
|
131
|
+
margin-bottom: var(--ai-size-2);
|
|
132
|
+
display: flex;
|
|
133
|
+
align-items: center;
|
|
134
|
+
justify-content: center;
|
|
135
|
+
padding: var(--ai-size-2);
|
|
136
|
+
transition: background-color 0.2s ease;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.label {
|
|
140
|
+
font-size: 0.6875rem; /* 11px */
|
|
141
|
+
font-weight: 500;
|
|
142
|
+
line-height: 1;
|
|
143
|
+
text-align: center;
|
|
144
|
+
}
|
|
145
|
+
</style>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<svelte:options customElement={{
|
|
2
|
+
tag: 'graymatter-mobile-bottom-nav'
|
|
3
|
+
}} />
|
|
4
|
+
|
|
5
|
+
<script lang="ts">
|
|
6
|
+
import MobileBottomNav from './MobileBottomNav.svelte';
|
|
7
|
+
|
|
8
|
+
// Props for the web component
|
|
9
|
+
let { onNavItemClick } = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<MobileBottomNav
|
|
13
|
+
{onNavItemClick}
|
|
14
|
+
/>
|