@gsa-tts/graymatter-ui 0.4.7 → 0.4.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gsa-tts/graymatter-ui",
3
- "version": "0.4.7",
3
+ "version": "0.4.9",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -61,8 +61,8 @@
61
61
  "typescript": "5.7.3",
62
62
  "vite": "^6.3.5",
63
63
  "vitest": "^3.0.7",
64
- "@gsa-tts/graymatter-typescript-config": "0.0.2",
65
64
  "@gsa-tts/graymatter-eslint": "0.0.2",
65
+ "@gsa-tts/graymatter-typescript-config": "0.0.2",
66
66
  "@gsa-tts/graymatter-vitest-config": "0.0.1"
67
67
  },
68
68
  "dependencies": {
@@ -11,15 +11,17 @@
11
11
  selectedItem,
12
12
  isMenuButtonDisabled,
13
13
  navigationStore,
14
+ selectedSubNavItemId,
14
15
  type NavigationItem,
15
16
  } from '../stores/navigationStore.js';
17
+ import { get } from 'svelte/store';
16
18
  import DiscoverIcon from './icons/DiscoverIcon.svelte';
17
19
  import ChatIcon from './icons/ChatIcon.svelte';
18
20
  import ConsoleIcon from './icons/ConsoleIcon.svelte';
19
21
  import ApiIcon from './icons/ApiIcon.svelte';
20
22
  import MenuIcon from './icons/MenuIcon.svelte';
21
23
  import ProfileMenu from './ProfileMenu.svelte';
22
- // import HelpIcon from './icons/HelpIcon.svelte';
24
+ import HelpIcon from './icons/HelpIcon.svelte';
23
25
 
24
26
  const {
25
27
  ssrSelectedItem = undefined,
@@ -32,14 +34,16 @@
32
34
  chatUrl,
33
35
  consoleUrl,
34
36
  discoverUrl,
37
+ supplementalMenuData,
35
38
  } = $props();
36
39
 
40
+ const helpUrl = supplementalMenuData?.help?.url?.trim();
41
+
37
42
  let hydrated = false;
38
43
  let navContainer: HTMLDivElement;
39
44
  let hoveredItem = $state<string | null>(null);
40
45
  let menuButtonHovered = $state(false);
41
46
  let canHover = $state(false);
42
- // let helpIconHovered = $state(false);
43
47
  let discoverNavRef = $state<HTMLAnchorElement | null>(null);
44
48
  let chatNavRef = $state<HTMLAnchorElement | null>(null);
45
49
  let consoleNavRef = $state<HTMLAnchorElement | null>(null);
@@ -92,6 +96,7 @@
92
96
  if (navContainer) {
93
97
  navContainer.classList.add('hydrated');
94
98
  }
99
+
95
100
  // Detect if device supports hover (desktop only)
96
101
  if (typeof window !== 'undefined') {
97
102
  const mq = window.matchMedia('(hover: hover)');
@@ -425,23 +430,24 @@
425
430
 
426
431
  {#if profileMenuData}
427
432
  <div class="nav-footer" part="nav-footer">
428
- <!-- TODO: Add help icon back in when we have decided on full functionality-->
429
- <!-- <div class="nav-footer-icon-container">
430
- <button
431
- type="button"
432
- class="nav-footer-icon-inner"
433
- tabindex="0"
434
- aria-label="Help"
435
- onmouseenter={() => (helpIconHovered = true)}
436
- onmouseleave={() => (helpIconHovered = false)}
437
- onfocus={() => (helpIconHovered = true)}
438
- onblur={() => (helpIconHovered = false)}
439
- >
440
- <div class="nav-footer-icon-svg-wrapper">
441
- <HelpIcon isHovered={helpIconHovered} />
433
+ {#if helpUrl}
434
+ <div
435
+ class="nav-footer-icon-container"
436
+ part="nav-footer-icon-container"
437
+ >
438
+ <a
439
+ class="help-link"
440
+ class:selected={get(selectedSubNavItemId) === 'help'}
441
+ aria-current={get(selectedSubNavItemId) === 'help'}
442
+ href={helpUrl}
443
+ part="help-link"
444
+ title="Help"
445
+ aria-label="Help"
446
+ >
447
+ <HelpIcon />
448
+ </a>
442
449
  </div>
443
- </button>
444
- </div> -->
450
+ {/if}
445
451
  <div class="nav-footer-profile-container">
446
452
  <ProfileMenu
447
453
  userMeta={profileMenuData?.userMeta}
@@ -742,15 +748,13 @@
742
748
  color: var(--ai-color-neutral-700);
743
749
  }
744
750
 
745
- /* .nav-footer-icon-container {
751
+ .nav-footer-icon-container {
752
+ align-items: center;
746
753
  display: flex;
747
- padding: 0 var(--ai-size-4);
748
754
  flex-direction: column;
749
755
  justify-content: center;
750
- align-items: center;
751
- gap: var(--ai-size-4);
752
- align-self: stretch;
753
- } */
756
+ margin-block-end: var(--ai-size-4);
757
+ }
754
758
 
755
759
  .nav-footer-profile-container {
756
760
  display: flex;
@@ -761,38 +765,22 @@
761
765
  gap: var(--ai-size-4);
762
766
  align-self: stretch;
763
767
  }
764
- /* .nav-footer-icon-inner {
765
- display: flex;
766
- width: var(--ai-size-40);
767
- height: var(--ai-size-40);
768
- padding: var(--ai-size-8);
769
- justify-content: center;
770
- align-items: center;
771
- border-radius: var(--ai-size-4);
772
- background: none;
773
- border: none;
774
- cursor: pointer;
775
- transition: background-color var(--ai-transition-ease-medium), border-radius var(--ai-transition-ease-medium);
776
- } */
777
- /* .nav-footer-icon-inner:hover,
778
- .nav-footer-icon-inner:focus {
779
- background-color: var(--ai-color-steel-300);
768
+
769
+ .help-link {
780
770
  border-radius: var(--ai-size-4);
771
+ padding: var(--ai-size-4);
772
+ transition: background-color var(--ai-transition-ease-medium);
781
773
  }
782
- .nav-footer-icon-inner:focus {
783
- outline: none;
774
+
775
+ .help-link :global(svg) {
776
+ display: block;
784
777
  }
785
- .nav-footer-icon-inner:focus-visible {
786
- outline: var(--ai-size-2) solid var(--ai-color-blue-600);
787
- outline-offset: var(--ai-size-2);
788
- border-radius: var(--ai-size-4);
778
+
779
+ .help-link:hover {
780
+ background: var(--ai-color-steel-300);
781
+ }
782
+
783
+ .help-link:is(.selected) {
784
+ background-color: var(--ai-color-steel-300);
789
785
  }
790
- .nav-footer-icon-svg-wrapper {
791
- width: var(--ai-size-24);
792
- height: var(--ai-size-24);
793
- flex-shrink: 0;
794
- display: flex;
795
- align-items: center;
796
- justify-content: center;
797
- } */
798
786
  </style>
@@ -19,6 +19,7 @@
19
19
  chatUrl,
20
20
  consoleUrl,
21
21
  discoverUrl,
22
+ supplementalMenuData,
22
23
  } = $props();
23
24
  </script>
24
25
 
@@ -33,6 +34,7 @@
33
34
  {chatUrl}
34
35
  {consoleUrl}
35
36
  {discoverUrl}
37
+ {supplementalMenuData}
36
38
  >
37
39
  <slot />
38
40
  </DesktopSideNav>
@@ -15,6 +15,7 @@ const {
15
15
  showAppIcons = false,
16
16
  disableCodeCopyButtons = false,
17
17
  profileMenuData = null,
18
+ supplementalMenuData = undefined,
18
19
  hideDiscover = true,
19
20
  contentCustomization = undefined,
20
21
  logoLinkUrl,
@@ -65,6 +66,7 @@ const subNavData = generateApiDocumentationNavData(apiDocsMetadata);
65
66
  {description}
66
67
  {openGraphImage}
67
68
  {hideDiscover}
69
+ {supplementalMenuData}
68
70
  >
69
71
  <!-- Initialize navigation state and auto-expand submenu for section pages -->
70
72
  <NavigationInitializer
@@ -16,12 +16,14 @@ const {
16
16
  gtmID,
17
17
  showAppIcons = true,
18
18
  profileMenuData = undefined,
19
+ supplementalMenuData = undefined,
19
20
  logoLinkUrl,
20
21
  logoLinkLabel,
21
22
  title: pageTitle,
22
23
  description,
23
24
  openGraphImage,
24
25
  hideDiscover = true,
26
+ className = '',
25
27
  } = Astro.props;
26
28
 
27
29
  // Use getSecret directly for better environment variable handling
@@ -33,13 +35,13 @@ const discoverUrl =
33
35
  getSecret('DISCOVER_URL') || getSecret('PUBLIC_DISCOVER_URL');
34
36
 
35
37
  const chat = chatUrl || '#';
36
- const console = consoleUrl || '#';
38
+ const consoleApp = consoleUrl || '#';
37
39
  const api = apiDocsUrl || '#';
38
40
  const discover = discoverUrl || '#';
39
41
  ---
40
42
 
41
43
  <BaseLayout title={pageTitle} {gtmID} {description} {openGraphImage}>
42
- <div class="app">
44
+ <div class={`app ${className}`}>
43
45
  <!-- Desktop Navigation -->
44
46
  <div class="layout-container">
45
47
  <nav aria-label="Main navigation">
@@ -51,8 +53,9 @@ const discover = discoverUrl || '#';
51
53
  profileMenuData={profileMenuData}
52
54
  apiUrl={api}
53
55
  chatUrl={chat}
54
- consoleUrl={console}
56
+ consoleUrl={consoleApp}
55
57
  discoverUrl={discover}
58
+ {supplementalMenuData}
56
59
  >
57
60
  <slot name="sub-nav" />
58
61
  </DesktopSideNav>
@@ -6,6 +6,7 @@ export function setupCommonMocks() {
6
6
  vi.mock('../stores/navigationStore.js', () => {
7
7
  const isExpanded = writable(true);
8
8
  const selectedItem = writable('console');
9
+ const selectedSubNavItemId = writable('');
9
10
  const selectedSubNavItemTitle = writable('');
10
11
 
11
12
  const isMenuButtonDisabled = derived(
@@ -17,6 +18,7 @@ export function setupCommonMocks() {
17
18
  isExpanded,
18
19
  selectedItem,
19
20
  isMenuButtonDisabled,
21
+ selectedSubNavItemId,
20
22
  selectedSubNavItemTitle,
21
23
  navigationStore: {
22
24
  setSelectedItem: vi.fn(),