@hashicorp/react-components 0.0.0-canary.fa24a72 → 0.0.0-nightly.0a567ac

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 (28) hide show
  1. package/package.json +2 -2
  2. package/src/components/nav-panel/components/link-list/index.tsx +6 -5
  3. package/src/components/nav-panel/components/panel/column/style.module.css +2 -2
  4. package/src/components/nav-panel/components/panel/root/style.module.css +1 -1
  5. package/src/components/nav-panel/components/promo/index.tsx +6 -6
  6. package/src/components/nav-panel/components/promo/style.module.css +3 -2
  7. package/src/components/nav-panel/product-panel/index.tsx +9 -3
  8. package/src/components/nav-panel/product-panel/style.module.css +41 -22
  9. package/src/components/nav-panel/standard-panel/style.module.css +1 -1
  10. package/src/components/subnav/index.tsx +2 -2
  11. package/src/components/subnav/partials/CtaLinks/github-stars-link/style.module.css +8 -12
  12. package/src/components/subnav/partials/CtaLinks/style.module.css +4 -4
  13. package/src/components/subnav/partials/DropdownTrigger/index.tsx +1 -1
  14. package/src/components/subnav/partials/DropdownTrigger/style.module.css +7 -4
  15. package/src/components/subnav/partials/MenuItemsDefault/index.tsx +10 -3
  16. package/src/components/subnav/partials/MenuItemsDefault/style.module.css +37 -24
  17. package/src/components/subnav/partials/MenuItemsOverflow/index.tsx +8 -4
  18. package/src/components/subnav/partials/MenuItemsOverflow/style.module.css +22 -16
  19. package/src/components/subnav/partials/TitleLink/index.tsx +2 -2
  20. package/src/components/subnav/partials/TitleLink/mktg-logos/all-community-product-logos_on-dark.ts +2 -1
  21. package/src/components/subnav/partials/TitleLink/mktg-logos/all-community-product-logos_on-light.ts +2 -1
  22. package/src/components/subnav/partials/TitleLink/style.module.css +1 -1
  23. package/src/components/subnav/partials/nav-item-text/style.module.css +2 -4
  24. package/src/components/subnav/style.module.css +3 -5
  25. package/src/lib/parse-url/index.test.ts +5 -0
  26. package/src/lib/parse-url/index.ts +4 -2
  27. package/src/lib/v/index.ts +4 -5
  28. package/src/components/subnav/theme.module.css +0 -50
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hashicorp/react-components",
3
- "version": "0.0.0-canary.fa24a72",
3
+ "version": "0.0.0-nightly.0a567ac",
4
4
  "main": "src/index.ts",
5
5
  "scripts": {
6
6
  "lint": "next-hashicorp lint",
@@ -24,7 +24,7 @@
24
24
  "react-hook-form": "^7.43.5"
25
25
  },
26
26
  "devDependencies": {
27
- "@hashicorp/platform-cli": "^2.6.0",
27
+ "@hashicorp/platform-cli": "^2.8.0",
28
28
  "@hashicorp/platform-types": "^0.4.0",
29
29
  "@testing-library/jest-dom": "^6.4.2",
30
30
  "@vitejs/plugin-react": "^4.2.1",
@@ -1,6 +1,6 @@
1
1
  import Link from 'next/link'
2
2
  import { parseUrl } from '../../../../lib/parse-url'
3
- import { v } from '../../../../lib/v'
3
+ import { vercelSplit } from '../../../../lib/v'
4
4
  import FlightIcon from '@hashicorp/react-design-system-components/src/components/flight-icon'
5
5
  import * as NavigationMenu from '@radix-ui/react-navigation-menu'
6
6
  import s from './style.module.css'
@@ -44,8 +44,9 @@ export default function LinkList({ links, linkClickHandler }: LinkListProps) {
44
44
  let style
45
45
  link.iconGradient
46
46
  ? (style = {
47
- '--iconGradient': GRADIENT_VALUE_MAP.get(v(link.iconGradient))
48
- ?.iconGradient,
47
+ '--iconGradient': GRADIENT_VALUE_MAP.get(
48
+ vercelSplit(link.iconGradient)
49
+ )?.iconGradient,
49
50
  } as React.CSSProperties)
50
51
  : (style = null)
51
52
  return (
@@ -60,12 +61,12 @@ export default function LinkList({ links, linkClickHandler }: LinkListProps) {
60
61
  >
61
62
  {link.iconGradient && link.icon ? (
62
63
  <div className={s.iconBackground} style={style}>
63
- <FlightIcon name={v(link.icon)} />
64
+ <FlightIcon name={vercelSplit(link.icon)} />
64
65
  </div>
65
66
  ) : (
66
67
  link.icon && (
67
68
  <FlightIcon
68
- name={v(link.icon)}
69
+ name={vercelSplit(link.icon)}
69
70
  color="var(--token-color-foreground-faint)"
70
71
  />
71
72
  )
@@ -1,4 +1,4 @@
1
- @custom-media --dev-dot-viewport (min-width: 1210px);
1
+ @custom-media --dev-dot-viewport (min-width: 924px);
2
2
 
3
3
  .column {
4
4
  position: relative;
@@ -7,7 +7,7 @@
7
7
  justify-content: flex-start;
8
8
  min-width: 190px;
9
9
  padding: 0;
10
- margin: 0 var(--hdsplus-spacing-05);
10
+ margin: 0 var(--hdsplus-spacing-07);
11
11
  border-radius: var(--hdsplus-spacing-03);
12
12
 
13
13
  @media (--large) {
@@ -1,4 +1,4 @@
1
- @custom-media --dev-dot-viewport (min-width: 1210px);
1
+ @custom-media --dev-dot-viewport (min-width: 924px);
2
2
 
3
3
  .root {
4
4
  width: 100%;
@@ -1,6 +1,6 @@
1
1
  import { useCallback } from 'react'
2
2
  import classNames from 'classnames'
3
- import { v } from '../../../../lib/v'
3
+ import { vercelSplit } from '../../../../lib/v'
4
4
  import Link from 'next/link'
5
5
  import { parseUrl } from '../../../../lib/parse-url'
6
6
  import { trackNavClickEvent } from '../../../../lib/track-nav-click-event'
@@ -51,19 +51,19 @@ export default function Promo({
51
51
  {icon && (
52
52
  <div
53
53
  className={classNames(s.icon, {
54
- [s.hashidays]: v(theme) === 'hashidays',
55
- [s.hashiconf]: v(theme) === 'hashiconf',
54
+ [s.hashidays]: vercelSplit(theme) === 'hashidays',
55
+ [s.hashiconf]: vercelSplit(theme) === 'hashiconf',
56
56
  })}
57
57
  >
58
- <FlightIcon name={v(icon)} />
58
+ <FlightIcon name={vercelSplit(icon)} />
59
59
  </div>
60
60
  )}
61
61
  <div className={s.rightContent}>
62
62
  <div>
63
63
  <div
64
64
  className={classNames(s.title, {
65
- [s.hashidays]: v(theme) === 'hashidays',
66
- [s.hashiconf]: v(theme) === 'hashiconf',
65
+ [s.hashidays]: vercelSplit(theme) === 'hashidays',
66
+ [s.hashiconf]: vercelSplit(theme) === 'hashiconf',
67
67
  })}
68
68
  >
69
69
  {title}
@@ -1,4 +1,4 @@
1
- @custom-media --dev-dot-viewport (min-width: 1210px);
1
+ @custom-media --dev-dot-viewport (min-width: 924px);
2
2
 
3
3
  .promo {
4
4
  display: flex;
@@ -9,7 +9,8 @@
9
9
  var(--hdsplus-spacing-06) var(--hdsplus-spacing-08);
10
10
  flex-direction: row;
11
11
  gap: var(--hdsplus-spacing-04);
12
- margin: var(--hdsplus-spacing-05);
12
+ margin: var(--hdsplus-spacing-07);
13
+ margin-bottom: var(--hdsplus-spacing-09);
13
14
 
14
15
  @media (--large) {
15
16
  &.noSide {
@@ -1,3 +1,4 @@
1
+ import classNames from 'classnames'
1
2
  import Link from 'next/link'
2
3
  import * as NavPanel from '../components/panel'
3
4
  import Promo, { type PromoProps } from '../components/promo'
@@ -8,10 +9,9 @@ import { parseUrl } from '../../../lib/parse-url'
8
9
  import { trackNavClickEvent } from '../../../lib/track-nav-click-event'
9
10
  import * as NavigationMenu from '@radix-ui/react-navigation-menu'
10
11
  import s from './style.module.css'
11
- import classNames from 'classnames'
12
12
 
13
13
  const PRODUCT_LOGO_MAP = new Map([
14
- ['Terraform', 'terraform-fill-color'],
14
+ ['Terraform', 'terraform-fill'],
15
15
  ['Packer', 'packer-fill-color'],
16
16
  ['Vault', 'vault-fill-color'],
17
17
  ['Boundary', 'boundary-fill-color'],
@@ -24,6 +24,7 @@ const PRODUCT_LOGO_MAP = new Map([
24
24
  ])
25
25
 
26
26
  const PRODUCT_LOGO_EXCEPTION_CLASSNAMES = {
27
+ Terraform: 'terraform',
27
28
  'HCP Vault Secrets': 'hcpVaultSecrets',
28
29
  'HCP Vault Radar': 'hcpVaultRadar',
29
30
  }
@@ -94,7 +95,11 @@ const ProductPanel = ({
94
95
  {sidePanel.navItems.map(({ icon, title, description, url }) => {
95
96
  return (
96
97
  <li key={title}>
97
- <Link href={parseUrl(url).href} className={s.sidePanelItem}>
98
+ <Link
99
+ aria-label={`${title} - ${description}`}
100
+ href={parseUrl(url).href}
101
+ className={classNames(s.sidePanelItem, s.focusIndicator)}
102
+ >
98
103
  <div className={s.iconBackground}>
99
104
  <FlightIcon
100
105
  size={16}
@@ -129,6 +134,7 @@ function NavProduct({ url, product, description }: NavProductProps) {
129
134
  return (
130
135
  <NavigationMenu.Link asChild>
131
136
  <Link
137
+ aria-label={`${product} - ${description}`}
132
138
  href={parseUrl(url).href}
133
139
  onClickCapture={() => {
134
140
  trackNavClickEvent(product, url, 'products')
@@ -1,4 +1,4 @@
1
- @custom-media --dev-dot-viewport (min-width: 1210px);
1
+ @custom-media --dev-dot-viewport (min-width: 924px);
2
2
 
3
3
  .productPanel {
4
4
  height: 100%;
@@ -26,7 +26,7 @@
26
26
  list-style: none;
27
27
  padding: 0;
28
28
  display: grid;
29
- margin: var(--hdsplus-spacing-06) 0 0;
29
+ margin: var(--hdsplus-spacing-07) 0 0;
30
30
 
31
31
  @media (--large) {
32
32
  @nest .noSide & {
@@ -61,14 +61,14 @@
61
61
  @media (--large) {
62
62
  @nest .noSide & {
63
63
  padding-bottom: 0;
64
- padding-left: var(--hdsplus-spacing-06);
64
+ padding-left: var(--hdsplus-spacing-06);
65
65
  }
66
66
  }
67
67
 
68
68
  @media (--dev-dot-viewport) {
69
69
  @nest .hasSide & {
70
70
  padding-bottom: 0;
71
- padding-left: var(--hdsplus-spacing-06);
71
+ padding-left: var(--hdsplus-spacing-06);
72
72
  }
73
73
  }
74
74
  }
@@ -83,22 +83,28 @@
83
83
  @media (--large) {
84
84
  @nest .noSide & {
85
85
  padding: var(--hdsplus-spacing-06) var(--hdsplus-spacing-05)
86
- var(--hdsplus-spacing-04);
87
- grid-auto-flow: row;
88
- grid-template-columns: repeat(2, 300px);
89
- grid-template-rows: repeat(2, max-content);
90
- gap: 0;
86
+ var(--hdsplus-spacing-04);
87
+ grid-auto-flow: row;
88
+ grid-template-columns: repeat(2, 300px);
89
+ grid-template-rows: repeat(2, max-content);
90
+ gap: 0;
91
91
  }
92
92
  }
93
93
 
94
94
  @media (--dev-dot-viewport) {
95
95
  @nest .hasSide & {
96
96
  padding: var(--hdsplus-spacing-06) var(--hdsplus-spacing-05)
97
- var(--hdsplus-spacing-04);
98
- grid-auto-flow: row;
99
- grid-template-columns: repeat(2, 300px);
100
- grid-template-rows: repeat(2, max-content);
101
- gap: 0;
97
+ var(--hdsplus-spacing-04);
98
+ grid-auto-flow: row;
99
+ grid-template-columns: repeat(2, 300px);
100
+ grid-template-rows: repeat(2, max-content);
101
+ gap: 0;
102
+ }
103
+ }
104
+
105
+ & li:last-child {
106
+ & .productWrapper {
107
+ margin-bottom: 0;
102
108
  }
103
109
  }
104
110
  }
@@ -113,7 +119,7 @@
113
119
  @media (--large) {
114
120
  @nest .noSide & {
115
121
  padding: var(--hdsplus-spacing-03) var(--hdsplus-spacing-05);
116
- margin-bottom: 0;
122
+ margin-bottom: 0;
117
123
 
118
124
  &:hover {
119
125
  background-color: var(--token-color-surface-interactive-hover);
@@ -125,7 +131,7 @@
125
131
  @media (--dev-dot-viewport) {
126
132
  @nest .hasSide & {
127
133
  padding: var(--hdsplus-spacing-03) var(--hdsplus-spacing-05);
128
- margin-bottom: 0;
134
+ margin-bottom: 0;
129
135
 
130
136
  &:hover {
131
137
  background-color: var(--token-color-surface-interactive-hover);
@@ -191,15 +197,15 @@
191
197
 
192
198
  @media (--large) {
193
199
  @nest .noSide & {
194
- padding: var(--hdsplus-spacing-07) 0 var(--hdsplus-spacing-05)
195
- var(--hdsplus-spacing-04);
200
+ padding: var(--hdsplus-spacing-07) 0 var(--hdsplus-spacing-09)
201
+ var(--hdsplus-spacing-04);
196
202
  }
197
203
  }
198
204
 
199
205
  @media (--dev-dot-viewport) {
200
206
  @nest .hasSide & {
201
- padding: var(--hdsplus-spacing-07) 0 var(--hdsplus-spacing-05)
202
- var(--hdsplus-spacing-04);
207
+ padding: var(--hdsplus-spacing-07) 0 var(--hdsplus-spacing-09)
208
+ var(--hdsplus-spacing-04);
203
209
  }
204
210
  }
205
211
  }
@@ -231,12 +237,10 @@
231
237
  /* Lifted from .productWrapper */
232
238
  .sidePanelItem {
233
239
  display: flex;
234
- margin-bottom: var(--hdsplus-spacing-05);
235
240
  gap: var(--hdsplus-spacing-05);
236
241
 
237
242
  @media (--dev-dot-viewport) {
238
243
  padding: var(--hdsplus-spacing-03) var(--hdsplus-spacing-05);
239
- margin-bottom: 0;
240
244
 
241
245
  &:hover {
242
246
  background-color: var(--token-color-surface-interactive-hover);
@@ -276,6 +280,21 @@ packages/react-components/src/components/nav-panel/components/link-list/style.mo
276
280
 
277
281
  /* Branding exception classnames */
278
282
 
283
+ /* Allows switching to a dark-mode-specific color for Terraform */
284
+ .terraform {
285
+ & use {
286
+ fill: var(--token-color-terraform-brand);
287
+
288
+ @nest [data-theme='dark'] & {
289
+ fill: var(--token-color-terraform-foreground);
290
+ }
291
+ }
292
+
293
+ & path {
294
+ fill: inherit;
295
+ }
296
+ }
297
+
279
298
  /* Styles for HCP Vault mimic the spec for `product-square` icons,
280
299
  while allowing the symbol inside the icon border to change color
281
300
  based on the site's theme
@@ -2,7 +2,7 @@
2
2
  display: flex;
3
3
  gap: var(--hdsplus-spacing-03);
4
4
  flex-direction: column;
5
- margin-top: var(--hdsplus-spacing-06);
5
+ margin-top: var(--hdsplus-spacing-07);
6
6
 
7
7
  @media (--large) {
8
8
  flex-direction: row;
@@ -17,7 +17,6 @@ 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'
22
21
 
23
22
  const productAllowList = {
@@ -175,9 +174,10 @@ function Subnav({ className, theme = 'light', ...restProps }: SubnavProps) {
175
174
  <style>{`:root{--subnav-height:${height}px}`}</style>
176
175
  <NavigationMenu.Root
177
176
  ref={wrapperRef}
178
- className={classNames(s.root, themeStyles[theme], className, {
177
+ className={classNames(s.root, className, {
179
178
  [s.isSticky]: isSticky,
180
179
  [s.hasOverflow]: hasOverflow,
180
+ 'hdsplus-dark-mode': theme === 'dark',
181
181
  })}
182
182
  aria-label={`${product} website navigation`}
183
183
  onValueChange={activatePanel}
@@ -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
 
@@ -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);
@@ -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,13 +9,19 @@ 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-design-system-components/src/components/flight-icon'
12
13
 
13
14
  interface MenuItemsDefaultProps {
14
15
  menuItems: (
15
16
  | {
16
17
  text: string
17
18
  url: string
18
- submenu: { text: string; url: string; _isActiveUrl: string }[]
19
+ submenu: {
20
+ icon: string
21
+ text: string
22
+ url: string
23
+ _isActiveUrl: string
24
+ }[]
19
25
  _isActiveUrl: boolean
20
26
  }
21
27
  | 'divider'
@@ -86,7 +92,7 @@ function NavLink(props: NavLinkProps) {
86
92
 
87
93
  interface NavLinkWithDropdownProps {
88
94
  text: string
89
- submenu: { text: string; url: string; _isActiveUrl: string }[]
95
+ submenu: { icon: string; text: string; url: string; _isActiveUrl: string }[]
90
96
  activatePanel: (panel: string) => void
91
97
  }
92
98
 
@@ -128,12 +134,13 @@ class NavLinkWithDropdown extends React.Component<
128
134
  <NavigationMenu.Sub>
129
135
  <NavigationMenu.List className={s.dropdownList}>
130
136
  {submenu.map((submenuItem, stableIdx) => {
131
- const { text, url } = submenuItem
137
+ const { icon, text, url } = submenuItem
132
138
  return (
133
139
  // eslint-disable-next-line react/no-array-index-key
134
140
  <NavigationMenu.Item key={stableIdx}>
135
141
  <NavigationMenu.Link asChild>
136
142
  <Link className={s.submenuItem} href={url}>
143
+ {icon ? <FlightIcon name={icon} /> : null}
137
144
  {text}
138
145
  </Link>
139
146
  </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,7 @@ 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-design-system-components/src/components/flight-icon'
15
16
 
16
17
  interface MenuItemsOverflowProps {
17
18
  menuItems: (
@@ -19,7 +20,7 @@ interface MenuItemsOverflowProps {
19
20
  | {
20
21
  text: string
21
22
  url: string
22
- submenu: { url: string; text: string }[]
23
+ submenu: { icon: string; url: string; text: string }[]
23
24
  }
24
25
  )[]
25
26
  ctaLinks: CtaLinkProps
@@ -89,6 +90,7 @@ class MenuItemsOverflow extends React.Component<
89
90
  key={subStableIdx}
90
91
  url={subItem.url}
91
92
  text={subItem.text}
93
+ icon={subItem.icon}
92
94
  />
93
95
  ))}
94
96
  <hr className={s.divider} />
@@ -120,15 +122,17 @@ class MenuItemsOverflow extends React.Component<
120
122
  }
121
123
 
122
124
  interface SubmenuItemProps {
125
+ icon?: string
123
126
  url: string
124
127
  text: string
125
128
  }
126
129
 
127
- function SubmenuItem({ url, text }: SubmenuItemProps) {
130
+ function SubmenuItem({ icon, url, text }: SubmenuItemProps) {
128
131
  return (
129
132
  <li>
130
133
  <NavigationMenu.Link asChild>
131
- <Link className={s.submenuItem} href={url} title={v(text)}>
134
+ <Link className={s.submenuItem} href={url} title={vercelSplit(text)}>
135
+ {icon ? <FlightIcon name={icon} /> : null}
132
136
  {text}
133
137
  </Link>
134
138
  </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'
@@ -81,7 +81,7 @@ function getLogo(
81
81
 
82
82
  const TitleLink = forwardRef<HTMLAnchorElement, TitleLinkProps>(
83
83
  ({ text, url, product, theme }, ref) => {
84
- const parsedText = v(text)
84
+ const parsedText = vercelSplit(text)
85
85
  const Logo = getLogo(parsedText, theme)
86
86
 
87
87
  return (
@@ -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 }
@@ -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-light.svg'
6
6
  import vagrant from '@hashicorp/web-mktg-logos/src/vagrant/vagrant-community/vagrant-community_on-light.svg'
7
7
  import vault from '@hashicorp/web-mktg-logos/src/vault/vault-community/vault-community_on-light.svg'
8
+ import waypoint from '@hashicorp/web-mktg-logos/src/waypoint/hashicorp-waypoint-attributed/hashicorp-waypoint_on-light.svg'
8
9
 
9
- export { boundary, consul, nomad, packer, terraform, vagrant, vault }
10
+ export { boundary, consul, nomad, packer, terraform, vagrant, vault, waypoint }
@@ -10,7 +10,7 @@
10
10
  display: inline-flex;
11
11
  padding-block: var(--hdsplus-spacing-04);
12
12
  font-weight: var(--font-weight-bold);
13
- color: var(--title-text-color); /* from theme.module.css */
13
+ color: var(--token-color-foreground-primary); /* from theme.module.css */
14
14
  font-size: 1.25rem;
15
15
  line-height: 1.35rem;
16
16
 
@@ -3,13 +3,11 @@
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
- color: var(--menu-item-text-color); /* from theme.module.css */
7
+ color: var(--token-color-foreground-primary);
10
8
  position: relative;
11
9
 
12
10
  &.isActive {
13
- color: var(--menu-item-text-color-active);
11
+ color: var(--token-color-foreground-strong);
14
12
  }
15
13
  }
@@ -3,19 +3,17 @@
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: sticky;
10
8
  top: -1px;
11
9
  z-index: 900;
12
- background: var(--background-color); /* from theme.module.css */
13
- border-top: 1px solid var(--border-color); /* from theme.module.css */
10
+ background: var(--token-color-surface-primary);
11
+ border-top: 1px solid var(--token-color-border-faint);
14
12
  border-bottom: 1px solid transparent;
15
13
  transition: border-bottom-color 0.8s;
16
14
 
17
15
  &.isSticky {
18
- border-bottom-color: var(--border-color); /* from theme.module.css */
16
+ border-bottom-color: var(--token-color-border-faint);
19
17
  }
20
18
 
21
19
  /*
@@ -27,4 +27,9 @@ describe('parseUrl', () => {
27
27
  )
28
28
  expect(url.href).toBe('/resources?type=case-study&products=terraform')
29
29
  })
30
+
31
+ it('leaves HashiCorp subdomain URLs intact', () => {
32
+ const url = parseUrl('https://developer.hashicorp.com/terraform')
33
+ expect(url.href).toBe('https://developer.hashicorp.com/terraform')
34
+ })
30
35
  })
@@ -26,5 +26,7 @@ export function parseUrl(url: string | undefined): {
26
26
  const isRelative = (url) => url.startsWith('/')
27
27
  const isAnchor = (url) => url.startsWith('#')
28
28
 
29
- export const isInternal = (url) =>
30
- new URL(url).hostname.includes('hashicorp.com')
29
+ export const isInternal = (url) => {
30
+ const hostname = new URL(url).hostname
31
+ return hostname === 'hashicorp.com'
32
+ }
@@ -3,9 +3,8 @@ import { vercelStegaSplit } from '@vercel/stega'
3
3
  /**
4
4
  * Takes in a Vercel Visual Editing string and returns the string without
5
5
  * hidden data.
6
+ *
6
7
  */
7
- export function v<VercelVEString extends string>(
8
- s: VercelVEString
9
- ): VercelVEString {
10
- return vercelStegaSplit(s).cleaned as VercelVEString
11
- }
8
+ export const vercelSplit = <VercelString>(
9
+ original: VercelString
10
+ ): VercelString => vercelStegaSplit(original as string).cleaned as VercelString
@@ -1,50 +0,0 @@
1
- /**
2
- * Copyright (c) HashiCorp, Inc.
3
- * SPDX-License-Identifier: MPL-2.0
4
- */
5
-
6
- /*
7
- Theme settings.
8
- Consumed in nearly all CSS files in this component,
9
- including in /partials.
10
- */
11
-
12
- .light {
13
- /* main */
14
- --background-color: var(--white);
15
- --border-color: var(--gray-5);
16
- --dropdown-background-color: var(--white);
17
-
18
- /* title or logo link */
19
- --title-text-color: var(--gray-1);
20
-
21
- /* github-stars-link */
22
- --gh-stars-icon-color: var(--black);
23
- --gh-stars-scrim-color: rgba(0, 0, 0, 0.1);
24
-
25
- /* menu items */
26
- --menu-item-text-color: #3B3D45;
27
- --menu-item-text-color-active: #0C0C0E;
28
- --menu-item-heading-text-color: var(--gray-3);
29
- --menu-item-hover-color: #F1F2F3;
30
- }
31
-
32
- .dark {
33
- /* main */
34
- --background-color: var(--black);
35
- --border-color: var(--gray-2);
36
- --dropdown-background-color: var(--gray-1);
37
-
38
- /* title or logo link */
39
- --title-text-color: var(--white);
40
-
41
- /* github-stars-link */
42
- --gh-stars-icon-color: var(--white);
43
- --gh-stars-scrim-color: rgba(255, 255, 255, 0.15);
44
-
45
- /* menu items */
46
- --menu-item-text-color: #D5D7DB;
47
- --menu-item-text-color-active: #EFEFF1;
48
- --menu-item-heading-text-color: var(--gray-4);
49
- --menu-item-hover-color: #1E222A;
50
- }