@windstream/react-shared-components 0.2.34 → 0.2.36

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.
@@ -0,0 +1,100 @@
1
+ "use client";
2
+
3
+ import { ReactNode } from "react";
4
+ import { OrderedListProps } from "./types";
5
+
6
+ import { Link } from "@shared/components/link";
7
+ import { Text } from "@shared/components/text";
8
+ import { DynamicTabs } from "@shared/contentful/blocks/dynamic-tabs";
9
+
10
+ export const OrderedList = ({
11
+ anchorId,
12
+ backgroundColor = "white",
13
+ title,
14
+ description,
15
+ tabs,
16
+ }: OrderedListProps) => {
17
+ const formatItemName = (name: string) =>
18
+ name
19
+ .split(" ")
20
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
21
+ .join(" ");
22
+
23
+ // Child rendering for a single list item (itemName / itemSlug). The tab
24
+ // section UI and the column wrapper for these nodes live in DynamicTabs.
25
+ const renderChild = (
26
+ item: OrderedListProps["tabs"][number]["items"]["tabContent"][number],
27
+ index: number
28
+ ): ReactNode => {
29
+ if (!item.itemSlug) {
30
+ return (
31
+ <Text
32
+ key={`ordered-item-${index}`}
33
+ className="body2 relative text-left leading-7"
34
+ >
35
+ {formatItemName(item.itemName)}
36
+ </Text>
37
+ );
38
+ }
39
+
40
+ return (
41
+ <Link
42
+ key={`ordered-item-${index}`}
43
+ href={item.itemSlug}
44
+ title={item.itemName.toUpperCase()}
45
+ className="flex items-center underline underline-offset-4"
46
+ >
47
+ <Text className="body2 relative cursor-pointer text-left leading-7">
48
+ {formatItemName(item.itemName)}
49
+ </Text>
50
+ </Link>
51
+ );
52
+ };
53
+
54
+ // Build the DynamicTabs `tabs` prop. Each tab's `tabContent` holds the list
55
+ // of React nodes; DynamicTabs arranges them into columns in ordered mode.
56
+ const dynamicTabs = {
57
+ items: tabs.map((tab, index) => ({
58
+ tabName: tab.items.tabName,
59
+ anchorId: `tab-${index}`,
60
+ tabContent: tab.items.tabContent.map(renderChild),
61
+ })),
62
+ };
63
+
64
+ return (
65
+ <section
66
+ className={`bg-secondary-${backgroundColor}`}
67
+ data-testid="non-fiber-city-list"
68
+ id={anchorId}
69
+ >
70
+ <div className="mx-auto w-full max-w-120 px-0 py-12 md:px-6 md:py-20 lg:px-3">
71
+ <div className="mb-11 px-4 md:px-0">
72
+ <Text as={"h2"} className="heading2 text-center md:heading1">
73
+ {title}
74
+ </Text>
75
+ <Text
76
+ as={"h3"}
77
+ className="subheading3 mt-2 text-center md:subheading1"
78
+ >
79
+ {description}
80
+ </Text>
81
+ </div>
82
+ <div className="section-body">
83
+ {dynamicTabs.items.length > 0 ? (
84
+ <div>
85
+ <DynamicTabs
86
+ dynamic={true}
87
+ isOrderedList={true}
88
+ tabs={dynamicTabs}
89
+ navigationType={false}
90
+ mobileSidebarTabType={false}
91
+ />
92
+ </div>
93
+ ) : null}
94
+ </div>
95
+ </div>
96
+ </section>
97
+ );
98
+ };
99
+
100
+ export default OrderedList;
@@ -0,0 +1,9 @@
1
+ import { ReactNode } from "react";
2
+
3
+ export interface OrderedListProps {
4
+ anchorId?: string;
5
+ backgroundColor?: "white" | "cream";
6
+ title: ReactNode;
7
+ description: ReactNode;
8
+ tabs: any[];
9
+ }
@@ -285,6 +285,27 @@ describe("PrimaryHero", () => {
285
285
  });
286
286
 
287
287
  describe("Pricing description disclaimer", () => {
288
+ it("renders pricingDescription with subheading and responsive alignment classes", () => {
289
+ render(
290
+ <PrimaryHero
291
+ {...baseProps}
292
+ pricingDescription="Building a new home? Contact us to see if you're eligible for Kinetic Internet."
293
+ />
294
+ );
295
+
296
+ const pricingText = screen.getByText(
297
+ "Building a new home? Contact us to see if you're eligible for Kinetic Internet."
298
+ );
299
+
300
+ expect(pricingText).toBeInTheDocument();
301
+ expect(pricingText).toHaveClass("subheading1");
302
+ expect(pricingText).toHaveClass(
303
+ "text-left",
304
+ "sm:text-center",
305
+ "xl:text-left"
306
+ );
307
+ });
308
+
288
309
  it("renders pricingDescriptionDisclaimer (desktop and mobile)", () => {
289
310
  render(
290
311
  <PrimaryHero
@@ -300,7 +321,6 @@ describe("PrimaryHero", () => {
300
321
  expect(screen.queryByText("Taxes apply")).not.toBeInTheDocument();
301
322
  });
302
323
  });
303
-
304
324
  describe("Images", () => {
305
325
  it("renders carousel image (mobile and desktop)", () => {
306
326
  render(
@@ -126,15 +126,19 @@ export const PrimaryHero: React.FC<PrimaryHeroProps> = props => {
126
126
 
127
127
  {pricingDescription ? (
128
128
  <Text
129
- data-cy="hero-pricing-disclaimer"
130
- className={cx("text-left sm:text-center xl:text-left")}
129
+ data-cy="hero-pricing-description"
130
+ className={cx("subheading1", "text-left sm:text-center xl:text-left")}
131
131
  >
132
132
  {pricingDescription}
133
133
  </Text>
134
134
  ) : null}
135
135
 
136
136
  {pricingDescriptionDisclaimer ? (
137
- <Text data-cy="hero-pricing-disclaimer" as="p" className="body3">
137
+ <Text
138
+ data-cy="hero-pricing-disclaimer"
139
+ as="p"
140
+ className={cx("body3", "text-left sm:text-center xl:text-left")}
141
+ >
138
142
  {pricingDescriptionDisclaimer}
139
143
  </Text>
140
144
  ) : null}
@@ -29,6 +29,8 @@ export type { NavigationProps } from "./blocks/navigation/types";
29
29
  export { PrimaryHero } from "./blocks/primary-hero";
30
30
  export type { PrimaryHeroProps } from "./blocks/primary-hero/types";
31
31
 
32
+ export { OrderedList } from "./blocks/ordered-list";
33
+ export type { OrderedListProps } from "./blocks/ordered-list/types";
32
34
  export { Text } from "./blocks/text";
33
35
  export type { TextProps } from "./blocks/text/types";
34
36