@hashicorp/react-components 0.0.0-canary.43d0406 → 0.0.0-canary.484207e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -8
- package/src/components/nav-panel/components/flight-icon/index.tsx +51 -0
- package/src/components/nav-panel/components/flight-icon/style.module.css +3 -0
- package/src/components/nav-panel/components/link-list/index.tsx +15 -9
- package/src/components/nav-panel/components/link-list/style.module.css +10 -10
- package/src/components/nav-panel/components/panel/column/style.module.css +3 -3
- package/src/components/nav-panel/components/panel/root/style.module.css +6 -6
- package/src/components/nav-panel/components/promo/index.tsx +15 -9
- package/src/components/nav-panel/components/promo/style.module.css +28 -13
- package/src/components/nav-panel/components/text/index.tsx +34 -0
- package/src/components/nav-panel/product-panel/index.tsx +42 -27
- package/src/components/nav-panel/product-panel/style.module.css +103 -43
- package/src/components/nav-panel/standard-panel/index.tsx +3 -0
- package/src/components/nav-panel/standard-panel/style.module.css +2 -2
- package/src/lib/get-localized-link-props/index.test.ts +30 -0
- package/src/lib/get-localized-link-props/index.ts +45 -0
- package/src/lib/parse-url/index.test.ts +40 -1
- package/src/lib/parse-url/index.ts +75 -9
- package/src/lib/send-posthog-event/index.ts +22 -0
- package/src/lib/supported-locales/index.ts +1 -0
- package/src/lib/track-nav-click-event/index.ts +4 -4
- package/src/lib/v/index.ts +4 -5
- package/src/components/actions/index.tsx +0 -107
- package/src/components/actions/style.module.css +0 -28
- package/src/components/actions/types.ts +0 -73
- package/src/components/call-to-action/index.tsx +0 -205
- package/src/components/call-to-action/styles/variant-centered.module.css +0 -93
- package/src/components/call-to-action/styles/variant-compact-grid.module.css +0 -88
- package/src/components/call-to-action/styles/variant-compact.module.css +0 -91
- package/src/components/call-to-action/styles/variant-links.module.css +0 -85
- package/src/components/card/README.md +0 -11
- package/src/components/card/card.tsx +0 -45
- package/src/components/card/index.test.tsx +0 -69
- package/src/components/card/index.tsx +0 -14
- package/src/components/card/newsroom-card/index.test.tsx +0 -39
- package/src/components/card/newsroom-card/index.tsx +0 -37
- package/src/components/card/newsroom-card/style.module.css +0 -12
- package/src/components/card/partner-card/index.test.tsx +0 -57
- package/src/components/card/partner-card/index.tsx +0 -69
- package/src/components/card/partner-card/style.module.css +0 -24
- package/src/components/card/person-card/index.test.tsx +0 -71
- package/src/components/card/person-card/index.tsx +0 -93
- package/src/components/card/person-card/style.module.css +0 -33
- package/src/components/card/primitives.tsx +0 -176
- package/src/components/card/promo-card/index.tsx +0 -51
- package/src/components/card/resource-card/index.test.tsx +0 -48
- package/src/components/card/resource-card/index.tsx +0 -37
- package/src/components/card/style.module.css +0 -145
- package/src/components/card/types.ts +0 -66
- package/src/components/card/unified-card/index.tsx +0 -64
- package/src/components/consent-manager/README.md +0 -73
- package/src/components/consent-manager/components/banner/banner.module.css +0 -23
- package/src/components/consent-manager/components/banner/banner.test.tsx +0 -31
- package/src/components/consent-manager/components/banner/banner.tsx +0 -73
- package/src/components/consent-manager/components/dialog/dialog.module.css +0 -145
- package/src/components/consent-manager/components/dialog/dialog.test.tsx +0 -194
- package/src/components/consent-manager/components/dialog/dialog.tsx +0 -339
- package/src/components/consent-manager/img/icn_close.tsx +0 -19
- package/src/components/consent-manager/index.test.tsx +0 -334
- package/src/components/consent-manager/index.tsx +0 -186
- package/src/components/consent-manager/loader/README.md +0 -29
- package/src/components/consent-manager/loader/categories.ts +0 -22
- package/src/components/consent-manager/loader/index.tsx +0 -94
- package/src/components/consent-manager/loader/presets/enterprise.ts +0 -12
- package/src/components/consent-manager/loader/presets/oss.ts +0 -10
- package/src/components/consent-manager/loader/services.ts +0 -45
- package/src/components/consent-manager/scripts/custom.tsx +0 -59
- package/src/components/consent-manager/scripts/segment.tsx +0 -87
- package/src/components/consent-manager/style.module.css +0 -9
- package/src/components/consent-manager/types.ts +0 -55
- package/src/components/consent-manager/util/cookies.test.ts +0 -75
- package/src/components/consent-manager/util/cookies.ts +0 -70
- package/src/components/consent-manager/util/integrations.test.ts +0 -115
- package/src/components/consent-manager/util/integrations.ts +0 -110
- package/src/components/intro/index.tsx +0 -82
- package/src/components/intro/style.module.css +0 -67
- package/src/components/intro/types.ts +0 -44
- package/src/components/marketo-form/CHANGELOG.md +0 -122
- package/src/components/marketo-form/README.md +0 -1
- package/src/components/marketo-form/contexts/FormMetadata.ts +0 -11
- package/src/components/marketo-form/docs.mdx +0 -197
- package/src/components/marketo-form/fixtures/index.ts +0 -185
- package/src/components/marketo-form/form/index.tsx +0 -369
- package/src/components/marketo-form/index.test.tsx +0 -320
- package/src/components/marketo-form/index.ts +0 -11
- package/src/components/marketo-form/package.original.json +0 -30
- package/src/components/marketo-form/partials/error-message/index.tsx +0 -12
- package/src/components/marketo-form/partials/error-message/style.module.css +0 -13
- package/src/components/marketo-form/partials/field/index.tsx +0 -90
- package/src/components/marketo-form/partials/field-wrapper/index.tsx +0 -26
- package/src/components/marketo-form/partials/fields/checkbox-field/index.tsx +0 -32
- package/src/components/marketo-form/partials/fields/email-field/index.tsx +0 -35
- package/src/components/marketo-form/partials/fields/form-page-url-field/index.tsx +0 -21
- package/src/components/marketo-form/partials/fields/hidden-field/index.tsx +0 -37
- package/src/components/marketo-form/partials/fields/htmltext-field/index.tsx +0 -21
- package/src/components/marketo-form/partials/fields/htmltext-field/style.module.css +0 -18
- package/src/components/marketo-form/partials/fields/name-field/index.tsx +0 -19
- package/src/components/marketo-form/partials/fields/name-field/style.module.css +0 -13
- package/src/components/marketo-form/partials/fields/radio-buttons-field/index.tsx +0 -48
- package/src/components/marketo-form/partials/fields/select-field/index.tsx +0 -39
- package/src/components/marketo-form/partials/fields/select-field/style.module.css +0 -5
- package/src/components/marketo-form/partials/fields/telephone-field/index.tsx +0 -30
- package/src/components/marketo-form/partials/fields/text-field/index.tsx +0 -30
- package/src/components/marketo-form/partials/fields/textarea-field/index.tsx +0 -29
- package/src/components/marketo-form/partials/label/index.tsx +0 -24
- package/src/components/marketo-form/partials/label/style.module.css +0 -12
- package/src/components/marketo-form/partials/visibility-rule/index.tsx +0 -84
- package/src/components/marketo-form/props.js +0 -66
- package/src/components/marketo-form/server/api-routes.ts +0 -109
- package/src/components/marketo-form/server/client.ts +0 -98
- package/src/components/marketo-form/server/index.ts +0 -8
- package/src/components/marketo-form/types.ts +0 -268
- package/src/components/marketo-form/utils.test.tsx +0 -103
- package/src/components/marketo-form/utils.ts +0 -449
- package/src/components/next-steps/index.tsx +0 -137
- package/src/components/next-steps/style.module.css +0 -270
- package/src/components/next-steps/types.ts +0 -63
- package/src/components/product-badge/index.test.tsx +0 -11
- package/src/components/product-badge/index.tsx +0 -42
- package/src/components/product-badge/style.module.css +0 -76
- package/src/components/products-used/index.tsx +0 -84
- package/src/components/products-used/style.module.css +0 -87
- package/src/components/products-used/types.ts +0 -31
- package/src/components/related-content/index.test.tsx +0 -74
- package/src/components/related-content/index.tsx +0 -56
- package/src/components/related-content/style.module.css +0 -89
- package/src/components/related-content/types.ts +0 -21
- package/src/components/subnav/helpers/areBasePathsMatching.ts +0 -13
- package/src/components/subnav/helpers/traverse/index.ts +0 -42
- package/src/components/subnav/helpers/useHeightRef.ts +0 -42
- package/src/components/subnav/helpers/useNavRef.ts +0 -30
- package/src/components/subnav/helpers/useOverflowRef.ts +0 -85
- package/src/components/subnav/helpers/useStuckRef.ts +0 -51
- package/src/components/subnav/index.tsx +0 -199
- package/src/components/subnav/partials/CtaLinks/github-stars-link/formatStarCount/index.test.ts +0 -26
- package/src/components/subnav/partials/CtaLinks/github-stars-link/formatStarCount/index.ts +0 -22
- package/src/components/subnav/partials/CtaLinks/github-stars-link/index.tsx +0 -87
- package/src/components/subnav/partials/CtaLinks/github-stars-link/parseGithubUrl/index.test.ts +0 -29
- package/src/components/subnav/partials/CtaLinks/github-stars-link/parseGithubUrl/index.ts +0 -32
- package/src/components/subnav/partials/CtaLinks/github-stars-link/style.module.css +0 -85
- package/src/components/subnav/partials/CtaLinks/icons/github-logo.js +0 -20
- package/src/components/subnav/partials/CtaLinks/icons/github.svg.js +0 -7
- package/src/components/subnav/partials/CtaLinks/icons/star.js +0 -20
- package/src/components/subnav/partials/CtaLinks/index.tsx +0 -130
- package/src/components/subnav/partials/CtaLinks/style.module.css +0 -45
- package/src/components/subnav/partials/DropdownTrigger/index.tsx +0 -35
- package/src/components/subnav/partials/DropdownTrigger/style.module.css +0 -36
- package/src/components/subnav/partials/MenuItemsDefault/index.tsx +0 -151
- package/src/components/subnav/partials/MenuItemsDefault/style.module.css +0 -91
- package/src/components/subnav/partials/MenuItemsOverflow/index.tsx +0 -139
- package/src/components/subnav/partials/MenuItemsOverflow/style.module.css +0 -82
- package/src/components/subnav/partials/TitleLink/index.tsx +0 -113
- package/src/components/subnav/partials/TitleLink/mktg-logos/all-community-product-logos_on-dark.ts +0 -9
- package/src/components/subnav/partials/TitleLink/mktg-logos/all-community-product-logos_on-light.ts +0 -9
- package/src/components/subnav/partials/TitleLink/mktg-logos/all-primary-logos_on-dark.ts +0 -23
- package/src/components/subnav/partials/TitleLink/mktg-logos/all-primary-logos_on-light.ts +0 -23
- package/src/components/subnav/partials/TitleLink/style.module.css +0 -43
- package/src/components/subnav/partials/nav-item-text/index.tsx +0 -37
- package/src/components/subnav/partials/nav-item-text/style.module.css +0 -15
- package/src/components/subnav/style.module.css +0 -68
- package/src/components/subnav/subnav-consts.ts +0 -1
- package/src/components/subnav/theme.module.css +0 -50
|
@@ -1,8 +1,31 @@
|
|
|
1
|
-
@custom-media --dev-dot-viewport (min-width:
|
|
1
|
+
@custom-media --dev-dot-viewport (min-width: 924px);
|
|
2
2
|
|
|
3
3
|
.productPanel {
|
|
4
4
|
height: 100%;
|
|
5
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
|
+
|
|
6
29
|
@media (--large) {
|
|
7
30
|
&.noSide {
|
|
8
31
|
display: grid;
|
|
@@ -26,7 +49,11 @@
|
|
|
26
49
|
list-style: none;
|
|
27
50
|
padding: 0;
|
|
28
51
|
display: grid;
|
|
29
|
-
margin: var(--
|
|
52
|
+
margin: var(--mds-spacing-07) 0 0;
|
|
53
|
+
|
|
54
|
+
@nest .topPromo & {
|
|
55
|
+
margin-bottom: var(--mds-spacing-07);
|
|
56
|
+
}
|
|
30
57
|
|
|
31
58
|
@media (--large) {
|
|
32
59
|
@nest .noSide & {
|
|
@@ -48,27 +75,27 @@
|
|
|
48
75
|
|
|
49
76
|
&:first-child {
|
|
50
77
|
border-bottom: 1px solid var(--token-color-border-primary);
|
|
51
|
-
margin-bottom: var(--
|
|
52
|
-
padding-bottom: var(--
|
|
78
|
+
margin-bottom: var(--mds-spacing-05);
|
|
79
|
+
padding-bottom: var(--mds-spacing-05);
|
|
53
80
|
}
|
|
54
81
|
}
|
|
55
82
|
|
|
56
83
|
.eyebrow {
|
|
57
|
-
padding-bottom: var(--
|
|
84
|
+
padding-bottom: var(--mds-spacing-04);
|
|
58
85
|
color: var(--token-color-foreground-strong);
|
|
59
|
-
font-weight: var(--font-weight-
|
|
86
|
+
font-weight: var(--mds-typography-font-weight-semibold);
|
|
60
87
|
|
|
61
88
|
@media (--large) {
|
|
62
89
|
@nest .noSide & {
|
|
63
90
|
padding-bottom: 0;
|
|
64
|
-
padding-left: var(--
|
|
91
|
+
padding-left: var(--mds-spacing-06);
|
|
65
92
|
}
|
|
66
93
|
}
|
|
67
94
|
|
|
68
95
|
@media (--dev-dot-viewport) {
|
|
69
96
|
@nest .hasSide & {
|
|
70
97
|
padding-bottom: 0;
|
|
71
|
-
padding-left: var(--
|
|
98
|
+
padding-left: var(--mds-spacing-06);
|
|
72
99
|
}
|
|
73
100
|
}
|
|
74
101
|
}
|
|
@@ -82,54 +109,58 @@
|
|
|
82
109
|
|
|
83
110
|
@media (--large) {
|
|
84
111
|
@nest .noSide & {
|
|
85
|
-
padding: var(--
|
|
86
|
-
|
|
87
|
-
grid-auto-flow: column;
|
|
112
|
+
padding: var(--mds-spacing-06) var(--mds-spacing-05) var(--mds-spacing-04);
|
|
113
|
+
grid-auto-flow: row;
|
|
88
114
|
grid-template-columns: repeat(2, 300px);
|
|
89
|
-
grid-template-rows: repeat(
|
|
115
|
+
grid-template-rows: repeat(2, max-content);
|
|
90
116
|
gap: 0;
|
|
91
117
|
}
|
|
92
118
|
}
|
|
93
119
|
|
|
94
120
|
@media (--dev-dot-viewport) {
|
|
95
121
|
@nest .hasSide & {
|
|
96
|
-
padding: var(--
|
|
97
|
-
|
|
98
|
-
grid-auto-flow: column;
|
|
122
|
+
padding: var(--mds-spacing-06) var(--mds-spacing-05) var(--mds-spacing-04);
|
|
123
|
+
grid-auto-flow: row;
|
|
99
124
|
grid-template-columns: repeat(2, 300px);
|
|
100
|
-
grid-template-rows: repeat(
|
|
125
|
+
grid-template-rows: repeat(2, max-content);
|
|
101
126
|
gap: 0;
|
|
102
127
|
}
|
|
103
128
|
}
|
|
129
|
+
|
|
130
|
+
& li:last-child {
|
|
131
|
+
& .productWrapper {
|
|
132
|
+
margin-bottom: 0;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
104
135
|
}
|
|
105
136
|
|
|
106
137
|
/* NavProduct styles */
|
|
107
138
|
|
|
108
139
|
.productWrapper {
|
|
109
140
|
display: flex;
|
|
110
|
-
margin-bottom: var(--
|
|
111
|
-
gap: var(--
|
|
141
|
+
margin-bottom: var(--mds-spacing-05);
|
|
142
|
+
gap: var(--mds-spacing-05);
|
|
112
143
|
|
|
113
144
|
@media (--large) {
|
|
114
145
|
@nest .noSide & {
|
|
115
|
-
padding: var(--
|
|
146
|
+
padding: var(--mds-spacing-03) var(--mds-spacing-05);
|
|
116
147
|
margin-bottom: 0;
|
|
117
148
|
|
|
118
149
|
&:hover {
|
|
119
150
|
background-color: var(--token-color-surface-interactive-hover);
|
|
120
|
-
border-radius: var(--
|
|
151
|
+
border-radius: var(--mds-spacing-01);
|
|
121
152
|
}
|
|
122
153
|
}
|
|
123
154
|
}
|
|
124
155
|
|
|
125
156
|
@media (--dev-dot-viewport) {
|
|
126
157
|
@nest .hasSide & {
|
|
127
|
-
padding: var(--
|
|
158
|
+
padding: var(--mds-spacing-03) var(--mds-spacing-05);
|
|
128
159
|
margin-bottom: 0;
|
|
129
160
|
|
|
130
161
|
&:hover {
|
|
131
162
|
background-color: var(--token-color-surface-interactive-hover);
|
|
132
|
-
border-radius: var(--
|
|
163
|
+
border-radius: var(--mds-spacing-01);
|
|
133
164
|
}
|
|
134
165
|
}
|
|
135
166
|
}
|
|
@@ -146,8 +177,8 @@
|
|
|
146
177
|
@nest .noSide & {
|
|
147
178
|
& svg {
|
|
148
179
|
@media (--large) {
|
|
149
|
-
height: var(--
|
|
150
|
-
width: var(--
|
|
180
|
+
height: var(--mds-spacing-08);
|
|
181
|
+
width: var(--mds-spacing-08);
|
|
151
182
|
}
|
|
152
183
|
}
|
|
153
184
|
}
|
|
@@ -155,8 +186,8 @@
|
|
|
155
186
|
@nest .hasSide & {
|
|
156
187
|
& svg {
|
|
157
188
|
@media (--dev-dot-viewport) {
|
|
158
|
-
height: var(--
|
|
159
|
-
width: var(--
|
|
189
|
+
height: var(--mds-spacing-08);
|
|
190
|
+
width: var(--mds-spacing-08);
|
|
160
191
|
}
|
|
161
192
|
}
|
|
162
193
|
}
|
|
@@ -189,17 +220,29 @@
|
|
|
189
220
|
justify-content: space-between;
|
|
190
221
|
flex-direction: column;
|
|
191
222
|
|
|
223
|
+
@nest .topPromo & {
|
|
224
|
+
justify-content: flex-start;
|
|
225
|
+
}
|
|
226
|
+
|
|
192
227
|
@media (--large) {
|
|
193
228
|
@nest .noSide & {
|
|
194
|
-
padding: var(--
|
|
195
|
-
var(--
|
|
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);
|
|
196
235
|
}
|
|
197
236
|
}
|
|
198
237
|
|
|
199
238
|
@media (--dev-dot-viewport) {
|
|
200
239
|
@nest .hasSide & {
|
|
201
|
-
padding: var(--
|
|
202
|
-
var(--
|
|
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);
|
|
203
246
|
}
|
|
204
247
|
}
|
|
205
248
|
}
|
|
@@ -209,10 +252,10 @@
|
|
|
209
252
|
background: var(--token-color-surface-faint);
|
|
210
253
|
display: flex;
|
|
211
254
|
flex-direction: column;
|
|
212
|
-
gap: var(--
|
|
255
|
+
gap: var(--mds-spacing-05);
|
|
213
256
|
margin: 0;
|
|
214
|
-
padding: var(--
|
|
215
|
-
var(--
|
|
257
|
+
padding: var(--mds-spacing-07) var(--mds-spacing-04) var(--mds-spacing-09)
|
|
258
|
+
var(--mds-spacing-07);
|
|
216
259
|
}
|
|
217
260
|
|
|
218
261
|
.sidePanelItems {
|
|
@@ -221,26 +264,24 @@
|
|
|
221
264
|
padding: 0;
|
|
222
265
|
display: grid;
|
|
223
266
|
grid-template-columns: 1fr;
|
|
224
|
-
gap: var(--
|
|
267
|
+
gap: var(--mds-spacing-07);
|
|
225
268
|
|
|
226
269
|
@media (--dev-dot-viewport) {
|
|
227
|
-
gap: var(--
|
|
270
|
+
gap: var(--mds-spacing-05);
|
|
228
271
|
}
|
|
229
272
|
}
|
|
230
273
|
|
|
231
274
|
/* Lifted from .productWrapper */
|
|
232
275
|
.sidePanelItem {
|
|
233
276
|
display: flex;
|
|
234
|
-
|
|
235
|
-
gap: var(--hdsplus-spacing-05);
|
|
277
|
+
gap: var(--mds-spacing-05);
|
|
236
278
|
|
|
237
279
|
@media (--dev-dot-viewport) {
|
|
238
|
-
padding: var(--
|
|
239
|
-
margin-bottom: 0;
|
|
280
|
+
padding: var(--mds-spacing-03) var(--mds-spacing-05);
|
|
240
281
|
|
|
241
282
|
&:hover {
|
|
242
283
|
background-color: var(--token-color-surface-interactive-hover);
|
|
243
|
-
border-radius: var(--
|
|
284
|
+
border-radius: var(--mds-spacing-01);
|
|
244
285
|
}
|
|
245
286
|
}
|
|
246
287
|
}
|
|
@@ -249,8 +290,8 @@
|
|
|
249
290
|
packages/react-components/src/components/nav-panel/components/link-list/style.module.css */
|
|
250
291
|
.iconBackground {
|
|
251
292
|
background: var(--token-color-foreground-high-contrast);
|
|
252
|
-
height: var(--
|
|
253
|
-
width: var(--
|
|
293
|
+
height: var(--mds-spacing-08);
|
|
294
|
+
width: var(--mds-spacing-08);
|
|
254
295
|
display: flex;
|
|
255
296
|
align-items: center;
|
|
256
297
|
justify-content: center;
|
|
@@ -276,13 +317,28 @@ packages/react-components/src/components/nav-panel/components/link-list/style.mo
|
|
|
276
317
|
|
|
277
318
|
/* Branding exception classnames */
|
|
278
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
|
+
|
|
279
335
|
/* Styles for HCP Vault mimic the spec for `product-square` icons,
|
|
280
336
|
while allowing the symbol inside the icon border to change color
|
|
281
337
|
based on the site's theme
|
|
282
338
|
*/
|
|
283
339
|
.hcpVaultSecrets,
|
|
284
340
|
.hcpVaultRadar {
|
|
285
|
-
padding: var(--
|
|
341
|
+
padding: var(--mds-spacing-01);
|
|
286
342
|
border: 2px solid var(--token-color-vault-brand);
|
|
287
343
|
border-radius: 3px;
|
|
288
344
|
|
|
@@ -294,3 +350,7 @@ packages/react-components/src/components/nav-panel/components/link-list/style.mo
|
|
|
294
350
|
fill: inherit;
|
|
295
351
|
}
|
|
296
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)
|
|
@@ -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
|
})
|
|
@@ -1,9 +1,46 @@
|
|
|
1
|
+
export const hashicorpDestinations: string[] = [
|
|
2
|
+
'app.terraform.io',
|
|
3
|
+
'boundaryproject.io',
|
|
4
|
+
'cloud.hashicorp.com',
|
|
5
|
+
'consul.io',
|
|
6
|
+
'developer.hashicorp.com',
|
|
7
|
+
'hashicorp.com',
|
|
8
|
+
'nomadproject.io',
|
|
9
|
+
'packer.io',
|
|
10
|
+
'portal.cloud.hashicorp.com',
|
|
11
|
+
'registry.terraform.io',
|
|
12
|
+
'terraform.io',
|
|
13
|
+
'vagrantup.com',
|
|
14
|
+
'vaultproject.io',
|
|
15
|
+
'waypointproject.io',
|
|
16
|
+
] as const
|
|
17
|
+
|
|
18
|
+
const containsHashiCorpDestination = (str: string): boolean =>
|
|
19
|
+
hashicorpDestinations.some(function (destination) {
|
|
20
|
+
return str.indexOf(destination) >= 0
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* This function determines if a `url` is a HashiCorp link (relative URLs, hashes,
|
|
25
|
+
* or a url with a HashiCorp domain) or a non-HashiCorp link.
|
|
26
|
+
*
|
|
27
|
+
* @param {string | undefined} url - The URL to be parsed. It may be a relative URL, an anchor, or a full external/internal URL.
|
|
28
|
+
*
|
|
29
|
+
* @returns {{ linkType: 'inbound' | 'outbound', href: string }}
|
|
30
|
+
* An object with two properties:
|
|
31
|
+
* - `linkType`: Indicates whether the URL is 'inbound' or 'outbound'. Can be used to conditionally
|
|
32
|
+
* render the value of the target attribute.
|
|
33
|
+
* - `href`: The parsed href (may include pathname, search, and hash for internal URLs).
|
|
34
|
+
*
|
|
35
|
+
* @throws {Error} Throws an error if the URL is undefined or invalid.
|
|
36
|
+
*/
|
|
1
37
|
export function parseUrl(url: string | undefined): {
|
|
2
|
-
linkType: 'inbound' | 'outbound'
|
|
38
|
+
linkType: 'inbound' | 'outbound' | ''
|
|
3
39
|
href: string
|
|
4
40
|
} {
|
|
5
41
|
if (!url) {
|
|
6
|
-
|
|
42
|
+
console.log('No url to parse, returning empty string')
|
|
43
|
+
return { linkType: '', href: '' }
|
|
7
44
|
}
|
|
8
45
|
|
|
9
46
|
if (isRelative(url) || isAnchor(url)) {
|
|
@@ -12,21 +49,50 @@ export function parseUrl(url: string | undefined): {
|
|
|
12
49
|
|
|
13
50
|
if (isInternal(url)) {
|
|
14
51
|
try {
|
|
15
|
-
const { pathname, search } = new URL(url)
|
|
16
|
-
const href = pathname + search
|
|
52
|
+
const { pathname, search, hash } = new URL(url)
|
|
53
|
+
const href = pathname + search + hash
|
|
17
54
|
return { linkType: 'inbound', href }
|
|
18
55
|
} catch (error) {
|
|
19
|
-
|
|
56
|
+
console.log(`Invalid href: ${url}`)
|
|
57
|
+
return { linkType: '', href: '' }
|
|
20
58
|
}
|
|
21
59
|
}
|
|
22
60
|
|
|
23
61
|
return { linkType: 'outbound', href: url }
|
|
24
62
|
}
|
|
25
63
|
|
|
26
|
-
const isRelative = (url) => url.startsWith('/')
|
|
27
|
-
const isAnchor = (url) => url.startsWith('#')
|
|
64
|
+
const isRelative = (url: string) => url.startsWith('/')
|
|
65
|
+
const isAnchor = (url: string) => url.startsWith('#')
|
|
28
66
|
|
|
29
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Determines whether the provided url uses hashicorp.com or www.hashicorp.com as the hostname.
|
|
69
|
+
*
|
|
70
|
+
* @param {string} url - The URL to check.
|
|
71
|
+
* @returns {boolean} - Returns true if the link uses a HashiCorp domain, otherwise false.
|
|
72
|
+
*/
|
|
73
|
+
|
|
74
|
+
export const isInternal = (url: string): boolean => {
|
|
30
75
|
const hostname = new URL(url).hostname
|
|
31
|
-
return hostname === 'hashicorp.com'
|
|
76
|
+
return hostname === 'hashicorp.com' || hostname === 'www.hashicorp.com'
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Determines whether the provided url uses a HashiCorp hostname. This is used in several
|
|
81
|
+
* components to open a new tab for non-HashiCorp links.
|
|
82
|
+
*
|
|
83
|
+
* @param {string} url - The URL to check.
|
|
84
|
+
* @returns {boolean} - Returns true if the link uses a HashiCorp domain, otherwise false.
|
|
85
|
+
*/
|
|
86
|
+
|
|
87
|
+
export const hasHashiCorpDestination = (url: string): boolean => {
|
|
88
|
+
// Fast return in case a relative URL or anchor is passed in
|
|
89
|
+
if (isRelative(url) || isAnchor(url)) return true
|
|
90
|
+
try {
|
|
91
|
+
const hostname = new URL(url).hostname
|
|
92
|
+
const isHashiCorpDestination = containsHashiCorpDestination(hostname)
|
|
93
|
+
return isHashiCorpDestination
|
|
94
|
+
} catch (e) {
|
|
95
|
+
console.error('Error: `url` is not a valid URL', e)
|
|
96
|
+
return false
|
|
97
|
+
}
|
|
32
98
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import posthog from 'posthog-js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A custom hook to send a custom event to PostHog.
|
|
5
|
+
*
|
|
6
|
+
* @param {string} eventName - The name of the custom event to be tracked in PostHog.
|
|
7
|
+
* @param {Record<string, any>} properties - A key-value object containing properties associated with the event.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const MyComponent = () => {
|
|
11
|
+
* sendPosthogEvent('button_click', { buttonId: 'submit', action: 'clicked' });
|
|
12
|
+
* return <button id="submit">Submit</button>;
|
|
13
|
+
* };
|
|
14
|
+
*/
|
|
15
|
+
const sendPosthogEvent = (
|
|
16
|
+
eventName: string,
|
|
17
|
+
properties: Record<string, any>
|
|
18
|
+
) => {
|
|
19
|
+
posthog.capture(eventName, properties)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default sendPosthogEvent
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const allSupportedLocales = ['en', 'de', 'es', 'fr', 'ja', 'ko', 'pt']
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import sendPosthogEvent from '../send-posthog-event'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Pushes a 'Nav link click' custom event to
|
|
5
|
-
* A wrapper around the
|
|
4
|
+
* Pushes a 'Nav link click' custom event to PostHog.
|
|
5
|
+
* A wrapper around the PostHog custom event method.
|
|
6
6
|
*
|
|
7
7
|
* @param {string} name - The name of the nav link
|
|
8
8
|
* @param {string} href - The href for the nav link
|
|
@@ -14,7 +14,7 @@ export const trackNavClickEvent = (
|
|
|
14
14
|
href: string,
|
|
15
15
|
section: string
|
|
16
16
|
) => {
|
|
17
|
-
|
|
17
|
+
sendPosthogEvent('Nav link click', {
|
|
18
18
|
name,
|
|
19
19
|
href,
|
|
20
20
|
section,
|
package/src/lib/v/index.ts
CHANGED
|
@@ -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
|
|
8
|
-
|
|
9
|
-
):
|
|
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
|