@windstream/react-shared-components 0.1.74 → 0.1.76
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/dist/contentful/index.d.ts +7 -0
- package/dist/contentful/index.esm.js +3 -3
- package/dist/contentful/index.esm.js.map +1 -1
- package/dist/contentful/index.js +3 -3
- package/dist/contentful/index.js.map +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/index.esm.js +5 -13
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +5 -13
- package/dist/index.js.map +1 -1
- package/dist/next/index.esm.js +2 -2
- package/dist/next/index.esm.js.map +1 -1
- package/dist/next/index.js +2 -2
- package/dist/next/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/utils/index.esm.js +1 -1
- package/dist/utils/index.esm.js.map +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
- package/src/contentful/blocks/navigation/desktop-link-groups.tsx/index.tsx +17 -2
- package/src/contentful/blocks/navigation/index.tsx +239 -134
- package/src/contentful/blocks/navigation/types.ts +7 -0
|
@@ -36,129 +36,213 @@ export const Navigation: React.FC<NavigationProps> = props => {
|
|
|
36
36
|
primaryNavigationLogoWidth = 76.5,
|
|
37
37
|
primaryNavigationLogoHeight = 24,
|
|
38
38
|
hideMobileCallButton = false,
|
|
39
|
+
displayUtilityNavigation = true,
|
|
40
|
+
displaySearchBar = true,
|
|
41
|
+
displayCallNowCta = true,
|
|
42
|
+
showCallButton = true,
|
|
43
|
+
showCallNowCtaInMainNav = false,
|
|
44
|
+
showMobileSliderMenu = true,
|
|
45
|
+
callNowCtaIcon,
|
|
46
|
+
navigationBackgroundColor,
|
|
47
|
+
navigationLinkColor,
|
|
39
48
|
} = props;
|
|
49
|
+
|
|
50
|
+
const logoUrl =
|
|
51
|
+
typeof primaryNavigationLogo === "string"
|
|
52
|
+
? primaryNavigationLogo
|
|
53
|
+
: primaryNavigationLogo?.url || "";
|
|
54
|
+
|
|
55
|
+
// Background token convention matches the legacy ResidentialNavbar:
|
|
56
|
+
// when CMS provides a token like "navy500" we map it to
|
|
57
|
+
// `bg-secondary-navy500`. Raw Tailwind classes (containing a `-`)
|
|
58
|
+
// are passed through untouched. Defaults to `bg-secondary-navy500`
|
|
59
|
+
// to preserve legacy behavior when CMS leaves the field empty.
|
|
60
|
+
const mainNavBgClass = navigationBackgroundColor
|
|
61
|
+
? navigationBackgroundColor.includes("-") ||
|
|
62
|
+
navigationBackgroundColor.startsWith("bg-")
|
|
63
|
+
? navigationBackgroundColor
|
|
64
|
+
: `bg-secondary-${navigationBackgroundColor}`
|
|
65
|
+
: "bg-secondary-navy500";
|
|
66
|
+
|
|
67
|
+
const callNowCtaIconUrl =
|
|
68
|
+
typeof callNowCtaIcon === "string"
|
|
69
|
+
? callNowCtaIcon
|
|
70
|
+
: callNowCtaIcon?.url || "";
|
|
71
|
+
|
|
72
|
+
// Styled "Call Now" pill used in the main nav rows when CMS opts in via
|
|
73
|
+
// `showCallNowCtaInMainNav` (desktop) or when the mobile slider menu is
|
|
74
|
+
// disabled (`showMobileSliderMenu: false`). Mirrors the legacy
|
|
75
|
+
// ResidentialNavbar styling so existing CMS entries render identically.
|
|
76
|
+
const renderMainNavCallCta = (
|
|
77
|
+
onClick?: (event: React.MouseEvent<HTMLAnchorElement>) => void
|
|
78
|
+
) => (
|
|
79
|
+
<Link
|
|
80
|
+
href={invocaPhoneNumberLink || "#"}
|
|
81
|
+
onClick={onClick}
|
|
82
|
+
className="bg-secondary-gray100 text-secondary-navy500 inline-flex h-8 items-center rounded-full pl-1 pr-2 no-underline shadow-none"
|
|
83
|
+
aria-label={
|
|
84
|
+
invocaPhoneNumberDisplayText
|
|
85
|
+
? `Call ${invocaPhoneNumberDisplayText}`
|
|
86
|
+
: "Call now"
|
|
87
|
+
}
|
|
88
|
+
>
|
|
89
|
+
{callNowCtaIconUrl ? (
|
|
90
|
+
<NextImage
|
|
91
|
+
src={callNowCtaIconUrl}
|
|
92
|
+
alt="Call us"
|
|
93
|
+
width={24}
|
|
94
|
+
height={24}
|
|
95
|
+
className="mr-2 self-center rounded-full"
|
|
96
|
+
/>
|
|
97
|
+
) : null}
|
|
98
|
+
<Text as="span" className="text-secondary-navy500 footnote">
|
|
99
|
+
{invocaPhoneNumberDisplayText}
|
|
100
|
+
</Text>
|
|
101
|
+
</Link>
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
const hasMobileMenuItems =
|
|
105
|
+
(primaryNavigationLinks?.length ?? 0) > 0 ||
|
|
106
|
+
(supportNavigationLinks?.length ?? 0) > 0 ||
|
|
107
|
+
(accountNavigationLinks?.length ?? 0) > 0;
|
|
108
|
+
|
|
40
109
|
return (
|
|
41
110
|
<div className="component-container">
|
|
42
111
|
<nav className={`menu-container z-[1000]`}>
|
|
43
|
-
|
|
44
|
-
<div className="
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
<
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
Object.
|
|
60
|
-
|
|
112
|
+
{displayUtilityNavigation ? (
|
|
113
|
+
<div className="utility-container hidden lg:block lg:border-b lg:px-2">
|
|
114
|
+
<div className="mx-auto flex max-w-120 justify-between">
|
|
115
|
+
<ul className="flex gap-5" aria-label="Utility Navigation">
|
|
116
|
+
{utilityNavigationLinks?.map((links, index) => {
|
|
117
|
+
return (
|
|
118
|
+
<li key={`main-menu-items-${index}`}>
|
|
119
|
+
<ContentfulButton
|
|
120
|
+
linkClassName={cx(
|
|
121
|
+
"footnote flex items-center w-full h-11 text-text",
|
|
122
|
+
// If utilityNavActiveIndex is not provided, default to making the second link active (for existing business app). If utilityNavActiveIndex is provided, use it to determine which link is active.
|
|
123
|
+
typeof utilityNavActiveIndex !== "number"
|
|
124
|
+
? index === 1 && "label4"
|
|
125
|
+
: utilityNavActiveIndex === index && "label4"
|
|
126
|
+
)}
|
|
127
|
+
linkVariant="unstyled"
|
|
128
|
+
{...(Object.fromEntries(
|
|
129
|
+
Object.entries(links).filter(([_, v]) => v !== null)
|
|
130
|
+
) as any)}
|
|
131
|
+
/>
|
|
132
|
+
</li>
|
|
133
|
+
);
|
|
134
|
+
})}
|
|
135
|
+
</ul>
|
|
136
|
+
<div className="flex items-center gap-10">
|
|
137
|
+
{displayCallNowCta ? (
|
|
138
|
+
<CallButton
|
|
139
|
+
className="border-none"
|
|
140
|
+
href={invocaPhoneNumberLink}
|
|
141
|
+
prefix={callNowCtaText}
|
|
142
|
+
onClick={onCallClickDesktop}
|
|
143
|
+
>
|
|
144
|
+
<Text className="body3 text-text">
|
|
145
|
+
{invocaPhoneNumberDisplayText}
|
|
146
|
+
</Text>
|
|
147
|
+
</CallButton>
|
|
148
|
+
) : null}
|
|
149
|
+
{displayCartIcon ? (
|
|
150
|
+
<Link
|
|
151
|
+
href={cartHref || "#"}
|
|
152
|
+
className="relative inline-flex cursor-pointer"
|
|
153
|
+
aria-label={cartIconAriaLabel}
|
|
154
|
+
onClick={onCartClick}
|
|
155
|
+
>
|
|
156
|
+
<MaterialIcon name="shopping_cart" />
|
|
157
|
+
{cartHasRetention ? (
|
|
158
|
+
<span className="absolute -right-2 -top-1 h-2.5 w-2.5 rounded-full bg-icon-brand" />
|
|
159
|
+
) : null}
|
|
160
|
+
</Link>
|
|
161
|
+
) : null}
|
|
162
|
+
{accountNavigationLinks?.map((links, index) => {
|
|
163
|
+
return (
|
|
164
|
+
<DesktopLinkGroups
|
|
165
|
+
key={`my-account-${index}`}
|
|
166
|
+
anchorName={`my-account-${index}`}
|
|
167
|
+
link={links}
|
|
61
168
|
/>
|
|
62
|
-
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
</ul>
|
|
66
|
-
<div className="flex items-center gap-10">
|
|
67
|
-
<CallButton
|
|
68
|
-
className="border-none"
|
|
69
|
-
href={invocaPhoneNumberLink}
|
|
70
|
-
prefix={callNowCtaText}
|
|
71
|
-
onClick={onCallClickDesktop}
|
|
72
|
-
>
|
|
73
|
-
<Text className="body3 text-text">
|
|
74
|
-
{invocaPhoneNumberDisplayText}
|
|
75
|
-
</Text>
|
|
76
|
-
</CallButton>
|
|
77
|
-
{displayCartIcon ? (
|
|
78
|
-
<Link
|
|
79
|
-
href={cartHref || "#"}
|
|
80
|
-
className="relative inline-flex cursor-pointer"
|
|
81
|
-
aria-label={cartIconAriaLabel}
|
|
82
|
-
onClick={onCartClick}
|
|
83
|
-
>
|
|
84
|
-
<MaterialIcon name="shopping_cart" />
|
|
85
|
-
{cartHasRetention ? (
|
|
86
|
-
<span className="absolute -right-2 -top-1 h-2.5 w-2.5 rounded-full bg-icon-brand" />
|
|
87
|
-
) : null}
|
|
88
|
-
</Link>
|
|
89
|
-
) : null}
|
|
90
|
-
{accountNavigationLinks?.map((links, index) => {
|
|
91
|
-
return (
|
|
92
|
-
<DesktopLinkGroups
|
|
93
|
-
key={`my-account-${index}`}
|
|
94
|
-
anchorName={`my-account-${index}`}
|
|
95
|
-
link={links}
|
|
96
|
-
/>
|
|
97
|
-
);
|
|
98
|
-
})}
|
|
169
|
+
);
|
|
170
|
+
})}
|
|
171
|
+
</div>
|
|
99
172
|
</div>
|
|
100
173
|
</div>
|
|
101
|
-
|
|
102
|
-
<div
|
|
174
|
+
) : null}
|
|
175
|
+
<div
|
|
176
|
+
className={cx(
|
|
177
|
+
"main-nav-container",
|
|
178
|
+
mainNavBgClass,
|
|
179
|
+
navigationLinkColor
|
|
180
|
+
)}
|
|
181
|
+
aria-label="Main Navigation"
|
|
182
|
+
>
|
|
103
183
|
<div className="mobile-nav-section flex h-14 items-center justify-between border border-b px-5 py-[10px] lg:hidden">
|
|
104
184
|
<div>
|
|
105
|
-
|
|
106
|
-
<
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
/>
|
|
116
|
-
</Link>
|
|
185
|
+
{logoUrl ? (
|
|
186
|
+
<Link href="/" className="flex">
|
|
187
|
+
<NextImage
|
|
188
|
+
src={logoUrl}
|
|
189
|
+
alt="Kinetic business logo"
|
|
190
|
+
width={primaryNavigationLogoWidth}
|
|
191
|
+
height={primaryNavigationLogoHeight}
|
|
192
|
+
/>
|
|
193
|
+
</Link>
|
|
194
|
+
) : null}
|
|
117
195
|
</div>
|
|
118
196
|
<div className="flex items-center gap-6">
|
|
119
|
-
{
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
onClick={onCartClick}
|
|
135
|
-
>
|
|
136
|
-
<MaterialIcon name="shopping_cart" />
|
|
137
|
-
{cartHasRetention ? (
|
|
138
|
-
<span className="absolute -right-2 -top-1 h-2.5 w-2.5 rounded-full bg-icon-brand" />
|
|
197
|
+
{!showMobileSliderMenu ? (
|
|
198
|
+
showCallButton ? (
|
|
199
|
+
renderMainNavCallCta(onCallClickMobile)
|
|
200
|
+
) : null
|
|
201
|
+
) : (
|
|
202
|
+
<>
|
|
203
|
+
{showCallButton && !hideMobileCallButton ? (
|
|
204
|
+
<CallButton
|
|
205
|
+
href={invocaPhoneNumberLink}
|
|
206
|
+
onClick={onCallClickMobile}
|
|
207
|
+
>
|
|
208
|
+
<Text as="span" className="footnote">
|
|
209
|
+
{invocaPhoneNumberDisplayText}
|
|
210
|
+
</Text>
|
|
211
|
+
</CallButton>
|
|
139
212
|
) : null}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
213
|
+
{displayCartIcon ? (
|
|
214
|
+
<Link
|
|
215
|
+
href={cartHref || "#"}
|
|
216
|
+
className="relative inline-flex cursor-pointer"
|
|
217
|
+
aria-label={cartIconAriaLabel}
|
|
218
|
+
onClick={onCartClick}
|
|
219
|
+
>
|
|
220
|
+
<MaterialIcon name="shopping_cart" />
|
|
221
|
+
{cartHasRetention ? (
|
|
222
|
+
<span className="absolute -right-2 -top-1 h-2.5 w-2.5 rounded-full bg-icon-brand" />
|
|
223
|
+
) : null}
|
|
224
|
+
</Link>
|
|
225
|
+
) : null}
|
|
226
|
+
{hasMobileMenuItems ? <MobileMenu {...props} /> : null}
|
|
227
|
+
</>
|
|
228
|
+
)}
|
|
143
229
|
</div>
|
|
144
230
|
</div>
|
|
145
231
|
|
|
146
232
|
<div className="desktop-nav-section hidden lg:block lg:border-b lg:px-2">
|
|
147
233
|
<div className="mx-auto flex h-14 max-w-120 items-center justify-between">
|
|
148
234
|
<div className="flex h-full">
|
|
149
|
-
|
|
150
|
-
<
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
/>
|
|
161
|
-
</Link>
|
|
235
|
+
{logoUrl ? (
|
|
236
|
+
<Link href="/" className="flex">
|
|
237
|
+
<NextImage
|
|
238
|
+
src={logoUrl}
|
|
239
|
+
alt="Kinetic business logo"
|
|
240
|
+
width={primaryNavigationLogoWidth}
|
|
241
|
+
height={primaryNavigationLogoHeight}
|
|
242
|
+
className="mr-[64px]"
|
|
243
|
+
/>
|
|
244
|
+
</Link>
|
|
245
|
+
) : null}
|
|
162
246
|
|
|
163
247
|
<div className="flex h-full items-center gap-5">
|
|
164
248
|
{primaryNavigationLinks?.map((links, index) => {
|
|
@@ -167,26 +251,33 @@ export const Navigation: React.FC<NavigationProps> = props => {
|
|
|
167
251
|
key={`main-menu-${index}`}
|
|
168
252
|
anchorName={`main-menu-${index}`}
|
|
169
253
|
link={links}
|
|
254
|
+
linkColorClassName={navigationLinkColor}
|
|
170
255
|
/>
|
|
171
256
|
);
|
|
172
257
|
})}
|
|
173
258
|
</div>
|
|
174
259
|
</div>
|
|
175
260
|
<div className="flex h-full items-center gap-10">
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
261
|
+
{showCallNowCtaInMainNav
|
|
262
|
+
? renderMainNavCallCta(onCallClickDesktop)
|
|
263
|
+
: null}
|
|
264
|
+
{displaySearchBar ? (
|
|
265
|
+
<DesktopSearchInput
|
|
266
|
+
searchBarIconURL={
|
|
267
|
+
typeof searchBarIcon === "string"
|
|
268
|
+
? searchBarIcon
|
|
269
|
+
: searchBarIcon?.url || ""
|
|
270
|
+
}
|
|
271
|
+
onSearch={onSearch}
|
|
272
|
+
/>
|
|
273
|
+
) : null}
|
|
184
274
|
{supportNavigationLinks?.map((links, index) => {
|
|
185
275
|
return (
|
|
186
276
|
<DesktopLinkGroups
|
|
187
277
|
key={`support-menu-${index}`}
|
|
188
278
|
anchorName={`support-menu-${index}`}
|
|
189
279
|
link={links}
|
|
280
|
+
linkColorClassName={navigationLinkColor}
|
|
190
281
|
/>
|
|
191
282
|
);
|
|
192
283
|
})}
|
|
@@ -207,6 +298,9 @@ const MobileMenu = (props: NavigationProps) => {
|
|
|
207
298
|
utilityNavigationLinks,
|
|
208
299
|
supportNavigationLinks,
|
|
209
300
|
accountNavigationLinks,
|
|
301
|
+
showCallButton,
|
|
302
|
+
displayCallNowCta,
|
|
303
|
+
displaySearchBar,
|
|
210
304
|
} = props;
|
|
211
305
|
const [isOpen, setIsOpen] = React.useState(false);
|
|
212
306
|
|
|
@@ -274,7 +368,7 @@ const MobileMenu = (props: NavigationProps) => {
|
|
|
274
368
|
<div
|
|
275
369
|
className={cx(
|
|
276
370
|
"fixed bottom-0 right-0 top-0",
|
|
277
|
-
"z-[100] h-full bg-bg px-0 py-4",
|
|
371
|
+
"z-[100] h-full bg-bg px-0 py-4 text-text",
|
|
278
372
|
"transition-all duration-300 ease-in-out",
|
|
279
373
|
"block",
|
|
280
374
|
isOpen ? "right-0" : "-right-96"
|
|
@@ -282,16 +376,25 @@ const MobileMenu = (props: NavigationProps) => {
|
|
|
282
376
|
id="mobile-menu-overlay"
|
|
283
377
|
>
|
|
284
378
|
<div id="drawer-items" className="flex h-full flex-col gap-3">
|
|
285
|
-
<div
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
379
|
+
<div
|
|
380
|
+
className={cx(
|
|
381
|
+
"flex items-center px-4",
|
|
382
|
+
showCallButton !== false || displayCallNowCta !== false
|
|
383
|
+
? "justify-between"
|
|
384
|
+
: "justify-end"
|
|
385
|
+
)}
|
|
386
|
+
>
|
|
387
|
+
{showCallButton !== false || displayCallNowCta !== false ? (
|
|
388
|
+
<div>
|
|
389
|
+
<CallButton
|
|
390
|
+
className="border-none"
|
|
391
|
+
href={props.invocaPhoneNumberLink}
|
|
392
|
+
onClick={props.onCallClickMobile}
|
|
393
|
+
>
|
|
394
|
+
{props.invocaPhoneNumberDisplayText}
|
|
395
|
+
</CallButton>
|
|
396
|
+
</div>
|
|
397
|
+
) : null}
|
|
295
398
|
<div>
|
|
296
399
|
<ContentfulButton
|
|
297
400
|
showButtonAs="unstyled"
|
|
@@ -302,16 +405,18 @@ const MobileMenu = (props: NavigationProps) => {
|
|
|
302
405
|
</ContentfulButton>
|
|
303
406
|
</div>
|
|
304
407
|
</div>
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
408
|
+
{displaySearchBar !== false ? (
|
|
409
|
+
<MobileSearchInput
|
|
410
|
+
closeMenu={closeMenu}
|
|
411
|
+
isMenuOpen={isOpen}
|
|
412
|
+
searchBarIconURL={
|
|
413
|
+
typeof props.searchBarIcon === "string"
|
|
414
|
+
? props.searchBarIcon
|
|
415
|
+
: props.searchBarIcon?.url || ""
|
|
416
|
+
}
|
|
417
|
+
onSearch={props.onSearch || (() => {})}
|
|
418
|
+
/>
|
|
419
|
+
) : null}
|
|
315
420
|
<div
|
|
316
421
|
className="flex-grow overflow-y-auto"
|
|
317
422
|
onClick={event => {
|
|
@@ -22,6 +22,13 @@ export interface Navigation {
|
|
|
22
22
|
navigationBackgroundColor?: Color;
|
|
23
23
|
utilityNavBackgroundColor?: Color;
|
|
24
24
|
utilityNavLinkColor?: Color;
|
|
25
|
+
/**
|
|
26
|
+
* Tailwind class (or raw class string) applied to the main nav row's
|
|
27
|
+
* text color, e.g. `"text-white"` or `"text-secondary-navy500"`. Used
|
|
28
|
+
* by section / secondary navbars rendered on a dark background where
|
|
29
|
+
* the labels need to be inverted.
|
|
30
|
+
*/
|
|
31
|
+
navigationLinkColor?: string;
|
|
25
32
|
utilityNavActiveIndex?: number;
|
|
26
33
|
|
|
27
34
|
callNowCtaText?: string;
|