@windstream/react-shared-components 0.1.74 → 0.1.75

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.
@@ -36,87 +36,121 @@ 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
+ navigationBackgroundColor,
44
+ navigationLinkColor,
39
45
  } = props;
46
+
47
+ const logoUrl =
48
+ typeof primaryNavigationLogo === "string"
49
+ ? primaryNavigationLogo
50
+ : primaryNavigationLogo?.url || "";
51
+
52
+ // Background token convention matches the legacy ResidentialNavbar:
53
+ // when CMS provides a token like "navy500" we map it to
54
+ // `bg-secondary-navy500`. Raw Tailwind classes (containing a `-`)
55
+ // are passed through untouched. Defaults to `bg-secondary-navy500`
56
+ // to preserve legacy behavior when CMS leaves the field empty.
57
+ const mainNavBgClass = navigationBackgroundColor
58
+ ? navigationBackgroundColor.includes("-") ||
59
+ navigationBackgroundColor.startsWith("bg-")
60
+ ? navigationBackgroundColor
61
+ : `bg-secondary-${navigationBackgroundColor}`
62
+ : "bg-secondary-navy500";
63
+
64
+ const hasMobileMenuItems =
65
+ (primaryNavigationLinks?.length ?? 0) > 0 ||
66
+ (supportNavigationLinks?.length ?? 0) > 0 ||
67
+ (accountNavigationLinks?.length ?? 0) > 0;
68
+
40
69
  return (
41
70
  <div className="component-container">
42
71
  <nav className={`menu-container z-[1000]`}>
43
- <div className="utility-container hidden lg:block lg:border-b lg:px-2">
44
- <div className="mx-auto flex max-w-120 justify-between">
45
- <ul className="flex gap-5" aria-label="Utility Navigation">
46
- {utilityNavigationLinks?.map((links, index) => {
47
- return (
48
- <li key={`main-menu-items-${index}`}>
49
- <ContentfulButton
50
- linkClassName={cx(
51
- "footnote flex items-center w-full h-11 text-text",
52
- // 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.
53
- typeof utilityNavActiveIndex !== "number"
54
- ? index === 1 && "label4"
55
- : utilityNavActiveIndex === index && "label4"
56
- )}
57
- linkVariant="unstyled"
58
- {...(Object.fromEntries(
59
- Object.entries(links).filter(([_, v]) => v !== null)
60
- ) as any)}
72
+ {displayUtilityNavigation ? (
73
+ <div className="utility-container hidden lg:block lg:border-b lg:px-2">
74
+ <div className="mx-auto flex max-w-120 justify-between">
75
+ <ul className="flex gap-5" aria-label="Utility Navigation">
76
+ {utilityNavigationLinks?.map((links, index) => {
77
+ return (
78
+ <li key={`main-menu-items-${index}`}>
79
+ <ContentfulButton
80
+ linkClassName={cx(
81
+ "footnote flex items-center w-full h-11 text-text",
82
+ // 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.
83
+ typeof utilityNavActiveIndex !== "number"
84
+ ? index === 1 && "label4"
85
+ : utilityNavActiveIndex === index && "label4"
86
+ )}
87
+ linkVariant="unstyled"
88
+ {...(Object.fromEntries(
89
+ Object.entries(links).filter(([_, v]) => v !== null)
90
+ ) as any)}
91
+ />
92
+ </li>
93
+ );
94
+ })}
95
+ </ul>
96
+ <div className="flex items-center gap-10">
97
+ {displayCallNowCta ? (
98
+ <CallButton
99
+ className="border-none"
100
+ href={invocaPhoneNumberLink}
101
+ prefix={callNowCtaText}
102
+ onClick={onCallClickDesktop}
103
+ >
104
+ <Text className="body3 text-text">
105
+ {invocaPhoneNumberDisplayText}
106
+ </Text>
107
+ </CallButton>
108
+ ) : null}
109
+ {displayCartIcon ? (
110
+ <Link
111
+ href={cartHref || "#"}
112
+ className="relative inline-flex cursor-pointer"
113
+ aria-label={cartIconAriaLabel}
114
+ onClick={onCartClick}
115
+ >
116
+ <MaterialIcon name="shopping_cart" />
117
+ {cartHasRetention ? (
118
+ <span className="absolute -right-2 -top-1 h-2.5 w-2.5 rounded-full bg-icon-brand" />
119
+ ) : null}
120
+ </Link>
121
+ ) : null}
122
+ {accountNavigationLinks?.map((links, index) => {
123
+ return (
124
+ <DesktopLinkGroups
125
+ key={`my-account-${index}`}
126
+ anchorName={`my-account-${index}`}
127
+ link={links}
61
128
  />
62
- </li>
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
- })}
129
+ );
130
+ })}
131
+ </div>
99
132
  </div>
100
133
  </div>
101
- </div>
102
- <div className="main-nav-container" aria-label="Main Navigation">
134
+ ) : null}
135
+ <div
136
+ className={cx("main-nav-container", mainNavBgClass, navigationLinkColor)}
137
+ aria-label="Main Navigation"
138
+ >
103
139
  <div className="mobile-nav-section flex h-14 items-center justify-between border border-b px-5 py-[10px] lg:hidden">
104
140
  <div>
105
- <Link href="/" className="flex">
106
- <NextImage
107
- src={
108
- typeof primaryNavigationLogo === "string"
109
- ? primaryNavigationLogo
110
- : primaryNavigationLogo?.url || ""
111
- }
112
- alt="Kinetic business logo"
113
- width={primaryNavigationLogoWidth}
114
- height={primaryNavigationLogoHeight}
115
- />
116
- </Link>
141
+ {logoUrl ? (
142
+ <Link href="/" className="flex">
143
+ <NextImage
144
+ src={logoUrl}
145
+ alt="Kinetic business logo"
146
+ width={primaryNavigationLogoWidth}
147
+ height={primaryNavigationLogoHeight}
148
+ />
149
+ </Link>
150
+ ) : null}
117
151
  </div>
118
152
  <div className="flex items-center gap-6">
119
- {hideMobileCallButton ? null : (
153
+ {showCallButton && !hideMobileCallButton ? (
120
154
  <CallButton
121
155
  href={invocaPhoneNumberLink}
122
156
  onClick={onCallClickMobile}
@@ -125,7 +159,7 @@ export const Navigation: React.FC<NavigationProps> = props => {
125
159
  {invocaPhoneNumberDisplayText}
126
160
  </Text>
127
161
  </CallButton>
128
- )}
162
+ ) : null}
129
163
  {displayCartIcon ? (
130
164
  <Link
131
165
  href={cartHref || "#"}
@@ -139,26 +173,24 @@ export const Navigation: React.FC<NavigationProps> = props => {
139
173
  ) : null}
140
174
  </Link>
141
175
  ) : null}
142
- <MobileMenu {...props} />
176
+ {hasMobileMenuItems ? <MobileMenu {...props} /> : null}
143
177
  </div>
144
178
  </div>
145
179
 
146
180
  <div className="desktop-nav-section hidden lg:block lg:border-b lg:px-2">
147
181
  <div className="mx-auto flex h-14 max-w-120 items-center justify-between">
148
182
  <div className="flex h-full">
149
- <Link href="/" className="flex">
150
- <NextImage
151
- src={
152
- typeof primaryNavigationLogo === "string"
153
- ? primaryNavigationLogo
154
- : primaryNavigationLogo?.url || ""
155
- }
156
- alt="Kinetic business logo"
157
- width={primaryNavigationLogoWidth}
158
- height={primaryNavigationLogoHeight}
159
- className="mr-[64px]"
160
- />
161
- </Link>
183
+ {logoUrl ? (
184
+ <Link href="/" className="flex">
185
+ <NextImage
186
+ src={logoUrl}
187
+ alt="Kinetic business logo"
188
+ width={primaryNavigationLogoWidth}
189
+ height={primaryNavigationLogoHeight}
190
+ className="mr-[64px]"
191
+ />
192
+ </Link>
193
+ ) : null}
162
194
 
163
195
  <div className="flex h-full items-center gap-5">
164
196
  {primaryNavigationLinks?.map((links, index) => {
@@ -167,26 +199,30 @@ export const Navigation: React.FC<NavigationProps> = props => {
167
199
  key={`main-menu-${index}`}
168
200
  anchorName={`main-menu-${index}`}
169
201
  link={links}
202
+ linkColorClassName={navigationLinkColor}
170
203
  />
171
204
  );
172
205
  })}
173
206
  </div>
174
207
  </div>
175
208
  <div className="flex h-full items-center gap-10">
176
- <DesktopSearchInput
177
- searchBarIconURL={
178
- typeof searchBarIcon === "string"
179
- ? searchBarIcon
180
- : searchBarIcon?.url || ""
181
- }
182
- onSearch={onSearch}
183
- />
209
+ {displaySearchBar ? (
210
+ <DesktopSearchInput
211
+ searchBarIconURL={
212
+ typeof searchBarIcon === "string"
213
+ ? searchBarIcon
214
+ : searchBarIcon?.url || ""
215
+ }
216
+ onSearch={onSearch}
217
+ />
218
+ ) : null}
184
219
  {supportNavigationLinks?.map((links, index) => {
185
220
  return (
186
221
  <DesktopLinkGroups
187
222
  key={`support-menu-${index}`}
188
223
  anchorName={`support-menu-${index}`}
189
224
  link={links}
225
+ linkColorClassName={navigationLinkColor}
190
226
  />
191
227
  );
192
228
  })}
@@ -207,6 +243,9 @@ const MobileMenu = (props: NavigationProps) => {
207
243
  utilityNavigationLinks,
208
244
  supportNavigationLinks,
209
245
  accountNavigationLinks,
246
+ showCallButton,
247
+ displayCallNowCta,
248
+ displaySearchBar,
210
249
  } = props;
211
250
  const [isOpen, setIsOpen] = React.useState(false);
212
251
 
@@ -274,7 +313,7 @@ const MobileMenu = (props: NavigationProps) => {
274
313
  <div
275
314
  className={cx(
276
315
  "fixed bottom-0 right-0 top-0",
277
- "z-[100] h-full bg-bg px-0 py-4",
316
+ "z-[100] h-full bg-bg px-0 py-4 text-text",
278
317
  "transition-all duration-300 ease-in-out",
279
318
  "block",
280
319
  isOpen ? "right-0" : "-right-96"
@@ -282,16 +321,25 @@ const MobileMenu = (props: NavigationProps) => {
282
321
  id="mobile-menu-overlay"
283
322
  >
284
323
  <div id="drawer-items" className="flex h-full flex-col gap-3">
285
- <div className="flex items-center justify-between px-4">
286
- <div>
287
- <CallButton
288
- className="border-none"
289
- href={props.invocaPhoneNumberLink}
290
- onClick={props.onCallClickMobile}
291
- >
292
- {props.invocaPhoneNumberDisplayText}
293
- </CallButton>
294
- </div>
324
+ <div
325
+ className={cx(
326
+ "flex items-center px-4",
327
+ showCallButton !== false || displayCallNowCta !== false
328
+ ? "justify-between"
329
+ : "justify-end"
330
+ )}
331
+ >
332
+ {showCallButton !== false || displayCallNowCta !== false ? (
333
+ <div>
334
+ <CallButton
335
+ className="border-none"
336
+ href={props.invocaPhoneNumberLink}
337
+ onClick={props.onCallClickMobile}
338
+ >
339
+ {props.invocaPhoneNumberDisplayText}
340
+ </CallButton>
341
+ </div>
342
+ ) : null}
295
343
  <div>
296
344
  <ContentfulButton
297
345
  showButtonAs="unstyled"
@@ -302,16 +350,18 @@ const MobileMenu = (props: NavigationProps) => {
302
350
  </ContentfulButton>
303
351
  </div>
304
352
  </div>
305
- <MobileSearchInput
306
- closeMenu={closeMenu}
307
- isMenuOpen={isOpen}
308
- searchBarIconURL={
309
- typeof props.searchBarIcon === "string"
310
- ? props.searchBarIcon
311
- : props.searchBarIcon?.url || ""
312
- }
313
- onSearch={props.onSearch || (() => {})}
314
- />
353
+ {displaySearchBar !== false ? (
354
+ <MobileSearchInput
355
+ closeMenu={closeMenu}
356
+ isMenuOpen={isOpen}
357
+ searchBarIconURL={
358
+ typeof props.searchBarIcon === "string"
359
+ ? props.searchBarIcon
360
+ : props.searchBarIcon?.url || ""
361
+ }
362
+ onSearch={props.onSearch || (() => {})}
363
+ />
364
+ ) : null}
315
365
  <div
316
366
  className="flex-grow overflow-y-auto"
317
367
  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;