@windstream/react-shared-components 0.1.44 → 0.1.46

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.
@@ -1,5 +1,7 @@
1
- import React from "react";
2
- import { AccordionProps, ThemeKey } from "./types";
1
+ "use client";
2
+
3
+ import React, { useEffect, useState } from "react";
4
+ import { AccordionItem, AccordionProps, ThemeKey } from "./types";
3
5
 
4
6
  import { Accordion as AccordionComponent } from "@shared/components/accordion";
5
7
  import { Divider } from "@shared/components/divider";
@@ -8,10 +10,40 @@ import { Text } from "@shared/components/text";
8
10
  export const Accordion: React.FC<AccordionProps> = ({
9
11
  items,
10
12
  title,
13
+ anchorId,
11
14
  background = "white",
12
15
  enableHeading = false,
13
16
  maxWidth = true,
17
+ initialExpandedItems: initialExpandedItemsProp = [],
18
+ hashAutoExpand = false,
19
+ descriptionMaxWidth = "max-w-[980px]",
20
+ itemContainerClassName,
14
21
  }) => {
22
+ const [expandedItems, setExpandedItems] = useState<string[]>(
23
+ initialExpandedItemsProp
24
+ );
25
+
26
+ useEffect(() => {
27
+ if (hashAutoExpand && typeof window !== "undefined") {
28
+ const hash = window.location.hash;
29
+ if (hash) {
30
+ const expandItemId = hash.substring(hash.indexOf("#") + 1);
31
+ setExpandedItems(prev => {
32
+ if (prev.includes(expandItemId)) return prev;
33
+ return [...prev, expandItemId];
34
+ });
35
+ }
36
+ }
37
+ }, [hashAutoExpand]);
38
+
39
+ const handleToggle = (itemAnchorId: string) => {
40
+ setExpandedItems(prev =>
41
+ prev.includes(itemAnchorId)
42
+ ? prev.filter(id => id !== itemAnchorId)
43
+ : [...prev, itemAnchorId]
44
+ );
45
+ };
46
+
15
47
  const bgColorClasses: Record<ThemeKey, string> = {
16
48
  blue: "bg-[#07B2E2]",
17
49
  green: "bg-[#26B170]",
@@ -19,43 +51,61 @@ export const Accordion: React.FC<AccordionProps> = ({
19
51
  purple: "bg-[#931D69]",
20
52
  white: "bg-white",
21
53
  navy: "bg-[#00002D]",
54
+ cream500: "bg-[#FFFEEF]",
22
55
  };
56
+
23
57
  return (
24
- <div className={`${bgColorClasses[background]} component-container`}>
25
- <div
26
- className={`${maxWidth ? "max-w-120 xl:mx-auto" : ""} mx-5 my-8 lg:mx-20 lg:my-18`}
27
- >
28
- <div>
29
- <Text
30
- as={enableHeading ? "h1" : "h2"}
31
- className="heading2 text-left text-text md:heading1 lg:text-center"
32
- >
33
- {title}
34
- </Text>
35
- </div>
36
- <div className="question-answer-section mt-10 lg:mt-16">
37
- {items?.map((item: any, index: number) => (
38
- <div key={`item-${index}`}>
39
- <AccordionComponent
40
- title={item.title}
41
- containerClassName="border-none"
42
- buttonClassName="p-0 label1"
43
- titleClassName="label3 md:label1 text-text"
44
- className="p-0 pt-6 text-text"
45
- iconClassName="text-icon"
46
- borderRadiusNone={true}
47
- openOnlyOnDesktop={false}
58
+ <section
59
+ id={anchorId}
60
+ className={`${bgColorClasses[background]} flex flex-col px-2 pb-20 pt-4 md:px-10`}
61
+ >
62
+ <div className={`${maxWidth ? "max-w-120 xl:mx-auto" : ""}`}>
63
+ <Text
64
+ as={enableHeading ? "h1" : "h2"}
65
+ className="heading2 mb-10 pt-12 text-left text-text md:heading1 lg:text-center"
66
+ >
67
+ {title}
68
+ </Text>
69
+ <div className={`pt-6 md:pt-10 ${itemContainerClassName ?? ""}`}>
70
+ {items?.map((item: AccordionItem, index: number) => {
71
+ const itemKey = item.anchorId || `item-${index}`;
72
+ const isOpen = item.anchorId
73
+ ? expandedItems.includes(item.anchorId)
74
+ : undefined;
75
+
76
+ return (
77
+ <div
78
+ key={itemKey}
79
+ id={item.anchorId}
80
+ className="snap-start scroll-mt-48 lg:scroll-mt-60"
48
81
  >
49
- <Text as="div">{item.description}</Text>
50
- </AccordionComponent>
51
- {index < items.length - 1 && (
52
- <Divider key={`divider-${index}`} className="my-6 md:my-10" />
53
- )}
54
- </div>
55
- ))}
82
+ <AccordionComponent
83
+ title={item.title}
84
+ defaultOpen={isOpen}
85
+ containerClassName="border-none"
86
+ buttonClassName="p-0 label1"
87
+ titleClassName="label3 md:label1 text-text"
88
+ className="p-0 pt-6 text-text"
89
+ iconClassName="text-icon"
90
+ borderRadiusNone={true}
91
+ openOnlyOnDesktop={false}
92
+ {...(item.anchorId && {
93
+ onClick: () => handleToggle(item.anchorId!),
94
+ })}
95
+ >
96
+ <div className={descriptionMaxWidth}>
97
+ <Text as="div">{item.description}</Text>
98
+ </div>
99
+ </AccordionComponent>
100
+ {index < items.length - 1 && (
101
+ <Divider key={`divider-${index}`} className="my-6 md:my-10" />
102
+ )}
103
+ </div>
104
+ );
105
+ })}
56
106
  </div>
57
107
  </div>
58
- </div>
108
+ </section>
59
109
  );
60
110
  };
61
111
 
@@ -1,11 +1,27 @@
1
1
  import React from "react";
2
2
 
3
+ export type AccordionItem = {
4
+ anchorId?: string;
5
+ title: string;
6
+ description: React.ReactNode;
7
+ };
8
+
3
9
  export type AccordionProps = {
10
+ /** Section-level anchor ID applied to the outer <section> element */
11
+ anchorId?: string;
4
12
  title: string;
5
13
  enableHeading?: boolean;
6
- background?: "blue" | "green" | "navy" | "purple" | "white" | "yellow";
7
- items: { title: string; description: React.ReactNode }[];
14
+ background?: ThemeKey;
15
+ items: AccordionItem[];
8
16
  maxWidth?: boolean;
17
+ /** Array of anchorIds that should be expanded on mount */
18
+ initialExpandedItems?: string[];
19
+ /** Enable URL hash auto-expand on mount */
20
+ hashAutoExpand?: boolean;
21
+ /** Max-width class for item descriptions (default: "max-w-[980px]") */
22
+ descriptionMaxWidth?: string;
23
+ /** Custom class for the accordion list wrapper */
24
+ itemContainerClassName?: string;
9
25
  };
10
26
 
11
27
  export type ThemeKey =
@@ -14,4 +30,5 @@ export type ThemeKey =
14
30
  | "yellow"
15
31
  | "purple"
16
32
  | "white"
17
- | "navy";
33
+ | "navy"
34
+ | "cream500";
@@ -27,7 +27,9 @@ export const CtaCallout: React.FC<CtaCalloutProps> = ({
27
27
  white: "bg-bg",
28
28
  };
29
29
  return (
30
- <div className={`${bgColorClasses[background]} component-container px-5 py-16 lg:px-13 lg:py-24`}>
30
+ <div
31
+ className={`${bgColorClasses[background]} component-container px-5 py-16 lg:px-13 lg:py-24`}
32
+ >
31
33
  <div
32
34
  className={`${maxWidth ? "mx-auto max-w-120" : ""} color-${color} flex flex-col ${color == "dark" ? "text-text" : "text-text-inverse"}`}
33
35
  >
@@ -45,7 +45,7 @@ export const Footer: React.FC<FooterProps> = ({
45
45
  <Button
46
46
  {...site}
47
47
  linkVariant="unstyled"
48
- linkClassName="text-white body3"
48
+ linkClassName="text-white body3 hover:underline underline-offset-4"
49
49
  onClick={footerClick}
50
50
  />
51
51
  </li>
@@ -60,7 +60,7 @@ export const Footer: React.FC<FooterProps> = ({
60
60
 
61
61
  <div className="py-8">
62
62
  <Divider className="my-8 hidden border-border-inverse md:my-8 md:block" />
63
-
63
+
64
64
  <p className="terms-text footnote text-white">
65
65
  &copy; {new Date().getFullYear()} {terms}
66
66
  </p>
@@ -74,7 +74,7 @@ export const Footer: React.FC<FooterProps> = ({
74
74
  >
75
75
  <Button
76
76
  {...link}
77
- linkClassName="footnote text-white"
77
+ linkClassName="footnote text-white hover:underline underline-offset-4"
78
78
  linkVariant="unstyled"
79
79
  onClick={footerClick}
80
80
  />
@@ -165,7 +165,7 @@ export const ImagePromoBar: React.FC<ImagePromoBarProps> = ({
165
165
  <aside className="flex w-full shrink-0 items-center justify-center lg:w-auto">
166
166
  {/* Media Section */}
167
167
  {image && (
168
- <div className="relative w-[334px] h-[334px] md:w-[486px] md:h-[486px] rounded-image overflow-hidden">
168
+ <div className="relative h-[334px] w-[334px] overflow-hidden rounded-image md:h-[486px] md:w-[486px]">
169
169
  <NextImage
170
170
  src={image}
171
171
  alt="section-image"
@@ -23,7 +23,7 @@ export type PrimaryHeroProps = {
23
23
  primaryCta1?: any;
24
24
  primaryCta2?: any;
25
25
  hideOnMobileCta1?: boolean;
26
- hideOnMobileCta2?: boolean;
26
+ hideOnMobileCta2?: boolean;
27
27
  secondaryCtaPrefix?: string;
28
28
  secondaryCta?: any;
29
29
  bottomLink?: any;