@gsa-tts/graymatter-ui 0.3.0 → 0.3.1
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/README.md +33 -3
- package/assets/images/ai-icons/check-circle.svg +3 -0
- package/assets/images/ai-icons/console-icon.svg +6 -6
- package/assets/images/ai-icons/pause-button.svg +5 -0
- package/assets/images/ai-icons/play-button.svg +4 -0
- package/assets/images/api-hero-image.webp +0 -0
- package/assets/images/api-icon-w.svg +3 -0
- package/assets/images/chat-hero-image.webp +0 -0
- package/assets/images/chat-icon-b.svg +4 -0
- package/assets/images/console-hero-image.webp +0 -0
- package/assets/images/console-icon-w.svg +6 -0
- package/assets/images/og-preview.webp +0 -0
- package/assets/images/partners/gemini-government-logo.svg +129 -0
- package/assets/images/partners/microsoft-logo.svg +14 -0
- package/dist/graymatter-ui.js +1693 -1631
- package/dist/graymatter-ui.umd.cjs +37 -15
- package/package.json +4 -5
- package/src/component-options/componentOptions.ts +27 -13
- package/src/components/Button.svelte +164 -6
- package/src/components/DesktopSideNav.webcomponent.svelte +2 -0
- package/src/components/GoogleTagManager.astro +1 -1
- package/src/components/Head.astro +57 -24
- package/src/components/icons/ExclamationIcon.svelte +24 -0
- package/src/components/icons/index.ts +1 -0
- package/src/helpers/url.ts +13 -4
- package/src/layouts/BaseLayout.astro +2 -4
- package/src/layouts/GlobalAppLayout.astro +3 -1
- package/src/styles/base/theme.css +6 -1
- package/src/utils/getAppUrls.ts +27 -4
- package/assets/images/lp-bg-hero-1024.webp +0 -0
- package/assets/images/lp-bg-hero-1920.webp +0 -0
- package/assets/images/lp-bg-hero-640.webp +0 -0
- package/assets/images/lp-bg-hero.png +0 -0
- /package/assets/images/{api-icon.svg → api-icon-b.svg} +0 -0
- /package/assets/images/{chat-icon.svg → chat-icon-w.svg} +0 -0
- /package/assets/images/{console-icon.svg → console-icon-b.svg} +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.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -44,7 +44,6 @@
|
|
|
44
44
|
"@testing-library/jest-dom": "^6.6.3",
|
|
45
45
|
"@testing-library/svelte": "^5.2.8",
|
|
46
46
|
"@testing-library/user-event": "^14.6.1",
|
|
47
|
-
"@turbo/gen": "^2.4.0",
|
|
48
47
|
"@types/node": "^22.13.0",
|
|
49
48
|
"@uswds/compile": "1.2.2",
|
|
50
49
|
"@vitest/coverage-istanbul": "^3.0.7",
|
|
@@ -56,13 +55,13 @@
|
|
|
56
55
|
"vitest": "^3.0.7",
|
|
57
56
|
"vite": "^6.3.5",
|
|
58
57
|
"@gsa-tts/graymatter-eslint": "0.0.1",
|
|
59
|
-
"@gsa-tts/graymatter-
|
|
60
|
-
"@gsa-tts/graymatter-
|
|
58
|
+
"@gsa-tts/graymatter-typescript-config": "0.0.1",
|
|
59
|
+
"@gsa-tts/graymatter-vitest-config": "0.0.1"
|
|
61
60
|
},
|
|
62
61
|
"dependencies": {
|
|
63
62
|
"@fontsource-variable/archivo": "^5.2.6",
|
|
64
63
|
"@uswds/uswds": "3.12.0",
|
|
65
|
-
"astro": "^5.
|
|
64
|
+
"astro": "^5.12.8",
|
|
66
65
|
"slugify": "^1.6.6",
|
|
67
66
|
"@gsa-tts/graymatter-style-tokens": "0.3.0"
|
|
68
67
|
},
|
|
@@ -2,38 +2,52 @@ interface WebsiteComponentOptions {
|
|
|
2
2
|
usaBanner?: {
|
|
3
3
|
theme?: 'inverse' | 'default';
|
|
4
4
|
};
|
|
5
|
-
|
|
5
|
+
header?: {
|
|
6
6
|
theme?: 'inverse' | 'default';
|
|
7
7
|
};
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
interface
|
|
11
|
-
usaBanner?: {
|
|
12
|
-
theme?: 'inverse' | 'default';
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
interface ConsoleComponentOptions {
|
|
10
|
+
interface AppComponentOptions {
|
|
17
11
|
usaBanner?: {
|
|
18
12
|
theme?: 'inverse' | 'default';
|
|
19
13
|
};
|
|
20
14
|
}
|
|
21
15
|
|
|
22
16
|
export interface ComponentOptions {
|
|
17
|
+
api?: AppComponentOptions;
|
|
18
|
+
apiSubpage?: WebsiteComponentOptions;
|
|
19
|
+
chatSubpage?: WebsiteComponentOptions;
|
|
20
|
+
console?: AppComponentOptions;
|
|
21
|
+
consoleSubpage?: WebsiteComponentOptions;
|
|
22
|
+
partnershipsSubpage?: WebsiteComponentOptions;
|
|
23
23
|
website?: WebsiteComponentOptions;
|
|
24
|
-
api?: ApiComponentOptions;
|
|
25
|
-
console?: ConsoleComponentOptions;
|
|
26
24
|
}
|
|
27
25
|
|
|
28
26
|
export const componentOptions: ComponentOptions = {
|
|
29
|
-
|
|
27
|
+
api: {
|
|
28
|
+
usaBanner: { theme: 'default' },
|
|
29
|
+
},
|
|
30
|
+
apiSubpage: {
|
|
30
31
|
usaBanner: { theme: 'inverse' },
|
|
31
|
-
|
|
32
|
+
header: { theme: 'inverse' },
|
|
32
33
|
},
|
|
33
|
-
|
|
34
|
+
chatSubpage: {
|
|
34
35
|
usaBanner: { theme: 'default' },
|
|
36
|
+
header: { theme: 'default' },
|
|
35
37
|
},
|
|
36
38
|
console: {
|
|
37
39
|
usaBanner: { theme: 'default' },
|
|
38
40
|
},
|
|
41
|
+
consoleSubpage: {
|
|
42
|
+
usaBanner: { theme: 'inverse' },
|
|
43
|
+
header: { theme: 'inverse' },
|
|
44
|
+
},
|
|
45
|
+
partnershipsSubpage: {
|
|
46
|
+
usaBanner: { theme: 'default' },
|
|
47
|
+
header: { theme: 'default' },
|
|
48
|
+
},
|
|
49
|
+
website: {
|
|
50
|
+
usaBanner: { theme: 'inverse' },
|
|
51
|
+
header: { theme: 'inverse' },
|
|
52
|
+
},
|
|
39
53
|
};
|
|
@@ -1,13 +1,33 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Button Component
|
|
4
|
+
*
|
|
5
|
+
* Props:
|
|
6
|
+
* - variant: 'primary' | 'secondary' | 'unstyled' (default: 'primary')
|
|
7
|
+
* - theme: 'default' | 'inverted' (default: 'default')
|
|
8
|
+
* - shape: 'round' | 'square' (default: 'round')
|
|
9
|
+
* - size: 'small' | 'medium' | 'large' (default: 'medium')
|
|
10
|
+
* - href?: string (optional - renders as <a> if provided)
|
|
11
|
+
* - disabled?: boolean (default: false)
|
|
12
|
+
* - type?: 'button' | 'submit' | 'reset' (default: 'button')
|
|
13
|
+
*
|
|
14
|
+
* Examples:
|
|
15
|
+
* - Round primary button: <Button>Click me</Button>
|
|
16
|
+
* - Square secondary button: <Button variant="secondary" shape="square">Square</Button>
|
|
17
|
+
* - Small button (any shape): <Button size="small">Small Button</Button>
|
|
18
|
+
* - Small square button: <Button variant="secondary" shape="square" size="small">Small Square</Button>
|
|
19
|
+
* - Inverted square button: <Button theme="inverted" shape="square">Inverted Square</Button>
|
|
20
|
+
*/
|
|
2
21
|
interface Props {
|
|
3
|
-
variant?: 'primary' | 'secondary';
|
|
22
|
+
variant?: 'primary' | 'secondary' | 'unstyled';
|
|
4
23
|
theme?: 'default' | 'inverted';
|
|
24
|
+
shape?: 'round' | 'square';
|
|
5
25
|
href?: string;
|
|
6
26
|
disabled?: boolean;
|
|
7
27
|
size: 'small' | 'medium' | 'large';
|
|
8
28
|
type?: 'button' | 'submit' | 'reset';
|
|
9
29
|
onclick?: (event: MouseEvent) => void;
|
|
10
|
-
children?:
|
|
30
|
+
children?: import('svelte').Snippet | null;
|
|
11
31
|
class?: string;
|
|
12
32
|
[key: `data-${string}`]: string;
|
|
13
33
|
[key: `aria-${string}`]: string;
|
|
@@ -16,7 +36,8 @@
|
|
|
16
36
|
let {
|
|
17
37
|
variant = 'primary',
|
|
18
38
|
theme = 'default',
|
|
19
|
-
|
|
39
|
+
shape = 'round',
|
|
40
|
+
href = undefined,
|
|
20
41
|
disabled = false,
|
|
21
42
|
onclick,
|
|
22
43
|
children = null,
|
|
@@ -41,6 +62,7 @@
|
|
|
41
62
|
variant === 'primary' ? 'usa-button--primary' : '',
|
|
42
63
|
variant === 'secondary' ? 'usa-button--outline ai-button--outline' : '',
|
|
43
64
|
variant === 'unstyled' ? 'ai-button--unstyled' : '',
|
|
65
|
+
shape === 'square' ? 'ai-button--square' : '',
|
|
44
66
|
]
|
|
45
67
|
.filter(Boolean)
|
|
46
68
|
.join(' ');
|
|
@@ -60,6 +82,7 @@
|
|
|
60
82
|
{/if}
|
|
61
83
|
|
|
62
84
|
<style>
|
|
85
|
+
/*! purgecss start ignore */
|
|
63
86
|
:root,
|
|
64
87
|
:host {
|
|
65
88
|
/* global button */
|
|
@@ -106,6 +129,37 @@
|
|
|
106
129
|
--ai-button-border-outline-inverted-hover: var(
|
|
107
130
|
--ai-button-border-outline-inverted-rest
|
|
108
131
|
);
|
|
132
|
+
|
|
133
|
+
/* square button specific tokens */
|
|
134
|
+
--ai-button-radius-square: var(--ai-size-4);
|
|
135
|
+
--ai-button-padding-x-square: var(--ai-size-12);
|
|
136
|
+
--ai-button-padding-y-square: var(--ai-size-6);
|
|
137
|
+
--ai-button-height-square: var(--ai-size-40);
|
|
138
|
+
--ai-button-width-square: 100%;
|
|
139
|
+
|
|
140
|
+
/* small square button tokens */
|
|
141
|
+
--ai-button-padding-x-square-small: var(--ai-size-8);
|
|
142
|
+
--ai-button-padding-y-square-small: var(--ai-size-4);
|
|
143
|
+
--ai-button-height-square-small: var(--ai-size-24);
|
|
144
|
+
|
|
145
|
+
/* square button color tokens */
|
|
146
|
+
--ai-button-background-square-primary-rest: var(--ai-color-black);
|
|
147
|
+
--ai-button-background-square-primary-hover: var(--ai-color-neutral-900);
|
|
148
|
+
--ai-button-background-square-primary-disabled: var(--ai-color-neutral-200);
|
|
149
|
+
--ai-button-text-square-primary-rest: var(--ai-color-white);
|
|
150
|
+
--ai-button-text-square-primary-hover: var(--ai-color-white);
|
|
151
|
+
--ai-button-text-square-primary-disabled: var(--ai-color-neutral-800);
|
|
152
|
+
|
|
153
|
+
--ai-button-background-square-secondary-rest: var(--ai-color-white);
|
|
154
|
+
--ai-button-background-square-secondary-hover: var(--ai-color-neutral-200);
|
|
155
|
+
--ai-button-background-square-secondary-disabled: var(
|
|
156
|
+
--ai-color-neutral-500
|
|
157
|
+
);
|
|
158
|
+
--ai-button-text-square-secondary-rest: var(--ai-color-black);
|
|
159
|
+
--ai-button-text-square-secondary-hover: var(--ai-color-black);
|
|
160
|
+
--ai-button-text-square-secondary-disabled: var(--ai-color-neutral-900);
|
|
161
|
+
--ai-button-border-square-secondary-rest: var(--ai-color-black);
|
|
162
|
+
--ai-button-border-square-secondary-hover: var(--ai-color-black);
|
|
109
163
|
}
|
|
110
164
|
|
|
111
165
|
.ai-button {
|
|
@@ -116,6 +170,7 @@
|
|
|
116
170
|
padding-inline: var(--ai-button-padding-x);
|
|
117
171
|
padding-block: var(--ai-button-padding-y);
|
|
118
172
|
margin: 0;
|
|
173
|
+
width: fit-content;
|
|
119
174
|
}
|
|
120
175
|
|
|
121
176
|
.ai-button:is(:hover, :focus) {
|
|
@@ -169,6 +224,108 @@
|
|
|
169
224
|
border: var(--ai-button-border-inverted-hover);
|
|
170
225
|
}
|
|
171
226
|
|
|
227
|
+
/* Square button styles */
|
|
228
|
+
.ai-button--square {
|
|
229
|
+
border-radius: var(--ai-button-radius-square);
|
|
230
|
+
padding-inline: var(--ai-button-padding-x-square);
|
|
231
|
+
padding-block: var(--ai-button-padding-y-square);
|
|
232
|
+
height: var(--ai-button-height-square);
|
|
233
|
+
width: var(--ai-button-width-square);
|
|
234
|
+
width: 100%;
|
|
235
|
+
display: flex;
|
|
236
|
+
align-items: center;
|
|
237
|
+
justify-content: center;
|
|
238
|
+
border: 0.0625rem solid var(--ai-color-neutral-300);
|
|
239
|
+
box-shadow: 0 0.0625rem var(--ai-size-2) 0 rgba(0, 0, 0, 0.1);
|
|
240
|
+
transition: all var(--ai-transition-ease-fast);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/* Small square button specific adjustments */
|
|
244
|
+
.ai-button--small.ai-button--square {
|
|
245
|
+
padding-inline: var(--ai-button-padding-x-square-small);
|
|
246
|
+
padding-block: var(--ai-button-padding-y-square-small);
|
|
247
|
+
height: var(--ai-button-height-square-small);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.ai-button--square:is(:hover, :focus) {
|
|
251
|
+
border-color: var(--ai-color-neutral-400);
|
|
252
|
+
box-shadow: 0 var(--ai-size-2) var(--ai-size-4) 0 rgba(0, 0, 0, 0.3);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.ai-button--square:focus {
|
|
256
|
+
outline-offset: var(--ai-size-2);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/* Square button variants */
|
|
260
|
+
.ai-button--square.ai-button--primary {
|
|
261
|
+
background-color: var(--ai-button-background-square-primary-rest);
|
|
262
|
+
color: var(--ai-button-text-square-primary-rest);
|
|
263
|
+
border-color: transparent;
|
|
264
|
+
box-shadow: none;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
.ai-button--square.ai-button--primary:is(:hover, :focus) {
|
|
268
|
+
background-color: var(--ai-button-background-square-primary-hover);
|
|
269
|
+
color: var(--ai-button-text-square-primary-hover);
|
|
270
|
+
border-color: transparent;
|
|
271
|
+
box-shadow: none;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.ai-button--square.ai-button--secondary {
|
|
275
|
+
background-color: var(--ai-button-background-square-secondary-rest);
|
|
276
|
+
color: var(--ai-button-text-square-secondary-rest);
|
|
277
|
+
border-color: var(--ai-button-border-square-secondary-rest);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.ai-button--square.ai-button--secondary:is(:hover, :focus) {
|
|
281
|
+
background-color: var(--ai-button-background-square-secondary-hover);
|
|
282
|
+
color: var(--ai-button-text-square-secondary-hover);
|
|
283
|
+
border-color: var(--ai-button-border-square-secondary-hover);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.ai-button--square.ai-button--outline {
|
|
287
|
+
background-color: var(--ai-color-white);
|
|
288
|
+
color: var(--ai-color-neutral-800);
|
|
289
|
+
border-color: var(--ai-color-neutral-300);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
.ai-button--square.ai-button--outline:is(:hover, :focus) {
|
|
293
|
+
background-color: var(--ai-color-neutral-50);
|
|
294
|
+
color: var(--ai-color-black);
|
|
295
|
+
border-color: var(--ai-color-neutral-400);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/* Square button inverted themes */
|
|
299
|
+
.ai-button--square.ai-button--inverted {
|
|
300
|
+
background-color: var(--ai-button-background-inverted-rest);
|
|
301
|
+
color: var(--ai-button-text-inverted-rest);
|
|
302
|
+
border-color: transparent;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.ai-button--square.ai-button--inverted:is(:hover, :focus) {
|
|
306
|
+
background-color: var(--ai-button-background-inverted-hover);
|
|
307
|
+
color: var(--ai-button-text-inverted-hover);
|
|
308
|
+
border-color: transparent;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
.ai-button--square.ai-button--outline-inverted {
|
|
312
|
+
background-color: transparent;
|
|
313
|
+
color: var(--ai-color-white);
|
|
314
|
+
border-color: var(--ai-color-neutral-300);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
.ai-button--square.ai-button--outline-inverted:is(:hover, :focus) {
|
|
318
|
+
background-color: var(--ai-color-neutral-900);
|
|
319
|
+
color: var(--ai-color-white);
|
|
320
|
+
border-color: var(--ai-color-neutral-400);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
.ai-menu-buttons {
|
|
324
|
+
display: flex;
|
|
325
|
+
gap: var(--ai-size-16);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/* Unstyled button styles */
|
|
172
329
|
.ai-button--unstyled {
|
|
173
330
|
background: none;
|
|
174
331
|
color: inherit;
|
|
@@ -189,9 +346,9 @@
|
|
|
189
346
|
text-decoration: underline;
|
|
190
347
|
}
|
|
191
348
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
349
|
+
/* Unstyled square button - just center the text, reuse existing unstyled styles */
|
|
350
|
+
.ai-button--unstyled.ai-button--square {
|
|
351
|
+
text-align: center;
|
|
195
352
|
}
|
|
196
353
|
|
|
197
354
|
/* disabled button styles */
|
|
@@ -226,4 +383,5 @@
|
|
|
226
383
|
color: inherit;
|
|
227
384
|
opacity: 0.75;
|
|
228
385
|
}
|
|
386
|
+
/*! purgecss end ignore */
|
|
229
387
|
</style>
|
|
@@ -10,7 +10,7 @@ if (Astro.props.gtmID) {
|
|
|
10
10
|
gtag('js', new Date());
|
|
11
11
|
gtag('config', '${Astro.props.gtmID}');
|
|
12
12
|
</script>
|
|
13
|
-
<script id="_fed_an_ua_tag" async
|
|
13
|
+
<script id="_fed_an_ua_tag" async src="https://dap.digitalgov.gov/Universal-Federated-Analytics-Min.js?agency=GSA&subagency=TTS"></script>`;
|
|
14
14
|
}
|
|
15
15
|
---
|
|
16
16
|
|
|
@@ -1,55 +1,88 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
2
|
+
import { siteName } from '../constants';
|
|
3
|
+
const { title, description, openGraphImage, gtmID } = Astro.props;
|
|
3
4
|
import { Font } from 'astro:assets';
|
|
4
5
|
import { getUrlFromBase } from '@gsa-tts/graymatter-ui/helpers';
|
|
6
|
+
import GoogleTagManager from './GoogleTagManager.astro';
|
|
7
|
+
|
|
8
|
+
// Default values for Open Graph
|
|
9
|
+
const defaultDescription =
|
|
10
|
+
'Accelerating trustworthy adoption of AI across the federal government. Three powerful AI tools. Industry-leading models. One integrated platform.';
|
|
11
|
+
const defaultOgImage = getUrlFromBase('/common/assets/images/og-preview.webp');
|
|
12
|
+
|
|
13
|
+
const pageTitle = `${title} | USAi`;
|
|
14
|
+
const ogTitle = title || siteName;
|
|
15
|
+
const ogDescription = description || defaultDescription;
|
|
16
|
+
const ogImage = openGraphImage || defaultOgImage;
|
|
17
|
+
const siteUrl = Astro.site || Astro.url.origin;
|
|
18
|
+
const canonicalUrl = new URL(Astro.url.pathname, siteUrl).href;
|
|
5
19
|
---
|
|
6
20
|
|
|
7
21
|
<meta name="viewport" content="width=device-width" />
|
|
22
|
+
<title>{pageTitle}</title>
|
|
23
|
+
<script is:inline>
|
|
24
|
+
if ('performance' in window) {
|
|
25
|
+
performance.mark('usai:documenthead:start');
|
|
26
|
+
}
|
|
27
|
+
</script>
|
|
28
|
+
{gtmID && <GoogleTagManager {gtmID} />}
|
|
29
|
+
<script is:inline src=`${getUrlFromBase('uswds/js/uswds-init.min.js')}`
|
|
30
|
+
></script>
|
|
31
|
+
<Font cssVariable="--ai-font-family-sans" preload />
|
|
32
|
+
<style>
|
|
33
|
+
body {
|
|
34
|
+
font-family: var(--ai-font-family-sans);
|
|
35
|
+
}
|
|
36
|
+
</style>
|
|
37
|
+
<script>
|
|
38
|
+
import '../../static/uswds/js/uswds.js';
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<!-- Open Graph -->
|
|
42
|
+
<meta property="og:type" content="website" />
|
|
43
|
+
<meta property="og:url" content={canonicalUrl} />
|
|
44
|
+
<meta property="og:title" content={ogTitle} />
|
|
45
|
+
<meta property="og:description" content={ogDescription} />
|
|
46
|
+
<meta property="og:image" content={ogImage} />
|
|
47
|
+
<meta property="og:site_name" content={ogTitle} />
|
|
48
|
+
|
|
49
|
+
<meta property="twitter:card" content="summary_large_image" />
|
|
50
|
+
<meta property="twitter:url" content={canonicalUrl} />
|
|
51
|
+
<meta property="twitter:title" content={ogTitle} />
|
|
52
|
+
<meta property="twitter:description" content={ogDescription} />
|
|
53
|
+
<meta property="twitter:image" content={ogImage} />
|
|
54
|
+
|
|
55
|
+
<!-- Additional meta tags -->
|
|
56
|
+
<meta name="description" content={ogDescription} />
|
|
57
|
+
<link rel="canonical" href={canonicalUrl} />
|
|
58
|
+
|
|
8
59
|
<link
|
|
9
60
|
rel="icon"
|
|
10
61
|
sizes="any"
|
|
11
|
-
href=`${getUrlFromBase('/assets/images/favicon
|
|
62
|
+
href=`${getUrlFromBase('/common/assets/images/favicon.ico')}`
|
|
12
63
|
media="(prefers-color-scheme: light)"
|
|
13
64
|
/>
|
|
14
65
|
<link
|
|
15
66
|
rel="icon"
|
|
16
67
|
type="image/svg+xml"
|
|
17
|
-
href=`${getUrlFromBase('/assets/images/favicon-light.svg')}`
|
|
68
|
+
href=`${getUrlFromBase('/common/assets/images/favicon-light.svg')}`
|
|
18
69
|
media="(prefers-color-scheme: light)"
|
|
19
70
|
/>
|
|
20
71
|
<link
|
|
21
72
|
rel="icon"
|
|
22
73
|
sizes="any"
|
|
23
|
-
href=`${getUrlFromBase('/assets/images/favicon-dark.ico')}`
|
|
74
|
+
href=`${getUrlFromBase('/common/assets/images/favicon-dark.ico')}`
|
|
24
75
|
media="(prefers-color-scheme: dark)"
|
|
25
76
|
/>
|
|
26
77
|
<link
|
|
27
78
|
rel="icon"
|
|
28
79
|
type="image/svg+xml"
|
|
29
|
-
href=`${getUrlFromBase('/assets/images/favicon-dark.svg')}`
|
|
80
|
+
href=`${getUrlFromBase('/common/assets/images/favicon-dark.svg')}`
|
|
30
81
|
media="(prefers-color-scheme: dark)"
|
|
31
82
|
/>
|
|
32
|
-
<meta name="generator" content={Astro.generator} />
|
|
33
|
-
<title>{title}</title>
|
|
34
|
-
<script is:inline>
|
|
35
|
-
if ('performance' in window) {
|
|
36
|
-
performance.mark('gsa:documenthead:start');
|
|
37
|
-
}
|
|
38
|
-
</script>
|
|
39
|
-
<script is:inline src=`${getUrlFromBase('uswds/js/uswds-init.min.js')}`
|
|
40
|
-
></script>
|
|
41
|
-
<Font cssVariable="--ai-font-family-sans" preload />
|
|
42
|
-
<style>
|
|
43
|
-
body {
|
|
44
|
-
font-family: var(--ai-font-family-sans);
|
|
45
|
-
}
|
|
46
|
-
</style>
|
|
47
|
-
<script>
|
|
48
|
-
import '../../static/uswds/js/uswds.js';
|
|
49
|
-
</script>
|
|
50
83
|
<!-- This belongs at the very bottom of the head -->
|
|
51
84
|
<script is:inline>
|
|
52
85
|
if ('performance' in window) {
|
|
53
|
-
performance.mark('
|
|
86
|
+
performance.mark('usai:documenthead:end');
|
|
54
87
|
}
|
|
55
88
|
</script>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface Props {
|
|
3
|
+
class?: string;
|
|
4
|
+
size?: number;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
let { class: className = '', size = 32 }: Props = $props();
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<svg
|
|
11
|
+
class={className}
|
|
12
|
+
width={size}
|
|
13
|
+
height={size}
|
|
14
|
+
viewBox="0 0 32 33"
|
|
15
|
+
fill="none"
|
|
16
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
17
|
+
>
|
|
18
|
+
<path
|
|
19
|
+
fill-rule="evenodd"
|
|
20
|
+
clip-rule="evenodd"
|
|
21
|
+
d="M3 16.5028C3 9.32311 8.8203 3.50281 16 3.50281C23.1797 3.50281 29 9.32311 29 16.5028C29 23.6825 23.1797 29.5028 16 29.5028C8.8203 29.5028 3 23.6825 3 16.5028ZM16 11.5028C16.5523 11.5028 17 11.9505 17 12.5028V17.5028C17 18.0551 16.5523 18.5028 16 18.5028C15.4477 18.5028 15 18.0551 15 17.5028V12.5028C15 11.9505 15.4477 11.5028 16 11.5028ZM16 22.5028C16.5523 22.5028 17 22.0551 17 21.5028C17 20.9505 16.5523 20.5028 16 20.5028C15.4477 20.5028 15 20.9505 15 21.5028C15 22.0551 15.4477 22.5028 16 22.5028Z"
|
|
22
|
+
fill="currentColor"
|
|
23
|
+
/>
|
|
24
|
+
</svg>
|
|
@@ -4,3 +4,4 @@ export { default as ConsoleIcon } from './ConsoleIcon.svelte';
|
|
|
4
4
|
export { default as ApiIcon } from './ApiIcon.svelte';
|
|
5
5
|
export { default as MenuIcon } from './MenuIcon.svelte';
|
|
6
6
|
export { default as CloseIcon } from './CloseIcon.svelte';
|
|
7
|
+
export { default as ExclamationIcon } from './ExclamationIcon.svelte';
|
package/src/helpers/url.ts
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
import { normalizeTrailingSlash } from './string-formatters.js';
|
|
2
2
|
|
|
3
3
|
export const getBaseUrl = () => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
if (!BASEURL) {
|
|
4
|
+
// Check if we're in a browser environment
|
|
5
|
+
if (typeof window !== 'undefined') {
|
|
7
6
|
return '/';
|
|
8
7
|
}
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
// Node.js environment
|
|
10
|
+
if (typeof process !== 'undefined' && process.env) {
|
|
11
|
+
const { BASEURL } = process.env;
|
|
12
|
+
if (!BASEURL) {
|
|
13
|
+
return '/';
|
|
14
|
+
}
|
|
15
|
+
return normalizeTrailingSlash(BASEURL);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Fallback
|
|
19
|
+
return '/';
|
|
11
20
|
};
|
|
12
21
|
|
|
13
22
|
export const getUrlFromBase = (assetPath?: string) => {
|
|
@@ -4,6 +4,7 @@ import Head from '../components/Head.astro';
|
|
|
4
4
|
import UsaSkipNav from '../components/UsaSkipNav.svelte';
|
|
5
5
|
import { getPageTitle } from '../helpers/meta';
|
|
6
6
|
import GoogleTagManager from '../components/GoogleTagManager.astro';
|
|
7
|
+
const { description, openGraphImage, gtmID } = Astro.props;
|
|
7
8
|
|
|
8
9
|
const title = getPageTitle(Astro);
|
|
9
10
|
---
|
|
@@ -12,10 +13,7 @@ const title = getPageTitle(Astro);
|
|
|
12
13
|
<html lang="en">
|
|
13
14
|
<head>
|
|
14
15
|
<meta charset="UTF-8" />
|
|
15
|
-
<Head
|
|
16
|
-
<slot name="analytics">
|
|
17
|
-
<GoogleTagManager gtmID={Astro.props.gtmID} />
|
|
18
|
-
</slot>
|
|
16
|
+
<Head {title} {gtmID} {openGraphImage} {description} />
|
|
19
17
|
</head>
|
|
20
18
|
<body>
|
|
21
19
|
<slot name="skip-nav">
|
|
@@ -19,10 +19,12 @@ const {
|
|
|
19
19
|
logoLinkUrl,
|
|
20
20
|
logoLinkLabel,
|
|
21
21
|
title: pageTitle,
|
|
22
|
+
description,
|
|
23
|
+
openGraphImage,
|
|
22
24
|
} = Astro.props;
|
|
23
25
|
---
|
|
24
26
|
|
|
25
|
-
<BaseLayout title={pageTitle}
|
|
27
|
+
<BaseLayout title={pageTitle} {gtmID} {description} {openGraphImage}>
|
|
26
28
|
<div class="app">
|
|
27
29
|
<!-- Desktop Navigation -->
|
|
28
30
|
<div class="layout-container">
|
|
@@ -14,7 +14,12 @@ body {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
*:focus {
|
|
17
|
-
outline
|
|
17
|
+
outline: var(--ai-size-2) solid var(--ai-color-blue-600);
|
|
18
|
+
outline-offset: var(--ai-size-4);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
*:focus:not(:focus-visible) {
|
|
22
|
+
outline: none;
|
|
18
23
|
}
|
|
19
24
|
|
|
20
25
|
a:focus {
|
package/src/utils/getAppUrls.ts
CHANGED
|
@@ -1,9 +1,32 @@
|
|
|
1
|
+
import { getUrlFromBase } from '@gsa-tts/graymatter-ui/helpers/url.js';
|
|
2
|
+
|
|
1
3
|
function warnIfMissing(name: string, value: string | undefined) {
|
|
2
4
|
if (!value) {
|
|
3
5
|
console.warn(`[getAppUrls] Environment variable for ${name} is missing!`);
|
|
4
6
|
}
|
|
5
7
|
}
|
|
6
8
|
|
|
9
|
+
function isAbsoluteUrl(url: string): boolean {
|
|
10
|
+
try {
|
|
11
|
+
new URL(url);
|
|
12
|
+
return true;
|
|
13
|
+
} catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function processUrl(url: string | undefined, fallback: string): string {
|
|
19
|
+
if (!url) {
|
|
20
|
+
return fallback;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (isAbsoluteUrl(url)) {
|
|
24
|
+
return url;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return getUrlFromBase(url);
|
|
28
|
+
}
|
|
29
|
+
|
|
7
30
|
export function getAppUrls(envArg?: Record<string, string | undefined>) {
|
|
8
31
|
const env = envArg || import.meta.env;
|
|
9
32
|
const fallback = '#';
|
|
@@ -18,9 +41,9 @@ export function getAppUrls(envArg?: Record<string, string | undefined>) {
|
|
|
18
41
|
warnIfMissing('api', apiUrl);
|
|
19
42
|
|
|
20
43
|
return {
|
|
21
|
-
chat: chatUrl
|
|
22
|
-
console: consoleUrl
|
|
23
|
-
api: apiUrl
|
|
24
|
-
discover: discoverUrl
|
|
44
|
+
chat: processUrl(chatUrl, fallback),
|
|
45
|
+
console: processUrl(consoleUrl, fallback),
|
|
46
|
+
api: processUrl(apiUrl, getUrlFromBase('/api/documentation')),
|
|
47
|
+
discover: processUrl(discoverUrl, '#'),
|
|
25
48
|
};
|
|
26
49
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|