@gsa-tts/graymatter-ui 0.3.1 → 0.3.2
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/chat-hero-image-mobile.webp +0 -0
- package/dist/graymatter-ui.js +1930 -1878
- package/dist/graymatter-ui.umd.cjs +21 -21
- package/package.json +4 -3
- package/src/astro-config/index.ts +10 -0
- package/src/components/Button.svelte +4 -0
- package/src/components/Head.astro +2 -1
- package/src/components/MobileSideMenu.svelte +2 -2
- package/src/components/MobileSideMenu.webcomponent.svelte +2 -4
- package/src/components/MobileTopNav.svelte +9 -2
- package/src/components/MobileTopNav.webcomponent.svelte +2 -2
- package/src/layouts/GlobalAppLayout.astro +6 -127
- package/src/styles/base/typography.css +8 -1
- package/static/uswds/styles/styles.css +1 -1
- package/static/uswds/styles/styles.css.map +1 -1
- package/assets/images/api-hero-image.png +0 -0
- package/assets/images/chat-hero-image.png +0 -0
- package/assets/images/console-hero-image.png +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gsa-tts/graymatter-ui",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -52,14 +52,15 @@
|
|
|
52
52
|
"gulp": "^5.0.0",
|
|
53
53
|
"svelte": "^5.35.4",
|
|
54
54
|
"typescript": "5.7.3",
|
|
55
|
-
"vitest": "^3.0.7",
|
|
56
55
|
"vite": "^6.3.5",
|
|
57
|
-
"
|
|
56
|
+
"vitest": "^3.0.7",
|
|
58
57
|
"@gsa-tts/graymatter-typescript-config": "0.0.1",
|
|
58
|
+
"@gsa-tts/graymatter-eslint": "0.0.1",
|
|
59
59
|
"@gsa-tts/graymatter-vitest-config": "0.0.1"
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
62
|
"@fontsource-variable/archivo": "^5.2.6",
|
|
63
|
+
"@fontsource/space-mono": "^5.2.8",
|
|
63
64
|
"@uswds/uswds": "3.12.0",
|
|
64
65
|
"astro": "^5.12.8",
|
|
65
66
|
"slugify": "^1.6.6",
|
|
@@ -113,6 +113,16 @@ export function createAstroConfig({
|
|
|
113
113
|
styles: ['normal'],
|
|
114
114
|
optimizedFallbacks: true,
|
|
115
115
|
},
|
|
116
|
+
{
|
|
117
|
+
name: 'Space Mono',
|
|
118
|
+
cssVariable: '--ai-font-family-monospace', // Scoped variable name
|
|
119
|
+
provider: fontProviders.fontsource(),
|
|
120
|
+
weights: [400],
|
|
121
|
+
fallbacks: ['monospace'],
|
|
122
|
+
subsets: ['latin'],
|
|
123
|
+
styles: ['normal'],
|
|
124
|
+
optimizedFallbacks: true,
|
|
125
|
+
},
|
|
116
126
|
],
|
|
117
127
|
},
|
|
118
128
|
image: {
|
|
@@ -7,7 +7,7 @@ import GoogleTagManager from './GoogleTagManager.astro';
|
|
|
7
7
|
|
|
8
8
|
// Default values for Open Graph
|
|
9
9
|
const defaultDescription =
|
|
10
|
-
'Accelerating
|
|
10
|
+
'Accelerating trusted AI adoption across government. Three powerful AI tools. Industry-leading models. One integrated platform.';
|
|
11
11
|
const defaultOgImage = getUrlFromBase('/common/assets/images/og-preview.webp');
|
|
12
12
|
|
|
13
13
|
const pageTitle = `${title} | USAi`;
|
|
@@ -29,6 +29,7 @@ const canonicalUrl = new URL(Astro.url.pathname, siteUrl).href;
|
|
|
29
29
|
<script is:inline src=`${getUrlFromBase('uswds/js/uswds-init.min.js')}`
|
|
30
30
|
></script>
|
|
31
31
|
<Font cssVariable="--ai-font-family-sans" preload />
|
|
32
|
+
<Font cssVariable="--ai-font-family-monospace" />
|
|
32
33
|
<style>
|
|
33
34
|
body {
|
|
34
35
|
font-family: var(--ai-font-family-sans);
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
let sideMenuElement: HTMLDivElement;
|
|
12
12
|
let pendingMobileHash: string | null = null;
|
|
13
13
|
|
|
14
|
-
let { logoLinkUrl, logoLinkLabel } = $props();
|
|
14
|
+
let { logoLinkUrl, logoLinkLabel, children } = $props();
|
|
15
15
|
|
|
16
16
|
function handleMobileAnchorNavigate(event: Event) {
|
|
17
17
|
const customEvent = event as CustomEvent;
|
|
@@ -180,7 +180,7 @@
|
|
|
180
180
|
<!-- Show submenu items if available and not on discover -->
|
|
181
181
|
{#if $selectedItem && $selectedItem !== 'discover'}
|
|
182
182
|
<div class="subnav-section" part="subnav-section">
|
|
183
|
-
|
|
183
|
+
{@render children?.()}
|
|
184
184
|
</div>
|
|
185
185
|
{:else}
|
|
186
186
|
<!-- Show message when no submenu is available -->
|
|
@@ -7,9 +7,7 @@
|
|
|
7
7
|
<script lang="ts">
|
|
8
8
|
import MobileSideMenu from './MobileSideMenu.svelte';
|
|
9
9
|
|
|
10
|
-
let { logoLinkUrl, logoLinkLabel } = $props();
|
|
10
|
+
let { logoLinkUrl, logoLinkLabel, children } = $props();
|
|
11
11
|
</script>
|
|
12
12
|
|
|
13
|
-
<MobileSideMenu {logoLinkUrl} {logoLinkLabel}
|
|
14
|
-
<slot />
|
|
15
|
-
</MobileSideMenu>
|
|
13
|
+
<MobileSideMenu {logoLinkUrl} {logoLinkLabel} {children} />
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import MenuIcon from './icons/MenuIcon.svelte';
|
|
9
9
|
import { onMount } from 'svelte';
|
|
10
10
|
|
|
11
|
-
let { profileMenuData } = $props();
|
|
11
|
+
let { profileMenuData, logoLinkUrl, logoLinkLabel } = $props();
|
|
12
12
|
|
|
13
13
|
import ProfileMenu from './ProfileMenu.svelte';
|
|
14
14
|
|
|
@@ -90,7 +90,14 @@
|
|
|
90
90
|
</button>
|
|
91
91
|
|
|
92
92
|
<div class="brand">
|
|
93
|
-
|
|
93
|
+
{#if logoLinkUrl}
|
|
94
|
+
<a class="display-flex" href={logoLinkUrl} aria-label={logoLinkLabel}>
|
|
95
|
+
<Logo width={75} height={22} />
|
|
96
|
+
</a>
|
|
97
|
+
{:else}
|
|
98
|
+
<Logo width={75} height={22} />
|
|
99
|
+
{/if}
|
|
100
|
+
|
|
94
101
|
<span class="brand-text">{$selectedSubNavItemTitle || ''}</span>
|
|
95
102
|
</div>
|
|
96
103
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import MobileTopNav from './MobileTopNav.svelte';
|
|
9
9
|
|
|
10
10
|
// Props for the web component
|
|
11
|
-
let { profileMenuData } = $props();
|
|
11
|
+
let { profileMenuData, logoLinkUrl, logoLinkLabel } = $props();
|
|
12
12
|
</script>
|
|
13
13
|
|
|
14
|
-
<MobileTopNav {profileMenuData} />
|
|
14
|
+
<MobileTopNav {profileMenuData} {logoLinkUrl} {logoLinkLabel} />
|
|
@@ -50,7 +50,12 @@ const {
|
|
|
50
50
|
|
|
51
51
|
<!-- Mobile Navigation -->
|
|
52
52
|
<nav aria-label="Mobile navigation">
|
|
53
|
-
<MobileTopNav
|
|
53
|
+
<MobileTopNav
|
|
54
|
+
client:load
|
|
55
|
+
{profileMenuData}
|
|
56
|
+
{logoLinkUrl}
|
|
57
|
+
{logoLinkLabel}
|
|
58
|
+
/>
|
|
54
59
|
<MobileSideMenu client:load {logoLinkUrl} {logoLinkLabel}>
|
|
55
60
|
<slot name="sub-nav" />
|
|
56
61
|
</MobileSideMenu>
|
|
@@ -104,10 +109,6 @@ const {
|
|
|
104
109
|
const mobileRect = mobileContent.getBoundingClientRect();
|
|
105
110
|
const scrollTop =
|
|
106
111
|
mobileContent.scrollTop + rect.top - mobileRect.top;
|
|
107
|
-
console.log(
|
|
108
|
-
'[GlobalAppLayout] Immediate mobile scroll to:',
|
|
109
|
-
scrollTop
|
|
110
|
-
);
|
|
111
112
|
mobileContent.scrollTo({ top: scrollTop, behavior: 'auto' });
|
|
112
113
|
|
|
113
114
|
setTimeout(() => {
|
|
@@ -140,11 +141,6 @@ const {
|
|
|
140
141
|
if (mainContent) {
|
|
141
142
|
const desktopAnchor = mainContent.querySelector(`[id="${anchor}"]`);
|
|
142
143
|
if (desktopAnchor) {
|
|
143
|
-
console.log(
|
|
144
|
-
'[GlobalAppLayout] Immediate desktop scroll for:',
|
|
145
|
-
anchor
|
|
146
|
-
);
|
|
147
|
-
|
|
148
144
|
try {
|
|
149
145
|
// Add temporary scroll margin to account for header
|
|
150
146
|
const originalScrollMargin =
|
|
@@ -202,27 +198,16 @@ const {
|
|
|
202
198
|
// Check navigation flag first, before any components mount
|
|
203
199
|
const isMainNavNavigation =
|
|
204
200
|
sessionStorage.getItem('navigatingToMainNav') === 'true';
|
|
205
|
-
console.log(
|
|
206
|
-
'[GlobalAppLayout] DOMContentLoaded - navigation flag:',
|
|
207
|
-
isMainNavNavigation
|
|
208
|
-
);
|
|
209
201
|
|
|
210
202
|
if (isMainNavNavigation) {
|
|
211
203
|
// Clear the flag immediately
|
|
212
204
|
sessionStorage.removeItem('navigatingToMainNav');
|
|
213
|
-
console.log(
|
|
214
|
-
'[GlobalAppLayout] Cleared navigation flag for main nav navigation'
|
|
215
|
-
);
|
|
216
205
|
// Don't clear header state here - let navigation components handle it
|
|
217
206
|
}
|
|
218
207
|
|
|
219
208
|
// Handle URL hash scrolling (fallback for cases where immediate scroll didn't work)
|
|
220
209
|
if (window.location.hash) {
|
|
221
210
|
const anchor = window.location.hash.substring(1);
|
|
222
|
-
console.log(
|
|
223
|
-
'[GlobalAppLayout] DOMContentLoaded fallback hash scroll for:',
|
|
224
|
-
anchor
|
|
225
|
-
);
|
|
226
211
|
|
|
227
212
|
// Only proceed if we haven't already scrolled
|
|
228
213
|
if (sessionStorage.getItem('globalLayoutScrolling') !== 'true') {
|
|
@@ -243,10 +228,6 @@ const {
|
|
|
243
228
|
const mobileRect = mobileContent.getBoundingClientRect();
|
|
244
229
|
const scrollTop =
|
|
245
230
|
mobileContent.scrollTop + rect.top - mobileRect.top;
|
|
246
|
-
console.log(
|
|
247
|
-
'[GlobalAppLayout] Fallback mobile scroll to:',
|
|
248
|
-
scrollTop
|
|
249
|
-
);
|
|
250
231
|
mobileContent.scrollTo({ top: scrollTop, behavior: 'auto' });
|
|
251
232
|
|
|
252
233
|
setTimeout(() => {
|
|
@@ -287,11 +268,6 @@ const {
|
|
|
287
268
|
);
|
|
288
269
|
if (desktopAnchor) {
|
|
289
270
|
setTimeout(() => {
|
|
290
|
-
console.log(
|
|
291
|
-
'[GlobalAppLayout] Fallback desktop scroll for:',
|
|
292
|
-
anchor
|
|
293
|
-
);
|
|
294
|
-
|
|
295
271
|
// Try scrollIntoView first with a temporary offset
|
|
296
272
|
try {
|
|
297
273
|
// Add temporary scroll margin to account for header
|
|
@@ -305,43 +281,18 @@ const {
|
|
|
305
281
|
inline: 'nearest',
|
|
306
282
|
});
|
|
307
283
|
|
|
308
|
-
console.log(
|
|
309
|
-
'[GlobalAppLayout] Used fallback scrollIntoView for desktop'
|
|
310
|
-
);
|
|
311
|
-
|
|
312
284
|
// Restore original scroll margin after a delay
|
|
313
285
|
setTimeout(() => {
|
|
314
286
|
desktopAnchor.style.scrollMarginTop =
|
|
315
287
|
originalScrollMargin;
|
|
316
288
|
}, 1000);
|
|
317
289
|
} catch (e) {
|
|
318
|
-
console.log(
|
|
319
|
-
'[GlobalAppLayout] Fallback scrollIntoView failed, using manual calculation:',
|
|
320
|
-
e
|
|
321
|
-
);
|
|
322
|
-
|
|
323
290
|
// Fallback to manual calculation
|
|
324
291
|
const headerHeight = 56;
|
|
325
292
|
const rect = desktopAnchor.getBoundingClientRect();
|
|
326
293
|
const scrollTop = window.scrollY + rect.top - headerHeight;
|
|
327
|
-
console.log(
|
|
328
|
-
'[GlobalAppLayout] Fallback desktop scroll calculation:',
|
|
329
|
-
{
|
|
330
|
-
anchor,
|
|
331
|
-
rectTop: rect.top,
|
|
332
|
-
windowScrollY: window.scrollY,
|
|
333
|
-
headerHeight,
|
|
334
|
-
scrollTop,
|
|
335
|
-
elementText: desktopAnchor.textContent?.trim(),
|
|
336
|
-
}
|
|
337
|
-
);
|
|
338
|
-
|
|
339
294
|
// Ensure scrollTop is not negative
|
|
340
295
|
const finalScrollTop = Math.max(0, scrollTop);
|
|
341
|
-
console.log(
|
|
342
|
-
'[GlobalAppLayout] Fallback final scroll position:',
|
|
343
|
-
finalScrollTop
|
|
344
|
-
);
|
|
345
296
|
|
|
346
297
|
window.scrollTo({ top: finalScrollTop, behavior: 'auto' });
|
|
347
298
|
}
|
|
@@ -374,25 +325,14 @@ const {
|
|
|
374
325
|
}, 100);
|
|
375
326
|
}, 100);
|
|
376
327
|
} else {
|
|
377
|
-
console.log(
|
|
378
|
-
'[GlobalAppLayout] Fallback desktop anchor not found in main-content container:',
|
|
379
|
-
anchor
|
|
380
|
-
);
|
|
381
328
|
// Log all available anchors for debugging
|
|
382
329
|
const allAnchors = mainContent.querySelectorAll('[id]');
|
|
383
|
-
console.log(
|
|
384
|
-
'[GlobalAppLayout] Available anchors in main-content:',
|
|
385
|
-
Array.from(allAnchors).map(el => el.id)
|
|
386
|
-
);
|
|
387
330
|
// Clear the flag if anchor not found
|
|
388
331
|
if (typeof window !== 'undefined') {
|
|
389
332
|
sessionStorage.removeItem('globalLayoutScrolling');
|
|
390
333
|
}
|
|
391
334
|
}
|
|
392
335
|
} else {
|
|
393
|
-
console.log(
|
|
394
|
-
'[GlobalAppLayout] Fallback desktop main-content container not found'
|
|
395
|
-
);
|
|
396
336
|
// Clear the flag if container not found
|
|
397
337
|
if (typeof window !== 'undefined') {
|
|
398
338
|
sessionStorage.removeItem('globalLayoutScrolling');
|
|
@@ -420,29 +360,10 @@ const {
|
|
|
420
360
|
const wasMobile = lastWidth <= 640;
|
|
421
361
|
const isMobile = currentWidth <= 640;
|
|
422
362
|
|
|
423
|
-
console.log('[GlobalAppLayout] Resize detected:', {
|
|
424
|
-
lastWidth,
|
|
425
|
-
currentWidth,
|
|
426
|
-
wasMobile,
|
|
427
|
-
isMobile,
|
|
428
|
-
changed: wasMobile !== isMobile,
|
|
429
|
-
});
|
|
430
|
-
|
|
431
363
|
if (wasMobile !== isMobile) {
|
|
432
|
-
console.log(
|
|
433
|
-
'[GlobalAppLayout] Layout changed from',
|
|
434
|
-
wasMobile ? 'mobile' : 'desktop',
|
|
435
|
-
'to',
|
|
436
|
-
isMobile ? 'mobile' : 'desktop'
|
|
437
|
-
);
|
|
438
|
-
|
|
439
364
|
// Handle anchor scrolling for layout changes
|
|
440
365
|
if (window.location.hash) {
|
|
441
366
|
const anchor = window.location.hash.substring(1);
|
|
442
|
-
console.log(
|
|
443
|
-
'[GlobalAppLayout] Layout change with URL hash:',
|
|
444
|
-
anchor
|
|
445
|
-
);
|
|
446
367
|
|
|
447
368
|
// Wait for navigation state to update, then scroll
|
|
448
369
|
setTimeout(() => {
|
|
@@ -460,10 +381,6 @@ const {
|
|
|
460
381
|
const mobileRect = mobileContent.getBoundingClientRect();
|
|
461
382
|
const scrollTop =
|
|
462
383
|
mobileContent.scrollTop + rect.top - mobileRect.top;
|
|
463
|
-
console.log(
|
|
464
|
-
'[GlobalAppLayout] Scrolling mobile to anchor:',
|
|
465
|
-
scrollTop
|
|
466
|
-
);
|
|
467
384
|
mobileContent.scrollTo({
|
|
468
385
|
top: scrollTop,
|
|
469
386
|
behavior: 'auto',
|
|
@@ -501,15 +418,6 @@ const {
|
|
|
501
418
|
`[id="${anchor}"]`
|
|
502
419
|
);
|
|
503
420
|
if (desktopAnchor) {
|
|
504
|
-
console.log(
|
|
505
|
-
'[GlobalAppLayout] Desktop anchor found for layout change:',
|
|
506
|
-
{
|
|
507
|
-
anchor,
|
|
508
|
-
elementText: desktopAnchor.textContent?.trim(),
|
|
509
|
-
elementId: desktopAnchor.id,
|
|
510
|
-
}
|
|
511
|
-
);
|
|
512
|
-
|
|
513
421
|
// Try scrollIntoView first with a temporary offset
|
|
514
422
|
try {
|
|
515
423
|
// Add temporary scroll margin to account for header
|
|
@@ -523,44 +431,20 @@ const {
|
|
|
523
431
|
inline: 'nearest',
|
|
524
432
|
});
|
|
525
433
|
|
|
526
|
-
console.log(
|
|
527
|
-
'[GlobalAppLayout] Used scrollIntoView for desktop layout change with scroll margin'
|
|
528
|
-
);
|
|
529
|
-
|
|
530
434
|
// Restore original scroll margin after a delay
|
|
531
435
|
setTimeout(() => {
|
|
532
436
|
desktopAnchor.style.scrollMarginTop =
|
|
533
437
|
originalScrollMargin;
|
|
534
438
|
}, 1000);
|
|
535
439
|
} catch (e) {
|
|
536
|
-
console.log(
|
|
537
|
-
'[GlobalAppLayout] scrollIntoView failed for layout change, using manual calculation:',
|
|
538
|
-
e
|
|
539
|
-
);
|
|
540
|
-
|
|
541
440
|
// Fallback to manual calculation
|
|
542
441
|
const headerHeight = 56;
|
|
543
442
|
const rect = desktopAnchor.getBoundingClientRect();
|
|
544
443
|
const scrollTop =
|
|
545
444
|
window.scrollY + rect.top - headerHeight;
|
|
546
|
-
console.log(
|
|
547
|
-
'[GlobalAppLayout] Desktop scroll calculation for layout change:',
|
|
548
|
-
{
|
|
549
|
-
anchor,
|
|
550
|
-
rectTop: rect.top,
|
|
551
|
-
windowScrollY: window.scrollY,
|
|
552
|
-
headerHeight,
|
|
553
|
-
scrollTop,
|
|
554
|
-
elementText: desktopAnchor.textContent?.trim(),
|
|
555
|
-
}
|
|
556
|
-
);
|
|
557
445
|
|
|
558
446
|
// Ensure scrollTop is not negative
|
|
559
447
|
const finalScrollTop = Math.max(0, scrollTop);
|
|
560
|
-
console.log(
|
|
561
|
-
'[GlobalAppLayout] Final scroll position for layout change:',
|
|
562
|
-
finalScrollTop
|
|
563
|
-
);
|
|
564
448
|
|
|
565
449
|
window.scrollTo({
|
|
566
450
|
top: finalScrollTop,
|
|
@@ -603,11 +487,6 @@ const {
|
|
|
603
487
|
detail: { isMobile },
|
|
604
488
|
})
|
|
605
489
|
);
|
|
606
|
-
console.log(
|
|
607
|
-
'[GlobalAppLayout] Dispatched layoutTransition event for',
|
|
608
|
-
isMobile ? 'mobile' : 'desktop',
|
|
609
|
-
'layout'
|
|
610
|
-
);
|
|
611
490
|
}
|
|
612
491
|
|
|
613
492
|
lastWidth = currentWidth;
|
|
@@ -50,7 +50,14 @@ h6,
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
pre {
|
|
53
|
-
padding: var(--ai-size-
|
|
53
|
+
padding: var(--ai-size-16);
|
|
54
|
+
border-radius: var(--ai-size-4);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
code {
|
|
58
|
+
font-family: var(--ai-font-family-monospace);
|
|
59
|
+
font-weight: var(--ai-font-weight-normal);
|
|
60
|
+
font-size: var(--ai-size-14);
|
|
54
61
|
}
|
|
55
62
|
|
|
56
63
|
a {
|