@hashicorp/react-components 0.0.0-nightly.b46420c → 0.0.0-nightly.b5f9cca

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.
Files changed (82) hide show
  1. package/package.json +5 -4
  2. package/src/components/actions/index.tsx +5 -5
  3. package/src/components/call-to-action/index.tsx +7 -7
  4. package/src/components/card/index.test.tsx +1 -1
  5. package/src/components/card/newsroom-card/index.test.tsx +1 -1
  6. package/src/components/card/partner-card/index.tsx +3 -3
  7. package/src/components/card/person-card/index.tsx +1 -1
  8. package/src/components/card/primitives.tsx +16 -15
  9. package/src/components/card/resource-card/index.test.tsx +1 -1
  10. package/src/components/card/resource-card/index.tsx +3 -0
  11. package/src/components/card/types.ts +2 -2
  12. package/src/components/card/unified-card/index.spec.tsx +40 -0
  13. package/src/components/card/unified-card/index.tsx +5 -11
  14. package/src/components/marketo-form/contexts/FormMetadata.ts +2 -0
  15. package/src/components/marketo-form/form/index.tsx +4 -2
  16. package/src/components/marketo-form/partials/fields/checkbox-field/index.tsx +1 -1
  17. package/src/components/marketo-form/partials/fields/email-field/index.tsx +1 -1
  18. package/src/components/marketo-form/partials/fields/form-page-url-field/index.tsx +2 -0
  19. package/src/components/marketo-form/partials/fields/hidden-field/index.tsx +1 -0
  20. package/src/components/marketo-form/partials/fields/radio-buttons-field/index.tsx +1 -1
  21. package/src/components/marketo-form/partials/fields/select-field/index.tsx +1 -1
  22. package/src/components/marketo-form/partials/fields/telephone-field/index.tsx +1 -1
  23. package/src/components/marketo-form/partials/fields/text-field/index.tsx +1 -1
  24. package/src/components/marketo-form/partials/fields/textarea-field/index.tsx +1 -1
  25. package/src/components/marketo-form/types.ts +10 -11
  26. package/src/components/nav-panel/components/link-list/index.tsx +25 -8
  27. package/src/components/nav-panel/components/panel/column/index.tsx +17 -2
  28. package/src/components/nav-panel/components/panel/column/style.module.css +12 -2
  29. package/src/components/nav-panel/components/panel/root/index.tsx +13 -2
  30. package/src/components/nav-panel/components/panel/root/style.module.css +19 -4
  31. package/src/components/nav-panel/components/promo/index.tsx +15 -8
  32. package/src/components/nav-panel/components/promo/style.module.css +28 -6
  33. package/src/components/nav-panel/product-panel/index.tsx +104 -27
  34. package/src/components/nav-panel/product-panel/style.module.css +230 -15
  35. package/src/components/nav-panel/standard-panel/index.tsx +3 -0
  36. package/src/components/nav-panel/standard-panel/style.module.css +1 -1
  37. package/src/components/next-steps/index.tsx +3 -2
  38. package/src/components/product-badge/index.tsx +1 -1
  39. package/src/components/subnav/index.tsx +14 -4
  40. package/src/components/subnav/partials/CtaLinks/github-stars-link/style.module.css +8 -12
  41. package/src/components/subnav/partials/CtaLinks/index.tsx +9 -8
  42. package/src/components/subnav/partials/CtaLinks/style.module.css +4 -4
  43. package/src/components/subnav/partials/DropdownTrigger/index.tsx +2 -2
  44. package/src/components/subnav/partials/DropdownTrigger/style.module.css +7 -4
  45. package/src/components/subnav/partials/MenuItemsDefault/index.tsx +29 -8
  46. package/src/components/subnav/partials/MenuItemsDefault/style.module.css +37 -24
  47. package/src/components/subnav/partials/MenuItemsOverflow/index.tsx +18 -4
  48. package/src/components/subnav/partials/MenuItemsOverflow/style.module.css +22 -16
  49. package/src/components/subnav/partials/TitleLink/index.tsx +5 -3
  50. package/src/components/subnav/partials/TitleLink/mktg-logos/all-community-product-logos_on-dark.ts +2 -1
  51. package/src/components/subnav/partials/TitleLink/mktg-logos/all-community-product-logos_on-light.ts +2 -1
  52. package/src/components/subnav/partials/TitleLink/style.module.css +1 -1
  53. package/src/components/subnav/partials/nav-item-text/style.module.css +2 -4
  54. package/src/components/subnav/style.module.css +4 -6
  55. package/src/lib/parse-url/index.test.ts +40 -1
  56. package/src/lib/parse-url/index.ts +78 -9
  57. package/src/lib/v/index.ts +4 -5
  58. package/src/components/consent-manager/README.md +0 -73
  59. package/src/components/consent-manager/components/banner/banner.module.css +0 -23
  60. package/src/components/consent-manager/components/banner/banner.test.tsx +0 -31
  61. package/src/components/consent-manager/components/banner/banner.tsx +0 -73
  62. package/src/components/consent-manager/components/dialog/dialog.module.css +0 -145
  63. package/src/components/consent-manager/components/dialog/dialog.test.tsx +0 -194
  64. package/src/components/consent-manager/components/dialog/dialog.tsx +0 -339
  65. package/src/components/consent-manager/img/icn_close.tsx +0 -19
  66. package/src/components/consent-manager/index.test.tsx +0 -334
  67. package/src/components/consent-manager/index.tsx +0 -186
  68. package/src/components/consent-manager/loader/README.md +0 -29
  69. package/src/components/consent-manager/loader/categories.ts +0 -22
  70. package/src/components/consent-manager/loader/index.tsx +0 -94
  71. package/src/components/consent-manager/loader/presets/enterprise.ts +0 -12
  72. package/src/components/consent-manager/loader/presets/oss.ts +0 -10
  73. package/src/components/consent-manager/loader/services.ts +0 -45
  74. package/src/components/consent-manager/scripts/custom.tsx +0 -59
  75. package/src/components/consent-manager/scripts/segment.tsx +0 -87
  76. package/src/components/consent-manager/style.module.css +0 -9
  77. package/src/components/consent-manager/types.ts +0 -55
  78. package/src/components/consent-manager/util/cookies.test.ts +0 -75
  79. package/src/components/consent-manager/util/cookies.ts +0 -70
  80. package/src/components/consent-manager/util/integrations.test.ts +0 -115
  81. package/src/components/consent-manager/util/integrations.ts +0 -110
  82. package/src/components/subnav/theme.module.css +0 -50
@@ -2,6 +2,7 @@
2
2
  * Copyright (c) HashiCorp, Inc.
3
3
  * SPDX-License-Identifier: MPL-2.0
4
4
  */
5
+ 'use client'
5
6
 
6
7
  import { useState } from 'react'
7
8
  import Badge from '@hashicorp/react-badge'
@@ -10,7 +11,7 @@ import ExpandableArrow from '@hashicorp/react-expandable-arrow'
10
11
  import Intro from '../intro'
11
12
  import Link from 'next/link'
12
13
  import type { NextStepsProps } from './types'
13
- import StandaloneLink from '@hashicorp/react-design-system-components/src/components/standalone-link'
14
+ import { HDSPlusStandaloneLink } from '@hashicorp/react-mds/src/hds-plus/standalone-link'
14
15
  import { IconArrowRight16 } from '@hashicorp/flight-icons/svg-react/arrow-right-16'
15
16
  import useProductMeta from '@hashicorp/platform-product-meta'
16
17
  import s from './style.module.css'
@@ -69,7 +70,7 @@ export default function NextSteps({
69
70
  {cta ? (
70
71
  <div className={s.cta}>
71
72
  <p className={s.ctaCopy}>{cta.copy}</p>
72
- <StandaloneLink
73
+ <HDSPlusStandaloneLink
73
74
  href={cta.href}
74
75
  text={cta.ctaText}
75
76
  icon={
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import type { Products } from '@hashicorp/platform-product-meta'
7
- import Badge from '@hashicorp/react-design-system-components/src/components/badge'
7
+ import Badge from '@hashicorp/react-hds/src/components/badge'
8
8
  import { IconDot16 } from '@hashicorp/flight-icons/svg-react/dot-16'
9
9
  import s from './style.module.css'
10
10
 
@@ -17,8 +17,8 @@ import CtaLinks, { type CtaLinkProps } from './partials/CtaLinks'
17
17
  import traverse, { isObject } from './helpers/traverse'
18
18
  import { areBasePathsMatching } from './helpers/areBasePathsMatching'
19
19
  import * as NavigationMenu from '@radix-ui/react-navigation-menu'
20
- import themeStyles from './theme.module.css'
21
20
  import s from './style.module.css'
21
+ import { getLocalizedHref } from '@web/utils/get-localized-href'
22
22
 
23
23
  const productAllowList = {
24
24
  consul: 'consul',
@@ -47,6 +47,7 @@ type SubnavDropdown = {
47
47
  type MenuItem = SubnavLink | SubnavDropdown | 'divider'
48
48
 
49
49
  export interface SubnavInnerProps {
50
+ locale?: string
50
51
  hasOverflow?: boolean
51
52
  titleLink: { text: string; url: string }
52
53
  product?: Products
@@ -62,6 +63,7 @@ export interface SubnavInnerProps {
62
63
  }
63
64
 
64
65
  function SubnavInner({
66
+ locale,
65
67
  hasOverflow,
66
68
  titleLink,
67
69
  product,
@@ -110,17 +112,20 @@ function SubnavInner({
110
112
  >
111
113
  <NavigationMenu.Link asChild>
112
114
  <TitleLink
115
+ locale={locale}
113
116
  text={titleLink.text}
114
- url={titleLink.url}
117
+ url={getLocalizedHref(titleLink.url)}
115
118
  product={product}
116
119
  theme={theme}
117
120
  />
118
121
  </NavigationMenu.Link>
122
+
119
123
  {!hasOverflow && (
120
124
  <div className={s.subNavRight}>
121
125
  <MenuItemsDefault
122
126
  menuItems={menuItemsWithActive}
123
127
  activatePanel={activatePanel}
128
+ locale={locale}
124
129
  />
125
130
  {ctaLinks?.length > 0 && (
126
131
  <CtaLinks
@@ -165,6 +170,10 @@ function Subnav({ className, theme = 'light', ...restProps }: SubnavProps) {
165
170
  setActivePanel(panel)
166
171
  }
167
172
 
173
+ const ariaLabel = restProps?.titleLink?.text
174
+ ? `${restProps.titleLink.text} pages`
175
+ : 'Subnav pages'
176
+
168
177
  return (
169
178
  <>
170
179
  {/**
@@ -175,11 +184,12 @@ function Subnav({ className, theme = 'light', ...restProps }: SubnavProps) {
175
184
  <style>{`:root{--subnav-height:${height}px}`}</style>
176
185
  <NavigationMenu.Root
177
186
  ref={wrapperRef}
178
- className={classNames(s.root, themeStyles[theme], className, {
187
+ className={classNames(s.root, className, {
179
188
  [s.isSticky]: isSticky,
180
189
  [s.hasOverflow]: hasOverflow,
190
+ 'hdsplus-dark-mode': theme === 'dark',
181
191
  })}
182
- aria-label={`${product} website navigation`}
192
+ aria-label={ariaLabel}
183
193
  onValueChange={activatePanel}
184
194
  value={activePanel}
185
195
  delayDuration={0}
@@ -3,15 +3,13 @@
3
3
  * SPDX-License-Identifier: MPL-2.0
4
4
  */
5
5
 
6
- /* Note: consumes from theme.module.css, as marked */
7
-
8
6
  .root {
9
- --local-scrim-color: transparent;
10
- --local-divider-color: var(--border-color); /* from theme.module.css */
7
+ --local-scrim-opacity: 0;
8
+ --local-divider-color: var(--token-color-border-primary);
11
9
 
12
10
  position: relative;
13
- color: var(--gh-stars-icon-color); /* from theme.module.css */
14
- border: 1px solid var(--local-divider-color); /* from theme.module.css */
11
+ color: var(--token-color-foreground-primary);
12
+ border: 1px solid var(--local-divider-color);
15
13
  border-radius: 5px;
16
14
  background: none;
17
15
  transition: background 0.2s, border-color 0.2s;
@@ -27,17 +25,15 @@
27
25
  right: -1px;
28
26
  bottom: -1px;
29
27
  border-radius: 5px;
30
- transition: background 0.25s ease;
28
+ transition: opacity 0.25s ease;
29
+ opacity: var(--local-scrim-opacity);
31
30
  z-index: 0;
32
- background-color: var(--local-scrim-color);
31
+ background-color: var(--token-color-foreground-primary);
33
32
  }
34
33
 
35
34
  &:hover,
36
35
  &:active {
37
- --local-divider-color: transparent;
38
- --local-scrim-color: var(
39
- --gh-stars-scrim-color
40
- ); /* from theme.module.css */
36
+ --local-scrim-opacity: 0.12;
41
37
  }
42
38
  }
43
39
 
@@ -3,19 +3,20 @@
3
3
  * SPDX-License-Identifier: MPL-2.0
4
4
  */
5
5
 
6
- import Button, {
7
- type ButtonProps,
8
- } from '@hashicorp/react-design-system-components/src/components/button'
9
- import FlightIcon from '@hashicorp/react-design-system-components/src/components/flight-icon'
6
+ import {
7
+ HDSPlusButton,
8
+ type HDSPlusButtonProps,
9
+ } from '@hashicorp/react-mds/src/hds-plus/button'
10
+ import FlightIcon from '@hashicorp/react-hds/src/components/flight-icon'
10
11
  import type { Products } from '@hashicorp/platform-product-meta'
11
- import type { ToggleButtonProps } from '@hashicorp/react-design-system-components/src/components/dropdown/toggle/button'
12
- import * as Dropdown from '@hashicorp/react-design-system-components/src/components/dropdown'
12
+ import type { ToggleButtonProps } from '@hashicorp/react-hds/src/components/dropdown/toggle/button'
13
+ import * as Dropdown from '@hashicorp/react-hds/src/components/dropdown'
13
14
  import GithubStarsLink from './github-stars-link'
14
15
  import classNames from 'classnames'
15
16
  import * as NavigationMenu from '@radix-ui/react-navigation-menu'
16
17
  import s from './style.module.css'
17
18
 
18
- type CtaLink = ButtonProps & { href: string; __typename?: string }
19
+ type CtaLink = HDSPlusButtonProps & { href: string; __typename?: string }
19
20
 
20
21
  type CtaDropdown = {
21
22
  __typename?: string
@@ -83,7 +84,7 @@ function CtaLinks({
83
84
  const isLastButton = stableIdx === links.length - 1
84
85
 
85
86
  return (
86
- <Button
87
+ <HDSPlusButton
87
88
  key={href}
88
89
  text={text}
89
90
  href={href}
@@ -10,26 +10,26 @@
10
10
  list-style: none;
11
11
  padding: 0 0 0 var(--hdsplus-spacing-05);
12
12
  margin: 0;
13
- gap: 0 12px;
13
+ gap: 0 var(--hdsplus-spacing-04);
14
14
  @media (--medium-up) {
15
15
  gap: 0;
16
16
  }
17
17
 
18
18
  & > * + * {
19
19
  /* Spaces consecutive buttons horizontally on desktop */
20
- margin-left: 16px;
20
+ margin-left: var(--hdsplus-spacing-05);
21
21
  }
22
22
 
23
23
  &.isInDropdown {
24
24
  /* Allows consecutive buttons to wrap */
25
25
  flex-wrap: wrap;
26
26
  white-space: wrap;
27
- padding-left: 0;
27
+ padding-inline: var(--hdsplus-spacing-04);
28
28
 
29
29
  & > * {
30
30
  /* Spaces consecutive buttons vertically */
31
31
  margin-left: 0;
32
- margin-top: 16px;
32
+ margin-top: var(--hdsplus-spacing-05);
33
33
 
34
34
  &:last-of-type {
35
35
  margin-bottom: var(--hdsplus-spacing-04);
@@ -3,7 +3,7 @@
3
3
  * SPDX-License-Identifier: MPL-2.0
4
4
  */
5
5
 
6
- import FlightIcon from '@hashicorp/react-design-system-components/src/components/flight-icon'
6
+ import FlightIcon from '@hashicorp/react-hds/src/components/flight-icon'
7
7
  import NavItemText from '../nav-item-text'
8
8
  import * as NavigationMenu from '@radix-ui/react-navigation-menu'
9
9
  import s from './style.module.css'
@@ -27,7 +27,7 @@ function DropdownTrigger(props: DropdownTriggerProps) {
27
27
  onMouseDown={(e) => e.preventDefault()}
28
28
  >
29
29
  <NavItemText isActive={isActive} text={text} />
30
- <FlightIcon name="chevron-down" color="var(--menu-item-text-color)" />
30
+ <FlightIcon name="chevron-down" />
31
31
  </NavigationMenu.Trigger>
32
32
  )
33
33
  }
@@ -3,8 +3,6 @@
3
3
  * SPDX-License-Identifier: MPL-2.0
4
4
  */
5
5
 
6
- /* Note: consumes from theme.module.css, as marked */
7
-
8
6
  .root {
9
7
  composes: hds-typography-body-200 from global;
10
8
  composes: hds-font-weight-medium from global;
@@ -26,11 +24,16 @@
26
24
  width: 12px;
27
25
  height: 12px;
28
26
  transition: transform 0.3s;
29
- fill: var(--menu-item-text-color); /* from theme.module.css */
27
+ fill: var(--token-color-foreground-primary);
30
28
  }
31
29
 
32
30
  &:hover {
33
- background-color: var(--menu-item-hover-color);
31
+ background-color: var(--token-color-surface-interactive-hover);
34
32
  border-radius: var(--hdsplus-spacing-01);
35
33
  }
34
+
35
+ &:focus {
36
+ outline: 2px solid var(--token-color-focus-action-internal);
37
+ outline-style: auto;
38
+ }
36
39
  }
@@ -9,22 +9,30 @@ import NavItemText from '../nav-item-text'
9
9
  import DropdownTrigger from '../DropdownTrigger'
10
10
  import * as NavigationMenu from '@radix-ui/react-navigation-menu'
11
11
  import s from './style.module.css'
12
+ import FlightIcon from '@hashicorp/react-hds/src/components/flight-icon'
13
+ import { getLocalizedHref } from '@web/utils/get-localized-href'
12
14
 
13
15
  interface MenuItemsDefaultProps {
14
16
  menuItems: (
15
17
  | {
16
18
  text: string
17
19
  url: string
18
- submenu: { text: string; url: string; _isActiveUrl: string }[]
20
+ submenu: {
21
+ icon: string
22
+ text: string
23
+ url: string
24
+ _isActiveUrl: string
25
+ }[]
19
26
  _isActiveUrl: boolean
20
27
  }
21
28
  | 'divider'
22
29
  )[]
23
30
  activatePanel: (panel: string) => void
31
+ locale?: string
24
32
  }
25
33
 
26
34
  function MenuItemsDefault(props: MenuItemsDefaultProps) {
27
- const { menuItems, activatePanel } = props
35
+ const { menuItems, activatePanel, locale } = props
28
36
  return (
29
37
  <NavigationMenu.List className={s.root}>
30
38
  {menuItems.map((menuItem, stableIdx) => {
@@ -41,6 +49,7 @@ function MenuItemsDefault(props: MenuItemsDefaultProps) {
41
49
  text={text}
42
50
  submenu={submenu}
43
51
  activatePanel={activatePanel}
52
+ locale={locale}
44
53
  />
45
54
  ) : (
46
55
  <NavLink
@@ -50,6 +59,7 @@ function MenuItemsDefault(props: MenuItemsDefaultProps) {
50
59
  text={text}
51
60
  url={url}
52
61
  isActive={_isActiveUrl}
62
+ locale={locale}
53
63
  />
54
64
  )
55
65
  })}
@@ -69,14 +79,19 @@ interface NavLinkProps {
69
79
  text: string
70
80
  url: string
71
81
  isActive: boolean
82
+ locale?: string
72
83
  }
73
84
 
74
85
  function NavLink(props: NavLinkProps) {
75
- const { text, url, isActive } = props
86
+ const { text, url, isActive, locale } = props
76
87
  return (
77
88
  <NavigationMenu.Item className={s.listItem}>
78
89
  <NavigationMenu.Link asChild>
79
- <Link className={s.navLink} href={url}>
90
+ <Link
91
+ className={s.navLink}
92
+ href={getLocalizedHref(url, locale)}
93
+ hrefLang={props.locale ? props.locale : undefined}
94
+ >
80
95
  <NavItemText isActive={isActive} text={text} />
81
96
  </Link>
82
97
  </NavigationMenu.Link>
@@ -86,8 +101,9 @@ function NavLink(props: NavLinkProps) {
86
101
 
87
102
  interface NavLinkWithDropdownProps {
88
103
  text: string
89
- submenu: { text: string; url: string; _isActiveUrl: string }[]
104
+ submenu: { icon: string; text: string; url: string; _isActiveUrl: string }[]
90
105
  activatePanel: (panel: string) => void
106
+ locale?: string
91
107
  }
92
108
 
93
109
  interface NavLinkWithDropdownState {
@@ -99,7 +115,7 @@ class NavLinkWithDropdown extends React.Component<
99
115
  NavLinkWithDropdownState
100
116
  > {
101
117
  render() {
102
- const { text, submenu, activatePanel } = this.props
118
+ const { text, submenu, activatePanel, locale } = this.props
103
119
  const hasActiveChild = submenu.some((s) => s._isActiveUrl)
104
120
 
105
121
  const handleFocusOutside = () => {
@@ -128,12 +144,17 @@ class NavLinkWithDropdown extends React.Component<
128
144
  <NavigationMenu.Sub>
129
145
  <NavigationMenu.List className={s.dropdownList}>
130
146
  {submenu.map((submenuItem, stableIdx) => {
131
- const { text, url } = submenuItem
147
+ const { icon, text, url } = submenuItem
132
148
  return (
133
149
  // eslint-disable-next-line react/no-array-index-key
134
150
  <NavigationMenu.Item key={stableIdx}>
135
151
  <NavigationMenu.Link asChild>
136
- <Link className={s.submenuItem} href={url}>
152
+ <Link
153
+ className={s.submenuItem}
154
+ href={getLocalizedHref(url, locale)}
155
+ hrefLang={locale ? locale : undefined}
156
+ >
157
+ {icon ? <FlightIcon name={icon} /> : null}
137
158
  {text}
138
159
  </Link>
139
160
  </NavigationMenu.Link>
@@ -3,8 +3,6 @@
3
3
  * SPDX-License-Identifier: MPL-2.0
4
4
  */
5
5
 
6
- /* Note: consumes from theme.module.css, as marked */
7
-
8
6
  .root {
9
7
  display: flex;
10
8
  padding: 0 0 0 var(--hdsplus-spacing-08);
@@ -16,7 +14,6 @@
16
14
 
17
15
  .listItem {
18
16
  position: relative;
19
- white-space: nowrap;
20
17
  margin: 0;
21
18
  padding: 0;
22
19
  }
@@ -31,7 +28,7 @@
31
28
  white-space: nowrap;
32
29
 
33
30
  &:hover {
34
- background-color: var(--menu-item-hover-color);
31
+ background-color: var(--token-color-surface-interactive-hover);
35
32
  border-radius: var(--hdsplus-spacing-01);
36
33
  }
37
34
 
@@ -42,43 +39,58 @@
42
39
  }
43
40
 
44
41
  .submenuItem {
42
+ --submenu-item-background-color: transparent;
43
+
44
+ position: relative;
45
45
  composes: hds-typography-body-200 from global;
46
46
  composes: hds-font-weight-medium from global;
47
- display: block;
48
- color: var(--menu-item-text-color); /* from theme.module.css */
47
+ color: var(--token-color-foreground-primary);
48
+ display: flex;
49
+ gap: var(--hdsplus-spacing-04);
50
+ padding: var(--hdsplus-spacing-03);
51
+ min-width: 190px;
52
+ align-items: center;
53
+
54
+ &::before {
55
+ content: "";
56
+ position: absolute;
57
+ z-index: -1;
58
+ inset: 2px 0;
59
+ border-radius: var(--hdsplus-spacing-01);
60
+ background-color: var(--submenu-item-background-color);
61
+ }
49
62
 
50
63
  &:hover {
51
- text-decoration: underline;
64
+ --submenu-item-background-color: var(--token-color-surface-interactive-hover);
65
+ }
66
+
67
+ @media (--large) {
68
+ max-width: 416px;
69
+ }
70
+
71
+ &:focus {
72
+ outline: 2px solid var(--token-color-focus-action-internal);
73
+ outline-style: auto;
52
74
  }
53
75
  }
54
76
 
55
77
  .submenuModal {
56
- border-radius: 4px;
57
- box-shadow: var(--token-elevation-high-box-shadow); /* from theme.module.css */
58
- background: var(--dropdown-background-color); /* from theme.module.css */
78
+ border-radius: var(--hdsplus-spacing-03);
79
+ border: 1px solid var(--token-color-border-primary);
80
+ box-shadow: var(--token-elevation-high-box-shadow);
81
+ background: var(--token-color-surface-primary);
59
82
  z-index: 1;
60
- display: block;
61
83
  position: absolute;
62
84
  top: 100%;
63
- margin: 8px 0 0 0;
64
- padding: 24px;
85
+ margin: var(--hdsplus-spacing-03) 0 0 0;
86
+ padding: var(--hdsplus-spacing-04);
65
87
  left: 100%;
66
88
  transform: translateX(-100%);
67
89
  list-style: none;
68
-
69
- & li {
70
- & a:hover .text {
71
- text-decoration: underline;
72
- }
73
-
74
- & + li {
75
- margin-top: 6px;
76
- }
77
- }
78
90
  }
79
91
 
80
92
  .verticalDivider {
81
- background: var(--border-color); /* from theme.module.css */
93
+ background: var(--token-color-border-primary);
82
94
  height: 1.75rem;
83
95
  width: 1px;
84
96
  margin: 0 8px;
@@ -86,6 +98,7 @@
86
98
  }
87
99
 
88
100
  .dropdownList {
101
+ min-width: max-content;
89
102
  list-style: none;
90
103
  padding: 0;
91
104
  }
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import React from 'react'
7
- import { v } from '../../../../lib/v'
7
+ import { vercelSplit } from '../../../../lib/v'
8
8
  import Link from 'next/link'
9
9
  import type { Products } from '@hashicorp/platform-product-meta'
10
10
  import CtaLinks, { type CtaLinkProps } from '../CtaLinks'
@@ -12,6 +12,8 @@ import DropdownTrigger from '../DropdownTrigger'
12
12
  import * as NavigationMenu from '@radix-ui/react-navigation-menu'
13
13
  import classNames from 'classnames'
14
14
  import s from './style.module.css'
15
+ import FlightIcon from '@hashicorp/react-hds/src/components/flight-icon'
16
+ import { getLocalizedHref } from '@web/utils/get-localized-href'
15
17
 
16
18
  interface MenuItemsOverflowProps {
17
19
  menuItems: (
@@ -19,7 +21,7 @@ interface MenuItemsOverflowProps {
19
21
  | {
20
22
  text: string
21
23
  url: string
22
- submenu: { url: string; text: string }[]
24
+ submenu: { icon: string; url: string; text: string }[]
23
25
  }
24
26
  )[]
25
27
  ctaLinks: CtaLinkProps
@@ -28,6 +30,7 @@ interface MenuItemsOverflowProps {
28
30
  menuText: string
29
31
  constrainWidth?: boolean
30
32
  activatePanel: (panel: string) => void
33
+ locale?: string
31
34
  }
32
35
 
33
36
  interface MenuItemsOverflowState {
@@ -47,6 +50,7 @@ class MenuItemsOverflow extends React.Component<
47
50
  menuText,
48
51
  constrainWidth,
49
52
  activatePanel,
53
+ locale,
50
54
  } = this.props
51
55
 
52
56
  const handleFocusOutside = () => {
@@ -89,6 +93,8 @@ class MenuItemsOverflow extends React.Component<
89
93
  key={subStableIdx}
90
94
  url={subItem.url}
91
95
  text={subItem.text}
96
+ icon={subItem.icon}
97
+ locale={locale}
92
98
  />
93
99
  ))}
94
100
  <hr className={s.divider} />
@@ -120,15 +126,23 @@ class MenuItemsOverflow extends React.Component<
120
126
  }
121
127
 
122
128
  interface SubmenuItemProps {
129
+ icon?: string
123
130
  url: string
124
131
  text: string
132
+ locale?: string
125
133
  }
126
134
 
127
- function SubmenuItem({ url, text }: SubmenuItemProps) {
135
+ function SubmenuItem({ icon, url, text, locale }: SubmenuItemProps) {
128
136
  return (
129
137
  <li>
130
138
  <NavigationMenu.Link asChild>
131
- <Link className={s.submenuItem} href={url} title={v(text)}>
139
+ <Link
140
+ className={s.submenuItem}
141
+ href={getLocalizedHref(url, locale)}
142
+ title={vercelSplit(text)}
143
+ hrefLang={locale ? locale : undefined}
144
+ >
145
+ {icon ? <FlightIcon name={icon} /> : null}
132
146
  {text}
133
147
  </Link>
134
148
  </NavigationMenu.Link>
@@ -3,8 +3,6 @@
3
3
  * SPDX-License-Identifier: MPL-2.0
4
4
  */
5
5
 
6
- /* Note: consumes from theme.module.css, as marked */
7
-
8
6
  .root {
9
7
  position: relative;
10
8
  display: flex;
@@ -12,14 +10,14 @@
12
10
  }
13
11
 
14
12
  .dropdown {
15
- background: var(--dropdown-background-color); /* from theme.module.css */
16
- border-radius: 4px;
13
+ background: var(--token-color-surface-primary);
14
+ border-radius: var(--hdsplus-spacing-03);
17
15
  box-shadow: var(--token-elevation-high-box-shadow);
18
- border: 1px solid var(--border-color);
16
+ border: 1px solid var(--token-color-border-primary);
19
17
  margin-top: 8px;
20
18
  max-height: calc(100vh - 300%);
21
19
  overflow-y: auto;
22
- padding: var(--hdsplus-spacing-04) var(--hdsplus-spacing-07);
20
+ padding: var(--hdsplus-spacing-04);
23
21
  position: absolute;
24
22
  right: 0;
25
23
  top: 100%;
@@ -52,27 +50,35 @@
52
50
 
53
51
  .submenuTitle {
54
52
  composes: g-type-label from global;
55
- margin: 12px 0 8px 0;
56
- color: var(--menu-item-heading-text-color); /* from theme.module.css */
53
+ margin: var(--hdsplus-spacing-04) var(--hdsplus-spacing-03) 8px;
54
+ color: var(--token-color-foreground-faint);
57
55
  }
58
56
 
59
57
  .divider {
60
- margin: 12px 0;
58
+ margin: var(--hdsplus-spacing-04) var(--hdsplus-spacing-03);
61
59
  border: 0;
62
60
  padding: 0;
63
61
  height: 1px;
64
- background: var(--border-color); /* from theme.module.css */
62
+ background: var(--token-color-border-primary);
65
63
  }
66
64
 
67
65
  .submenuItem {
68
- display: block;
69
- padding: 4px 0;
70
- color: var(--menu-item-text-color); /* from theme.module.css */
71
- font-weight: var(--font-weight-semi-bold);
72
- font-size: var(--token-typography-body-300-font-size);
66
+ composes: hds-typography-body-300 from global;
67
+ composes: hds-font-weight-semibold from global;
68
+ display: flex;
69
+ gap: var(--hdsplus-spacing-04);
70
+ padding: var(--hdsplus-spacing-02) var(--hdsplus-spacing-03);
71
+ color: var(--token-color-foreground-primary);
72
+ border-radius: var(--hdsplus-spacing-01);
73
+ align-items: center;
73
74
 
74
75
  &:hover {
75
- text-decoration: underline;
76
+ background-color: var(--token-color-surface-interactive-hover);
77
+ }
78
+
79
+ &:focus {
80
+ outline: 2px solid var(--token-color-focus-action-internal);
81
+ outline-style: auto;
76
82
  }
77
83
  }
78
84
 
@@ -7,7 +7,7 @@ import { forwardRef } from 'react'
7
7
  import { camelCase } from 'camel-case'
8
8
  import Link from 'next/link'
9
9
  import Image from 'next/image'
10
- import { v } from '../../../../lib/v'
10
+ import { vercelSplit } from '../../../../lib/v'
11
11
  import classNames from 'classnames'
12
12
  import * as CommunityProductLogosOnDark from './mktg-logos/all-community-product-logos_on-dark'
13
13
  import * as CommunityProductLogosOnLight from './mktg-logos/all-community-product-logos_on-light'
@@ -41,6 +41,7 @@ const logoDict = {
41
41
  }
42
42
 
43
43
  interface TitleLinkProps {
44
+ locale?: string
44
45
  text: string
45
46
  url: string
46
47
  product?: string
@@ -80,8 +81,8 @@ function getLogo(
80
81
  }
81
82
 
82
83
  const TitleLink = forwardRef<HTMLAnchorElement, TitleLinkProps>(
83
- ({ text, url, product, theme }, ref) => {
84
- const parsedText = v(text)
84
+ ({ text, url, product, theme, locale }, ref) => {
85
+ const parsedText = vercelSplit(text)
85
86
  const Logo = getLogo(parsedText, theme)
86
87
 
87
88
  return (
@@ -94,6 +95,7 @@ const TitleLink = forwardRef<HTMLAnchorElement, TitleLinkProps>(
94
95
  href={url}
95
96
  title={parsedText}
96
97
  ref={ref}
98
+ hrefLang={locale ? locale : undefined}
97
99
  >
98
100
  {Logo ? (
99
101
  <Image
@@ -5,5 +5,6 @@ import packer from '@hashicorp/web-mktg-logos/src/packer/packer-community/packer
5
5
  import terraform from '@hashicorp/web-mktg-logos/src/terraform/terraform-community/terraform-community_on-dark.svg'
6
6
  import vagrant from '@hashicorp/web-mktg-logos/src/vagrant/vagrant-community/vagrant-community_on-dark.svg'
7
7
  import vault from '@hashicorp/web-mktg-logos/src/vault/vault-community/vault-community_on-dark.svg'
8
+ import waypoint from '@hashicorp/web-mktg-logos/src/waypoint/hashicorp-waypoint-attributed/hashicorp-waypoint_on-dark.svg'
8
9
 
9
- export { boundary, consul, nomad, packer, terraform, vagrant, vault }
10
+ export { boundary, consul, nomad, packer, terraform, vagrant, vault, waypoint }