@hashicorp/react-components 0.0.0-nightly.0cf11a1 → 0.0.0-nightly.10f9286

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 (164) hide show
  1. package/package.json +5 -9
  2. package/src/components/nav-panel/components/flight-icon/index.tsx +51 -0
  3. package/src/components/nav-panel/components/flight-icon/style.module.css +3 -0
  4. package/src/components/nav-panel/components/link-list/index.tsx +15 -9
  5. package/src/components/nav-panel/components/link-list/style.module.css +10 -10
  6. package/src/components/nav-panel/components/panel/column/index.tsx +15 -2
  7. package/src/components/nav-panel/components/panel/column/style.module.css +13 -3
  8. package/src/components/nav-panel/components/panel/root/index.tsx +11 -2
  9. package/src/components/nav-panel/components/panel/root/style.module.css +20 -6
  10. package/src/components/nav-panel/components/promo/index.tsx +23 -10
  11. package/src/components/nav-panel/components/promo/style.module.css +52 -16
  12. package/src/components/nav-panel/components/text/index.tsx +34 -0
  13. package/src/components/nav-panel/product-panel/index.tsx +50 -17
  14. package/src/components/nav-panel/product-panel/style.module.css +184 -45
  15. package/src/components/nav-panel/standard-panel/index.tsx +3 -0
  16. package/src/components/nav-panel/standard-panel/style.module.css +2 -2
  17. package/src/lib/get-localized-link-props/index.test.ts +30 -0
  18. package/src/lib/get-localized-link-props/index.ts +45 -0
  19. package/src/lib/parse-url/index.test.ts +40 -1
  20. package/src/lib/parse-url/index.ts +74 -9
  21. package/src/lib/send-posthog-event/index.ts +22 -0
  22. package/src/lib/supported-locales/index.ts +10 -0
  23. package/src/lib/track-nav-click-event/index.ts +4 -4
  24. package/src/lib/v/index.ts +4 -5
  25. package/src/components/actions/index.tsx +0 -107
  26. package/src/components/actions/style.module.css +0 -28
  27. package/src/components/actions/types.ts +0 -73
  28. package/src/components/call-to-action/index.tsx +0 -205
  29. package/src/components/call-to-action/styles/variant-centered.module.css +0 -93
  30. package/src/components/call-to-action/styles/variant-compact-grid.module.css +0 -88
  31. package/src/components/call-to-action/styles/variant-compact.module.css +0 -91
  32. package/src/components/call-to-action/styles/variant-links.module.css +0 -85
  33. package/src/components/card/README.md +0 -11
  34. package/src/components/card/card.tsx +0 -45
  35. package/src/components/card/index.test.tsx +0 -69
  36. package/src/components/card/index.tsx +0 -14
  37. package/src/components/card/newsroom-card/index.test.tsx +0 -39
  38. package/src/components/card/newsroom-card/index.tsx +0 -37
  39. package/src/components/card/newsroom-card/style.module.css +0 -12
  40. package/src/components/card/partner-card/index.test.tsx +0 -57
  41. package/src/components/card/partner-card/index.tsx +0 -69
  42. package/src/components/card/partner-card/style.module.css +0 -24
  43. package/src/components/card/person-card/index.test.tsx +0 -71
  44. package/src/components/card/person-card/index.tsx +0 -93
  45. package/src/components/card/person-card/style.module.css +0 -33
  46. package/src/components/card/primitives.tsx +0 -176
  47. package/src/components/card/promo-card/index.tsx +0 -51
  48. package/src/components/card/resource-card/index.test.tsx +0 -48
  49. package/src/components/card/resource-card/index.tsx +0 -37
  50. package/src/components/card/style.module.css +0 -145
  51. package/src/components/card/types.ts +0 -66
  52. package/src/components/card/unified-card/index.tsx +0 -64
  53. package/src/components/consent-manager/README.md +0 -73
  54. package/src/components/consent-manager/components/banner/banner.module.css +0 -23
  55. package/src/components/consent-manager/components/banner/banner.test.tsx +0 -31
  56. package/src/components/consent-manager/components/banner/banner.tsx +0 -73
  57. package/src/components/consent-manager/components/dialog/dialog.module.css +0 -145
  58. package/src/components/consent-manager/components/dialog/dialog.test.tsx +0 -194
  59. package/src/components/consent-manager/components/dialog/dialog.tsx +0 -339
  60. package/src/components/consent-manager/img/icn_close.tsx +0 -19
  61. package/src/components/consent-manager/index.test.tsx +0 -334
  62. package/src/components/consent-manager/index.tsx +0 -186
  63. package/src/components/consent-manager/loader/README.md +0 -29
  64. package/src/components/consent-manager/loader/categories.ts +0 -22
  65. package/src/components/consent-manager/loader/index.tsx +0 -94
  66. package/src/components/consent-manager/loader/presets/enterprise.ts +0 -12
  67. package/src/components/consent-manager/loader/presets/oss.ts +0 -10
  68. package/src/components/consent-manager/loader/services.ts +0 -45
  69. package/src/components/consent-manager/scripts/custom.tsx +0 -59
  70. package/src/components/consent-manager/scripts/segment.tsx +0 -87
  71. package/src/components/consent-manager/style.module.css +0 -9
  72. package/src/components/consent-manager/types.ts +0 -55
  73. package/src/components/consent-manager/util/cookies.test.ts +0 -75
  74. package/src/components/consent-manager/util/cookies.ts +0 -70
  75. package/src/components/consent-manager/util/integrations.test.ts +0 -115
  76. package/src/components/consent-manager/util/integrations.ts +0 -110
  77. package/src/components/intro/index.tsx +0 -82
  78. package/src/components/intro/style.module.css +0 -67
  79. package/src/components/intro/types.ts +0 -44
  80. package/src/components/marketo-form/CHANGELOG.md +0 -122
  81. package/src/components/marketo-form/README.md +0 -1
  82. package/src/components/marketo-form/contexts/FormMetadata.ts +0 -11
  83. package/src/components/marketo-form/docs.mdx +0 -197
  84. package/src/components/marketo-form/fixtures/index.ts +0 -185
  85. package/src/components/marketo-form/form/index.tsx +0 -369
  86. package/src/components/marketo-form/index.test.tsx +0 -320
  87. package/src/components/marketo-form/index.ts +0 -11
  88. package/src/components/marketo-form/package.original.json +0 -30
  89. package/src/components/marketo-form/partials/error-message/index.tsx +0 -12
  90. package/src/components/marketo-form/partials/error-message/style.module.css +0 -13
  91. package/src/components/marketo-form/partials/field/index.tsx +0 -90
  92. package/src/components/marketo-form/partials/field-wrapper/index.tsx +0 -26
  93. package/src/components/marketo-form/partials/fields/checkbox-field/index.tsx +0 -32
  94. package/src/components/marketo-form/partials/fields/email-field/index.tsx +0 -35
  95. package/src/components/marketo-form/partials/fields/form-page-url-field/index.tsx +0 -21
  96. package/src/components/marketo-form/partials/fields/hidden-field/index.tsx +0 -37
  97. package/src/components/marketo-form/partials/fields/htmltext-field/index.tsx +0 -21
  98. package/src/components/marketo-form/partials/fields/htmltext-field/style.module.css +0 -18
  99. package/src/components/marketo-form/partials/fields/name-field/index.tsx +0 -19
  100. package/src/components/marketo-form/partials/fields/name-field/style.module.css +0 -13
  101. package/src/components/marketo-form/partials/fields/radio-buttons-field/index.tsx +0 -48
  102. package/src/components/marketo-form/partials/fields/select-field/index.tsx +0 -39
  103. package/src/components/marketo-form/partials/fields/select-field/style.module.css +0 -5
  104. package/src/components/marketo-form/partials/fields/telephone-field/index.tsx +0 -30
  105. package/src/components/marketo-form/partials/fields/text-field/index.tsx +0 -30
  106. package/src/components/marketo-form/partials/fields/textarea-field/index.tsx +0 -29
  107. package/src/components/marketo-form/partials/label/index.tsx +0 -24
  108. package/src/components/marketo-form/partials/label/style.module.css +0 -12
  109. package/src/components/marketo-form/partials/visibility-rule/index.tsx +0 -84
  110. package/src/components/marketo-form/props.js +0 -66
  111. package/src/components/marketo-form/server/api-routes.ts +0 -109
  112. package/src/components/marketo-form/server/client.ts +0 -98
  113. package/src/components/marketo-form/server/index.ts +0 -8
  114. package/src/components/marketo-form/types.ts +0 -268
  115. package/src/components/marketo-form/utils.test.tsx +0 -103
  116. package/src/components/marketo-form/utils.ts +0 -449
  117. package/src/components/next-steps/index.tsx +0 -137
  118. package/src/components/next-steps/style.module.css +0 -270
  119. package/src/components/next-steps/types.ts +0 -63
  120. package/src/components/product-badge/index.test.tsx +0 -11
  121. package/src/components/product-badge/index.tsx +0 -42
  122. package/src/components/product-badge/style.module.css +0 -76
  123. package/src/components/products-used/index.tsx +0 -84
  124. package/src/components/products-used/style.module.css +0 -87
  125. package/src/components/products-used/types.ts +0 -31
  126. package/src/components/related-content/index.test.tsx +0 -74
  127. package/src/components/related-content/index.tsx +0 -56
  128. package/src/components/related-content/style.module.css +0 -89
  129. package/src/components/related-content/types.ts +0 -21
  130. package/src/components/subnav/helpers/areBasePathsMatching.ts +0 -13
  131. package/src/components/subnav/helpers/traverse/index.ts +0 -42
  132. package/src/components/subnav/helpers/useHeightRef.ts +0 -42
  133. package/src/components/subnav/helpers/useNavRef.ts +0 -30
  134. package/src/components/subnav/helpers/useOverflowRef.ts +0 -85
  135. package/src/components/subnav/helpers/useStuckRef.ts +0 -51
  136. package/src/components/subnav/index.tsx +0 -199
  137. package/src/components/subnav/partials/CtaLinks/github-stars-link/formatStarCount/index.test.ts +0 -26
  138. package/src/components/subnav/partials/CtaLinks/github-stars-link/formatStarCount/index.ts +0 -22
  139. package/src/components/subnav/partials/CtaLinks/github-stars-link/index.tsx +0 -87
  140. package/src/components/subnav/partials/CtaLinks/github-stars-link/parseGithubUrl/index.test.ts +0 -29
  141. package/src/components/subnav/partials/CtaLinks/github-stars-link/parseGithubUrl/index.ts +0 -32
  142. package/src/components/subnav/partials/CtaLinks/github-stars-link/style.module.css +0 -85
  143. package/src/components/subnav/partials/CtaLinks/icons/github-logo.js +0 -20
  144. package/src/components/subnav/partials/CtaLinks/icons/github.svg.js +0 -7
  145. package/src/components/subnav/partials/CtaLinks/icons/star.js +0 -20
  146. package/src/components/subnav/partials/CtaLinks/index.tsx +0 -130
  147. package/src/components/subnav/partials/CtaLinks/style.module.css +0 -45
  148. package/src/components/subnav/partials/DropdownTrigger/index.tsx +0 -35
  149. package/src/components/subnav/partials/DropdownTrigger/style.module.css +0 -36
  150. package/src/components/subnav/partials/MenuItemsDefault/index.tsx +0 -151
  151. package/src/components/subnav/partials/MenuItemsDefault/style.module.css +0 -91
  152. package/src/components/subnav/partials/MenuItemsOverflow/index.tsx +0 -139
  153. package/src/components/subnav/partials/MenuItemsOverflow/style.module.css +0 -82
  154. package/src/components/subnav/partials/TitleLink/index.tsx +0 -113
  155. package/src/components/subnav/partials/TitleLink/mktg-logos/all-community-product-logos_on-dark.ts +0 -9
  156. package/src/components/subnav/partials/TitleLink/mktg-logos/all-community-product-logos_on-light.ts +0 -9
  157. package/src/components/subnav/partials/TitleLink/mktg-logos/all-primary-logos_on-dark.ts +0 -23
  158. package/src/components/subnav/partials/TitleLink/mktg-logos/all-primary-logos_on-light.ts +0 -23
  159. package/src/components/subnav/partials/TitleLink/style.module.css +0 -43
  160. package/src/components/subnav/partials/nav-item-text/index.tsx +0 -37
  161. package/src/components/subnav/partials/nav-item-text/style.module.css +0 -15
  162. package/src/components/subnav/style.module.css +0 -68
  163. package/src/components/subnav/subnav-consts.ts +0 -1
  164. package/src/components/subnav/theme.module.css +0 -50
@@ -1,16 +1,17 @@
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'
5
+ import { getLocalizedLinkProps } from '../../../lib/get-localized-link-props'
4
6
  import { Products } from '@hashicorp/platform-product-meta'
5
- import FlightIcon from '@hashicorp/react-design-system-components/src/components/flight-icon'
6
- import { TextPlus } from '@hashicorp/react-design-system-components/src/components/text'
7
- import { parseUrl } from '../../../lib/parse-url'
7
+ import FlightIcon from '../components/flight-icon'
8
+ import { Text } from '../components/text'
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
12
 
12
13
  const PRODUCT_LOGO_MAP = new Map([
13
- ['Terraform', 'terraform-fill-color'],
14
+ ['Terraform', 'terraform-fill'],
14
15
  ['Packer', 'packer-fill-color'],
15
16
  ['Vault', 'vault-fill-color'],
16
17
  ['Boundary', 'boundary-fill-color'],
@@ -23,11 +24,13 @@ const PRODUCT_LOGO_MAP = new Map([
23
24
  ])
24
25
 
25
26
  const PRODUCT_LOGO_EXCEPTION_CLASSNAMES = {
27
+ Terraform: 'terraform',
26
28
  'HCP Vault Secrets': 'hcpVaultSecrets',
27
29
  'HCP Vault Radar': 'hcpVaultRadar',
28
30
  }
29
31
 
30
32
  export interface ProductsPanelProps {
33
+ locale?: string
31
34
  productCategories: any
32
35
  promo?: PromoProps
33
36
  sidePanel?: {
@@ -39,27 +42,44 @@ export interface ProductsPanelProps {
39
42
  url: string
40
43
  }[]
41
44
  }
45
+ isPromoOnTop?: boolean
42
46
  }
43
47
 
44
48
  const ProductPanel = ({
49
+ locale,
45
50
  productCategories,
46
51
  promo,
47
52
  sidePanel,
53
+ isPromoOnTop = false,
48
54
  }: ProductsPanelProps) => {
49
55
  return (
50
- <NavPanel.Root className={s.productPanel}>
56
+ <NavPanel.Root
57
+ className={classNames(s.productPanel, {
58
+ [s.hasSide]: sidePanel,
59
+ [s.noSide]: !sidePanel,
60
+ [s.topPromo]: isPromoOnTop,
61
+ })}
62
+ hasSidePanel={Boolean(sidePanel)}
63
+ >
51
64
  <div className={s.mainPanel}>
52
- <NavPanel.Column>
65
+ {promo && isPromoOnTop ? (
66
+ <Promo
67
+ {...promo}
68
+ hasSidePanel={Boolean(sidePanel)}
69
+ isPromoOnTop={isPromoOnTop}
70
+ />
71
+ ) : null}
72
+ <NavPanel.Column hasSidePanel={Boolean(sidePanel)}>
53
73
  <ul className={s.productCategories}>
54
74
  {productCategories.map(({ title, products }) => {
55
75
  return (
56
76
  <li key={title} className={s.productCategory}>
57
- <TextPlus.Body className={s.eyebrow}>{title}</TextPlus.Body>
77
+ <Text className={s.eyebrow}>{title}</Text>
58
78
  <ul className={s.productList}>
59
79
  {products.map((product) => {
60
80
  return (
61
81
  <li key={product.url}>
62
- <NavProduct {...product} />
82
+ <NavProduct locale={locale} {...product} />
63
83
  </li>
64
84
  )
65
85
  })}
@@ -69,14 +89,16 @@ const ProductPanel = ({
69
89
  })}
70
90
  </ul>
71
91
  </NavPanel.Column>
72
- {promo ? <Promo {...promo} /> : null}
92
+ {promo && !isPromoOnTop ? (
93
+ <Promo {...promo} hasSidePanel={Boolean(sidePanel)} />
94
+ ) : null}
73
95
  </div>
74
96
 
75
97
  {sidePanel ? (
76
98
  <NavPanel.Column className={s.sidePanel}>
77
- <TextPlus.Body size="200" weight="semibold">
99
+ <Text size="200" weight="semibold" className={s.sidePanelText}>
78
100
  {sidePanel.label}
79
- </TextPlus.Body>
101
+ </Text>
80
102
 
81
103
  {/* ! TODO Replace the below list with the <LinkList /> component,
82
104
  That component will require a refactor to support greater customization
@@ -87,18 +109,26 @@ const ProductPanel = ({
87
109
  {sidePanel.navItems.map(({ icon, title, description, url }) => {
88
110
  return (
89
111
  <li key={title}>
90
- <Link href={parseUrl(url).href} className={s.sidePanelItem}>
112
+ <Link
113
+ aria-label={`${title} - ${description}`}
114
+ {...getLocalizedLinkProps(url, locale)}
115
+ locale={locale ? locale : undefined}
116
+ className={classNames(s.sidePanelItem, s.focusIndicator)}
117
+ >
91
118
  <div className={s.iconBackground}>
92
119
  <FlightIcon
93
- size={16}
94
120
  name={icon}
95
121
  color="var(--token-color-foreground-faint)"
96
122
  />
97
123
  </div>
98
124
  <div className={s.sidePanelItemContent}>
99
- <TextPlus.Body size="200" weight="semibold" tag="span">
125
+ <Text
126
+ size="200"
127
+ weight="semibold"
128
+ className={s.sidePanelText}
129
+ >
100
130
  {title}
101
- </TextPlus.Body>
131
+ </Text>
102
132
  <span className={s.sidePanelItemDesc}>{description}</span>
103
133
  </div>
104
134
  </Link>
@@ -113,16 +143,19 @@ const ProductPanel = ({
113
143
  }
114
144
 
115
145
  export interface NavProductProps {
146
+ locale?: string
116
147
  url: string
117
148
  product: Products | string
118
149
  description: string
119
150
  }
120
151
 
121
- function NavProduct({ url, product, description }: NavProductProps) {
152
+ function NavProduct({ locale, url, product, description }: NavProductProps) {
122
153
  return (
123
154
  <NavigationMenu.Link asChild>
124
155
  <Link
125
- href={parseUrl(url).href}
156
+ aria-label={`${product} - ${description}`}
157
+ {...getLocalizedLinkProps(url, locale)}
158
+ locale={locale ? locale : undefined}
126
159
  onClickCapture={() => {
127
160
  trackNavClickEvent(product, url, 'products')
128
161
  }}
@@ -1,11 +1,47 @@
1
+ @custom-media --dev-dot-viewport (min-width: 924px);
2
+
1
3
  .productPanel {
2
4
  height: 100%;
3
5
 
6
+ /* Temporarily included for devdot compatability
7
+ https://app.asana.com/1/90955849329269/project/1209320521286316/task/1210514680913728?focus=true */
8
+ --mds-spacing-01: 0.25rem;
9
+ --mds-spacing-02: 0.375rem;
10
+ --mds-spacing-03: 0.5rem;
11
+ --mds-spacing-04: 0.75rem;
12
+ --mds-spacing-05: 1rem;
13
+ --mds-spacing-06: 1.25rem;
14
+ --mds-spacing-07: 1.5rem;
15
+ --mds-spacing-08: 2rem;
16
+ --mds-spacing-09: 2.5rem;
17
+ --mds-spacing-10: 3rem;
18
+ --mds-spacing-11: 3.5rem;
19
+ --mds-spacing-12: 4rem;
20
+ --mds-spacing-13: 4.5rem;
21
+ --mds-spacing-14: 5.5rem;
22
+ --mds-spacing-15: 6rem;
23
+ --mds-spacing-16: 8rem;
24
+ --mds-spacing-17: 8.5rem;
25
+ --mds-typography-body-200-font-size: 0.875rem;
26
+ --mds-typography-font-weight-regular: 400;
27
+ --mds-typography-font-weight-semibold: 600;
28
+
4
29
  @media (--large) {
5
- display: grid;
6
- grid-template-rows: 1fr;
7
- grid-template-columns: max-content max-content;
8
- padding: 0;
30
+ &.noSide {
31
+ display: grid;
32
+ grid-template-rows: 1fr;
33
+ grid-template-columns: max-content max-content;
34
+ padding: 0;
35
+ }
36
+ }
37
+
38
+ @media (--dev-dot-viewport) {
39
+ &.hasSide {
40
+ display: grid;
41
+ grid-template-rows: 1fr;
42
+ grid-template-columns: max-content max-content;
43
+ padding: 0;
44
+ }
9
45
  }
10
46
  }
11
47
 
@@ -13,10 +49,22 @@
13
49
  list-style: none;
14
50
  padding: 0;
15
51
  display: grid;
16
- margin: var(--hdsplus-spacing-06) 0 0;
52
+ margin: var(--mds-spacing-07) 0 0;
53
+
54
+ @nest .topPromo & {
55
+ margin-bottom: var(--mds-spacing-07);
56
+ }
17
57
 
18
58
  @media (--large) {
19
- margin: 0;
59
+ @nest .noSide & {
60
+ margin: 0;
61
+ }
62
+ }
63
+
64
+ @media (--dev-dot-viewport) {
65
+ @nest .hasSide & {
66
+ margin: 0;
67
+ }
20
68
  }
21
69
  }
22
70
 
@@ -27,19 +75,28 @@
27
75
 
28
76
  &:first-child {
29
77
  border-bottom: 1px solid var(--token-color-border-primary);
30
- margin-bottom: var(--hdsplus-spacing-05);
31
- padding-bottom: var(--hdsplus-spacing-05);
78
+ margin-bottom: var(--mds-spacing-05);
79
+ padding-bottom: var(--mds-spacing-05);
32
80
  }
33
81
  }
34
82
 
35
83
  .eyebrow {
36
- padding-bottom: var(--hdsplus-spacing-04);
84
+ padding-bottom: var(--mds-spacing-04);
37
85
  color: var(--token-color-foreground-strong);
38
- font-weight: var(--font-weight-semi-bold);
86
+ font-weight: var(--mds-typography-font-weight-semibold);
39
87
 
40
88
  @media (--large) {
41
- padding-bottom: 0;
42
- padding-left: var(--hdsplus-spacing-06);
89
+ @nest .noSide & {
90
+ padding-bottom: 0;
91
+ padding-left: var(--mds-spacing-06);
92
+ }
93
+ }
94
+
95
+ @media (--dev-dot-viewport) {
96
+ @nest .hasSide & {
97
+ padding-bottom: 0;
98
+ padding-left: var(--mds-spacing-06);
99
+ }
43
100
  }
44
101
  }
45
102
 
@@ -51,12 +108,29 @@
51
108
  padding: 0;
52
109
 
53
110
  @media (--large) {
54
- padding: var(--hdsplus-spacing-06) var(--hdsplus-spacing-05)
55
- var(--hdsplus-spacing-04);
56
- grid-auto-flow: row;
57
- grid-template-columns: repeat(2, 300px);
58
- grid-template-rows: repeat(2, max-content);
59
- gap: 0;
111
+ @nest .noSide & {
112
+ padding: var(--mds-spacing-06) var(--mds-spacing-05) var(--mds-spacing-04);
113
+ grid-auto-flow: row;
114
+ grid-template-columns: repeat(2, 300px);
115
+ grid-template-rows: repeat(2, max-content);
116
+ gap: 0;
117
+ }
118
+ }
119
+
120
+ @media (--dev-dot-viewport) {
121
+ @nest .hasSide & {
122
+ padding: var(--mds-spacing-06) var(--mds-spacing-05) var(--mds-spacing-04);
123
+ grid-auto-flow: row;
124
+ grid-template-columns: repeat(2, 300px);
125
+ grid-template-rows: repeat(2, max-content);
126
+ gap: 0;
127
+ }
128
+ }
129
+
130
+ & li:last-child {
131
+ & .productWrapper {
132
+ margin-bottom: 0;
133
+ }
60
134
  }
61
135
  }
62
136
 
@@ -64,16 +138,30 @@
64
138
 
65
139
  .productWrapper {
66
140
  display: flex;
67
- margin-bottom: var(--hdsplus-spacing-05);
68
- gap: var(--hdsplus-spacing-05);
141
+ margin-bottom: var(--mds-spacing-05);
142
+ gap: var(--mds-spacing-05);
69
143
 
70
144
  @media (--large) {
71
- padding: var(--hdsplus-spacing-03) var(--hdsplus-spacing-05);
72
- margin-bottom: 0;
145
+ @nest .noSide & {
146
+ padding: var(--mds-spacing-03) var(--mds-spacing-05);
147
+ margin-bottom: 0;
148
+
149
+ &:hover {
150
+ background-color: var(--token-color-surface-interactive-hover);
151
+ border-radius: var(--mds-spacing-01);
152
+ }
153
+ }
154
+ }
73
155
 
74
- &:hover {
75
- background-color: var(--token-color-surface-interactive-hover);
76
- border-radius: var(--hdsplus-spacing-01);
156
+ @media (--dev-dot-viewport) {
157
+ @nest .hasSide & {
158
+ padding: var(--mds-spacing-03) var(--mds-spacing-05);
159
+ margin-bottom: 0;
160
+
161
+ &:hover {
162
+ background-color: var(--token-color-surface-interactive-hover);
163
+ border-radius: var(--mds-spacing-01);
164
+ }
77
165
  }
78
166
  }
79
167
  }
@@ -84,10 +172,23 @@
84
172
  & svg {
85
173
  height: 42px;
86
174
  width: 42px;
175
+ }
176
+
177
+ @nest .noSide & {
178
+ & svg {
179
+ @media (--large) {
180
+ height: var(--mds-spacing-08);
181
+ width: var(--mds-spacing-08);
182
+ }
183
+ }
184
+ }
87
185
 
88
- @media (--large) {
89
- height: var(--hdsplus-spacing-08);
90
- width: var(--hdsplus-spacing-08);
186
+ @nest .hasSide & {
187
+ & svg {
188
+ @media (--dev-dot-viewport) {
189
+ height: var(--mds-spacing-08);
190
+ width: var(--mds-spacing-08);
191
+ }
91
192
  }
92
193
  }
93
194
  }
@@ -119,9 +220,30 @@
119
220
  justify-content: space-between;
120
221
  flex-direction: column;
121
222
 
223
+ @nest .topPromo & {
224
+ justify-content: flex-start;
225
+ }
226
+
122
227
  @media (--large) {
123
- padding: var(--hdsplus-spacing-07) 0 var(--hdsplus-spacing-05)
124
- var(--hdsplus-spacing-04);
228
+ @nest .noSide & {
229
+ padding: var(--mds-spacing-07) 0 var(--mds-spacing-09)
230
+ var(--mds-spacing-04);
231
+ }
232
+
233
+ @nest .topPromo & {
234
+ padding-bottom: var(--mds-spacing-04);
235
+ }
236
+ }
237
+
238
+ @media (--dev-dot-viewport) {
239
+ @nest .hasSide & {
240
+ padding: var(--mds-spacing-07) 0 var(--mds-spacing-09)
241
+ var(--mds-spacing-04);
242
+ }
243
+
244
+ @nest .topPromo & {
245
+ padding-bottom: var(--mds-spacing-04);
246
+ }
125
247
  }
126
248
  }
127
249
 
@@ -130,10 +252,10 @@
130
252
  background: var(--token-color-surface-faint);
131
253
  display: flex;
132
254
  flex-direction: column;
133
- gap: var(--hdsplus-spacing-05);
255
+ gap: var(--mds-spacing-05);
134
256
  margin: 0;
135
- padding: var(--hdsplus-spacing-07) var(--hdsplus-spacing-04)
136
- var(--hdsplus-spacing-09) var(--hdsplus-spacing-07);
257
+ padding: var(--mds-spacing-07) var(--mds-spacing-04) var(--mds-spacing-09)
258
+ var(--mds-spacing-07);
137
259
  }
138
260
 
139
261
  .sidePanelItems {
@@ -142,26 +264,24 @@
142
264
  padding: 0;
143
265
  display: grid;
144
266
  grid-template-columns: 1fr;
145
- gap: var(--hdsplus-spacing-07);
267
+ gap: var(--mds-spacing-07);
146
268
 
147
- @media (--large) {
148
- gap: var(--hdsplus-spacing-05);
269
+ @media (--dev-dot-viewport) {
270
+ gap: var(--mds-spacing-05);
149
271
  }
150
272
  }
151
273
 
152
274
  /* Lifted from .productWrapper */
153
275
  .sidePanelItem {
154
276
  display: flex;
155
- margin-bottom: var(--hdsplus-spacing-05);
156
- gap: var(--hdsplus-spacing-05);
277
+ gap: var(--mds-spacing-05);
157
278
 
158
- @media (--large) {
159
- padding: var(--hdsplus-spacing-03) var(--hdsplus-spacing-05);
160
- margin-bottom: 0;
279
+ @media (--dev-dot-viewport) {
280
+ padding: var(--mds-spacing-03) var(--mds-spacing-05);
161
281
 
162
282
  &:hover {
163
283
  background-color: var(--token-color-surface-interactive-hover);
164
- border-radius: var(--hdsplus-spacing-01);
284
+ border-radius: var(--mds-spacing-01);
165
285
  }
166
286
  }
167
287
  }
@@ -170,8 +290,8 @@
170
290
  packages/react-components/src/components/nav-panel/components/link-list/style.module.css */
171
291
  .iconBackground {
172
292
  background: var(--token-color-foreground-high-contrast);
173
- height: var(--hdsplus-spacing-08);
174
- width: var(--hdsplus-spacing-08);
293
+ height: var(--mds-spacing-08);
294
+ width: var(--mds-spacing-08);
175
295
  display: flex;
176
296
  align-items: center;
177
297
  justify-content: center;
@@ -197,13 +317,28 @@ packages/react-components/src/components/nav-panel/components/link-list/style.mo
197
317
 
198
318
  /* Branding exception classnames */
199
319
 
320
+ /* Allows switching to a dark-mode-specific color for Terraform */
321
+ .terraform {
322
+ & use {
323
+ fill: var(--token-color-terraform-brand);
324
+
325
+ @nest [data-theme='dark'] & {
326
+ fill: var(--token-color-terraform-foreground);
327
+ }
328
+ }
329
+
330
+ & path {
331
+ fill: inherit;
332
+ }
333
+ }
334
+
200
335
  /* Styles for HCP Vault mimic the spec for `product-square` icons,
201
336
  while allowing the symbol inside the icon border to change color
202
337
  based on the site's theme
203
338
  */
204
339
  .hcpVaultSecrets,
205
340
  .hcpVaultRadar {
206
- padding: var(--hdsplus-spacing-01);
341
+ padding: var(--mds-spacing-01);
207
342
  border: 2px solid var(--token-color-vault-brand);
208
343
  border-radius: 3px;
209
344
 
@@ -215,3 +350,7 @@ packages/react-components/src/components/nav-panel/components/link-list/style.mo
215
350
  fill: inherit;
216
351
  }
217
352
  }
353
+
354
+ .sidePanelText {
355
+ font-weight: var(--mds-typography-font-weight-semibold);
356
+ }
@@ -12,12 +12,14 @@ interface StandardPanelProps {
12
12
  navData: NavItem[]
13
13
  promo?: PromoProps
14
14
  sectionName?: string
15
+ locale?: any
15
16
  }
16
17
 
17
18
  const StandardPanel = ({
18
19
  navData,
19
20
  promo,
20
21
  sectionName = '',
22
+ locale,
21
23
  }: StandardPanelProps) => {
22
24
  return (
23
25
  <NavPanel.Root>
@@ -26,6 +28,7 @@ const StandardPanel = ({
26
28
  return (
27
29
  <NavPanel.Column key={stableIdx}>
28
30
  <LinkList
31
+ locale={locale}
29
32
  links={navItems}
30
33
  linkClickHandler={(text, href) => {
31
34
  trackNavClickEvent(text, href, sectionName)
@@ -1,8 +1,8 @@
1
1
  .columns {
2
2
  display: flex;
3
- gap: var(--hdsplus-spacing-03);
3
+ gap: var(--mds-spacing-03);
4
4
  flex-direction: column;
5
- margin-top: var(--hdsplus-spacing-06);
5
+ margin-top: var(--mds-spacing-07);
6
6
 
7
7
  @media (--large) {
8
8
  flex-direction: row;
@@ -0,0 +1,30 @@
1
+ import { getLocalizedLinkProps } from '.'
2
+
3
+ describe('getLocalizedLinkProps', () => {
4
+ it('does not format localized homepage', () => {
5
+ const localizedLinkProps = getLocalizedLinkProps('/en', 'ja')
6
+ expect(localizedLinkProps.href).toBe('/en')
7
+ expect(localizedLinkProps.hrefLang).toBe('en')
8
+ })
9
+
10
+ it('does not format localized path hrefs', () => {
11
+ const localizedLinkProps = getLocalizedLinkProps('/ja/solutions', 'de')
12
+ expect(localizedLinkProps.href).toBe('/ja/solutions')
13
+ expect(localizedLinkProps.hrefLang).toBe('ja')
14
+ })
15
+
16
+ it('does format paths that start with a locale string', () => {
17
+ const localizedLinkProps = getLocalizedLinkProps(
18
+ '/deconstructing-cloud',
19
+ 'en'
20
+ )
21
+ expect(localizedLinkProps.href).toBe('/en/deconstructing-cloud')
22
+ expect(localizedLinkProps.hrefLang).toBe('en')
23
+ })
24
+
25
+ it('does not format external paths', () => {
26
+ const localizedLinkProps = getLocalizedLinkProps('https://google.com', 'ja')
27
+ expect(localizedLinkProps.href).toBe('https://google.com')
28
+ expect(localizedLinkProps.hrefLang).toBe(undefined)
29
+ })
30
+ })
@@ -0,0 +1,45 @@
1
+ import { parseUrl } from '../parse-url'
2
+ import { allSupportedLocales } from '../supported-locales'
3
+
4
+ export const getLocalizedLinkProps = (
5
+ url: string,
6
+ locale?: string
7
+ ): {
8
+ href: string
9
+ hrefLang: string | undefined
10
+ } => {
11
+ const parsedHref = parseUrl(url).href
12
+
13
+ // example: /en
14
+ const hrefIsLocalizedHomepage = allSupportedLocales.includes(
15
+ parsedHref.substring(1)
16
+ )
17
+
18
+ // true example: /en/solutions
19
+ // false example: /entry-point
20
+ const hrefIsLocalized =
21
+ allSupportedLocales.includes(parsedHref.substring(1, 3)) &&
22
+ parsedHref[3] === '/'
23
+
24
+ // If the href is already localized:
25
+ // - do not format the href
26
+ // - use the locale from the href for the hrefLang
27
+ if (hrefIsLocalizedHomepage || hrefIsLocalized) {
28
+ return {
29
+ href: parsedHref,
30
+ hrefLang: parsedHref.substring(1, 3),
31
+ }
32
+ }
33
+
34
+ if (parsedHref.startsWith('/') && locale) {
35
+ return {
36
+ href: `/${locale}${parsedHref}`,
37
+ hrefLang: locale,
38
+ }
39
+ }
40
+
41
+ return {
42
+ href: parsedHref,
43
+ hrefLang: undefined,
44
+ }
45
+ }
@@ -1,4 +1,4 @@
1
- import { parseUrl } from '.'
1
+ import { parseUrl, hasHashiCorpDestination } from '.'
2
2
 
3
3
  describe('parseUrl', () => {
4
4
  it('detects hashicorp.com URLs as internal', () => {
@@ -7,6 +7,12 @@ describe('parseUrl', () => {
7
7
  expect(url.linkType).toBe('inbound')
8
8
  })
9
9
 
10
+ it('detects www.hashicorp.com URLs as internal', () => {
11
+ const url = parseUrl('https://hashicorp.com/foo')
12
+ expect(url.href).toBe('/foo')
13
+ expect(url.linkType).toBe('inbound')
14
+ })
15
+
10
16
  it('detects URLs not containing hashicorp.com as external', () => {
11
17
  const externalUrl = 'https://google.com/example'
12
18
  const url = parseUrl(externalUrl)
@@ -27,4 +33,37 @@ describe('parseUrl', () => {
27
33
  )
28
34
  expect(url.href).toBe('/resources?type=case-study&products=terraform')
29
35
  })
36
+
37
+ it('leaves URL hash intact', () => {
38
+ const url = parseUrl('https://hashicorp.com/about#leadership')
39
+ expect(url.href).toBe('/about#leadership')
40
+ })
41
+
42
+ it('leaves HashiCorp subdomain URLs intact', () => {
43
+ const url = parseUrl('https://developer.hashicorp.com/terraform')
44
+ expect(url.href).toBe('https://developer.hashicorp.com/terraform')
45
+ })
46
+ })
47
+
48
+ describe('hasHashiCorpDestination', () => {
49
+ it('returns true for supported hashicorp domains', () => {
50
+ const isHashiCorpDestination = hasHashiCorpDestination(
51
+ 'https://portal.cloud.hashicorp.com/foo'
52
+ )
53
+ expect(isHashiCorpDestination).toBe(true)
54
+ })
55
+ it('returns false for external domains', () => {
56
+ const isHashiCorpDestination = hasHashiCorpDestination(
57
+ 'https://foo.com/bar'
58
+ )
59
+ expect(isHashiCorpDestination).toBe(false)
60
+ })
61
+ it('returns true for relative links', () => {
62
+ const isHashiCorpDestination = hasHashiCorpDestination('/bar')
63
+ expect(isHashiCorpDestination).toBe(true)
64
+ })
65
+ it('returns true for hashes', () => {
66
+ const isHashiCorpDestination = hasHashiCorpDestination('#someHash')
67
+ expect(isHashiCorpDestination).toBe(true)
68
+ })
30
69
  })