@windstream/react-shared-components 0.1.94 → 0.1.95
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/README.md +635 -635
- 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 +4 -4
- 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 +191 -191
- package/src/components/accordion/Accordion.stories.tsx +230 -230
- package/src/components/accordion/index.test.tsx +270 -270
- package/src/components/accordion/index.tsx +70 -70
- package/src/components/accordion/types.ts +12 -12
- package/src/components/alert-card/AlertCard.stories.tsx +171 -171
- package/src/components/alert-card/index.test.tsx +152 -152
- package/src/components/alert-card/index.tsx +41 -41
- package/src/components/alert-card/types.ts +13 -13
- package/src/components/animation-wrapper/index.test.tsx +424 -424
- package/src/components/animation-wrapper/index.tsx +129 -129
- package/src/components/animation-wrapper/types.ts +11 -11
- package/src/components/brand-button/BrandButton.stories.tsx +223 -223
- package/src/components/brand-button/helpers.ts +35 -35
- package/src/components/brand-button/index.test.tsx +292 -292
- package/src/components/brand-button/index.tsx +120 -120
- package/src/components/brand-button/types.ts +38 -38
- package/src/components/button/Button.stories.tsx +108 -108
- package/src/components/button/index.test.tsx +91 -91
- package/src/components/button/index.tsx +27 -27
- package/src/components/button/types.ts +14 -14
- package/src/components/call-button/CallButton.stories.tsx +324 -324
- package/src/components/call-button/index.test.tsx +260 -260
- package/src/components/call-button/index.tsx +106 -106
- package/src/components/call-button/types.ts +16 -16
- package/src/components/checkbox/Checkbox.stories.tsx +247 -247
- package/src/components/checkbox/index.test.tsx +252 -252
- package/src/components/checkbox/index.tsx +197 -197
- package/src/components/checkbox/types.ts +27 -27
- package/src/components/checklist/Checklist.stories.tsx +150 -150
- package/src/components/checklist/index.test.tsx +231 -231
- package/src/components/checklist/index.tsx +96 -96
- package/src/components/checklist/types.ts +23 -23
- package/src/components/collapse/Collapse.stories.tsx +255 -255
- package/src/components/collapse/index.test.tsx +277 -277
- package/src/components/collapse/index.tsx +47 -47
- package/src/components/collapse/types.ts +6 -6
- package/src/components/divider/Divider.stories.tsx +205 -205
- package/src/components/divider/index.test.tsx +53 -53
- package/src/components/divider/index.tsx +22 -22
- package/src/components/divider/type.ts +3 -3
- package/src/components/image/Image.stories.tsx +113 -113
- package/src/components/image/index.test.tsx +174 -174
- package/src/components/image/index.tsx +25 -25
- package/src/components/image/types.ts +40 -40
- package/src/components/input/Input.stories.tsx +325 -325
- package/src/components/input/index.test.tsx +348 -348
- package/src/components/input/index.tsx +177 -177
- package/src/components/input/types.ts +37 -37
- package/src/components/link/Link.stories.tsx +163 -163
- package/src/components/link/index.test.tsx +199 -199
- package/src/components/link/index.tsx +116 -116
- package/src/components/link/types.ts +25 -25
- package/src/components/list/List.stories.tsx +272 -272
- package/src/components/list/index.test.tsx +166 -166
- package/src/components/list/index.tsx +88 -88
- package/src/components/list/list-item/index.tsx +38 -38
- package/src/components/list/list-item/types.ts +13 -13
- package/src/components/list/types.ts +29 -29
- package/src/components/material-icon/MaterialIcon.stories.tsx +322 -322
- package/src/components/material-icon/constants.ts +99 -99
- package/src/components/material-icon/index.test.tsx +130 -130
- package/src/components/material-icon/index.tsx +47 -47
- package/src/components/material-icon/types.ts +31 -31
- package/src/components/modal/Modal.stories.tsx +171 -171
- package/src/components/modal/index.test.tsx +310 -310
- package/src/components/modal/index.tsx +164 -164
- package/src/components/modal/types.ts +24 -24
- package/src/components/next-image/index.test.tsx +406 -406
- package/src/components/next-image/index.tsx +74 -74
- package/src/components/next-image/types.ts +1 -1
- package/src/components/pagination/index.test.tsx +521 -521
- package/src/components/pagination/index.tsx +91 -91
- package/src/components/pagination/types.ts +6 -6
- package/src/components/radio-button/RadioButton.stories.tsx +307 -307
- package/src/components/radio-button/index.test.tsx +151 -151
- package/src/components/radio-button/index.tsx +75 -75
- package/src/components/radio-button/types.ts +21 -21
- package/src/components/see-more/SeeMore.stories.tsx +181 -181
- package/src/components/see-more/index.test.tsx +96 -96
- package/src/components/see-more/index.tsx +44 -44
- package/src/components/see-more/types.ts +4 -4
- package/src/components/select/Select.stories.tsx +411 -411
- package/src/components/select/index.test.tsx +256 -256
- package/src/components/select/index.tsx +155 -155
- package/src/components/select/types.ts +36 -36
- package/src/components/select-plan-button/SelectPlanButton.stories.tsx +184 -184
- package/src/components/select-plan-button/index.test.tsx +173 -173
- package/src/components/select-plan-button/index.tsx +63 -63
- package/src/components/select-plan-button/types.ts +17 -17
- package/src/components/skeleton/Skeleton.stories.tsx +179 -179
- package/src/components/skeleton/index.test.tsx +74 -74
- package/src/components/skeleton/index.tsx +61 -61
- package/src/components/skeleton/types.ts +4 -4
- package/src/components/spinner/Spinner.stories.tsx +335 -335
- package/src/components/spinner/index.test.tsx +76 -76
- package/src/components/spinner/index.tsx +44 -44
- package/src/components/spinner/types.ts +5 -5
- package/src/components/text/Text.stories.tsx +321 -321
- package/src/components/text/index.test.tsx +65 -65
- package/src/components/text/index.tsx +25 -25
- package/src/components/text/types.ts +45 -45
- package/src/components/tooltip/Tooltip.stories.tsx +219 -219
- package/src/components/tooltip/index.test.tsx +50 -50
- package/src/components/tooltip/index.tsx +74 -74
- package/src/components/tooltip/types.ts +7 -7
- package/src/components/view-cart-button/ViewCartButton.stories.tsx +252 -252
- package/src/components/view-cart-button/index.test.tsx +57 -57
- package/src/components/view-cart-button/index.tsx +42 -42
- package/src/components/view-cart-button/types.ts +5 -5
- package/src/contentful/blocks/accordion/Accordion.stories.mocks.tsx +128 -128
- package/src/contentful/blocks/accordion/Accordion.stories.tsx +98 -98
- package/src/contentful/blocks/accordion/index.test.tsx +218 -218
- package/src/contentful/blocks/accordion/index.tsx +114 -114
- package/src/contentful/blocks/accordion/types.ts +34 -34
- package/src/contentful/blocks/address-input-banner/index.test.tsx +132 -132
- package/src/contentful/blocks/address-input-banner/index.tsx +52 -52
- package/src/contentful/blocks/address-input-banner/types.ts +14 -14
- package/src/contentful/blocks/anchored-bottom-banner/index.test.tsx +287 -287
- package/src/contentful/blocks/anchored-bottom-banner/index.tsx +181 -181
- package/src/contentful/blocks/anchored-bottom-banner/types.ts +13 -13
- package/src/contentful/blocks/blogs-grid/BlogGrid.stories.mocks.tsx +144 -144
- package/src/contentful/blocks/blogs-grid/BlogGrid.stories.tsx +157 -157
- package/src/contentful/blocks/blogs-grid/index.test.tsx +355 -355
- package/src/contentful/blocks/blogs-grid/index.tsx +134 -134
- package/src/contentful/blocks/blogs-grid/types.ts +26 -26
- package/src/contentful/blocks/blogs-grid-base/index.test.tsx +274 -274
- package/src/contentful/blocks/blogs-grid-base/index.tsx +119 -119
- package/src/contentful/blocks/blogs-grid-base/types.ts +36 -36
- package/src/contentful/blocks/breadcrumbs/BreadcrumbNavigation.stories.tsx +147 -147
- package/src/contentful/blocks/breadcrumbs/index.test.tsx +281 -281
- package/src/contentful/blocks/breadcrumbs/index.tsx +95 -95
- package/src/contentful/blocks/breadcrumbs/types.ts +8 -8
- package/src/contentful/blocks/button/Button.stories.tsx +40 -40
- package/src/contentful/blocks/button/index.test.tsx +339 -339
- package/src/contentful/blocks/button/index.tsx +131 -131
- package/src/contentful/blocks/button/types.ts +39 -39
- package/src/contentful/blocks/callout/Callout.stories.tsx +23 -23
- package/src/contentful/blocks/callout/index.test.tsx +539 -539
- package/src/contentful/blocks/callout/index.tsx +277 -277
- package/src/contentful/blocks/callout/types.ts +78 -78
- package/src/contentful/blocks/cards/Cards.stories.tsx +23 -23
- package/src/contentful/blocks/cards/blog-card/index.test.tsx +218 -218
- package/src/contentful/blocks/cards/blog-card/index.tsx +129 -129
- package/src/contentful/blocks/cards/blog-card/types.ts +34 -34
- package/src/contentful/blocks/cards/floating-image-card/index.test.tsx +201 -201
- package/src/contentful/blocks/cards/floating-image-card/index.tsx +119 -119
- package/src/contentful/blocks/cards/floating-image-card/types.ts +30 -30
- package/src/contentful/blocks/cards/full-image-card/index.test.tsx +216 -216
- package/src/contentful/blocks/cards/full-image-card/index.tsx +130 -130
- package/src/contentful/blocks/cards/full-image-card/types.ts +29 -29
- package/src/contentful/blocks/cards/index.test.tsx +39 -39
- package/src/contentful/blocks/cards/index.tsx +13 -13
- package/src/contentful/blocks/cards/product-card/index.test.tsx +263 -263
- package/src/contentful/blocks/cards/product-card/index.tsx +251 -251
- package/src/contentful/blocks/cards/product-card/types.ts +28 -28
- package/src/contentful/blocks/cards/simple-card/index.test.tsx +364 -364
- package/src/contentful/blocks/cards/simple-card/index.tsx +325 -325
- package/src/contentful/blocks/cards/simple-card/types.ts +71 -71
- package/src/contentful/blocks/cards/testimonial-card/index.test.tsx +180 -180
- package/src/contentful/blocks/cards/testimonial-card/index.tsx +90 -90
- package/src/contentful/blocks/cards/testimonial-card/types.tsx +12 -12
- package/src/contentful/blocks/cards/types.ts +1 -1
- package/src/contentful/blocks/carousel/Carousel.stories.tsx +23 -23
- package/src/contentful/blocks/carousel/helper.test.tsx +539 -539
- package/src/contentful/blocks/carousel/helper.tsx +494 -494
- package/src/contentful/blocks/carousel/index.test.tsx +308 -308
- package/src/contentful/blocks/carousel/index.tsx +87 -87
- package/src/contentful/blocks/carousel/types.test.ts +16 -16
- package/src/contentful/blocks/carousel/types.ts +145 -145
- package/src/contentful/blocks/cart-retention-banner/index.test.tsx +409 -409
- package/src/contentful/blocks/cart-retention-banner/index.tsx +109 -109
- package/src/contentful/blocks/cart-retention-banner/types.ts +11 -11
- package/src/contentful/blocks/comparison-table/index.test.tsx +114 -114
- package/src/contentful/blocks/comparison-table/index.tsx +29 -29
- package/src/contentful/blocks/comparison-table/types.ts +6 -6
- package/src/contentful/blocks/cookiebanner/index.test.tsx +277 -277
- package/src/contentful/blocks/cookiebanner/index.tsx +146 -146
- package/src/contentful/blocks/cookiebanner/type.ts +7 -7
- package/src/contentful/blocks/cta-callout/CtaCallout.stories.tsx +46 -46
- package/src/contentful/blocks/cta-callout/index.test.tsx +244 -244
- package/src/contentful/blocks/cta-callout/index.tsx +73 -73
- package/src/contentful/blocks/cta-callout/types.ts +26 -26
- package/src/contentful/blocks/dynamic-tabs/index.test.tsx +240 -240
- package/src/contentful/blocks/dynamic-tabs/index.tsx +204 -204
- package/src/contentful/blocks/dynamic-tabs/types.ts +21 -21
- package/src/contentful/blocks/email-input-block/index.test.tsx +213 -213
- package/src/contentful/blocks/email-input-block/index.tsx +121 -121
- package/src/contentful/blocks/email-input-block/types.ts +16 -16
- package/src/contentful/blocks/find-kinetic/FindKinetic.stories.tsx +23 -23
- package/src/contentful/blocks/find-kinetic/index.test.tsx +269 -269
- package/src/contentful/blocks/find-kinetic/index.tsx +138 -138
- package/src/contentful/blocks/find-kinetic/types.ts +20 -20
- package/src/contentful/blocks/floating-banner/FloatingBanner.stories.tsx +34 -34
- package/src/contentful/blocks/floating-banner/index.test.tsx +246 -246
- package/src/contentful/blocks/floating-banner/index.tsx +97 -97
- package/src/contentful/blocks/floating-banner/types.ts +22 -22
- package/src/contentful/blocks/footer/Footer.stories.tsx +317 -317
- package/src/contentful/blocks/footer/index.test.tsx +302 -302
- package/src/contentful/blocks/footer/index.tsx +91 -91
- package/src/contentful/blocks/footer/types.ts +13 -13
- package/src/contentful/blocks/image-promo-bar/ImagePromoBar.stories.tsx +23 -23
- package/src/contentful/blocks/image-promo-bar/helper.test.tsx +61 -61
- package/src/contentful/blocks/image-promo-bar/helper.tsx +28 -28
- package/src/contentful/blocks/image-promo-bar/index.test.tsx +467 -467
- package/src/contentful/blocks/image-promo-bar/index.tsx +8 -6
- package/src/contentful/blocks/image-promo-bar/types.ts +44 -44
- package/src/contentful/blocks/image-promo-bar/vimeo-embed.test.tsx +142 -142
- package/src/contentful/blocks/image-promo-bar/vimeo-embed.tsx +93 -93
- package/src/contentful/blocks/image-promo-bar/youtube-embed.test.tsx +104 -104
- package/src/contentful/blocks/image-promo-bar/youtube-embed.tsx +46 -46
- package/src/contentful/blocks/modal/constants.ts +53 -53
- package/src/contentful/blocks/modal/index.test.tsx +209 -209
- package/src/contentful/blocks/modal/index.tsx +108 -108
- package/src/contentful/blocks/modal/types.ts +12 -12
- package/src/contentful/blocks/navigation/Navigation.stories.mocks.tsx +78 -78
- package/src/contentful/blocks/navigation/Navigation.stories.tsx +138 -138
- package/src/contentful/blocks/navigation/desktop-link-groups.tsx/index.test.tsx +208 -208
- package/src/contentful/blocks/navigation/desktop-link-groups.tsx/index.tsx +141 -141
- package/src/contentful/blocks/navigation/index.test.tsx +924 -924
- package/src/contentful/blocks/navigation/index.tsx +569 -569
- package/src/contentful/blocks/navigation/mobile-link-groups.tsx/index.test.tsx +131 -131
- package/src/contentful/blocks/navigation/mobile-link-groups.tsx/index.tsx +82 -82
- package/src/contentful/blocks/navigation/types.ts +71 -71
- package/src/contentful/blocks/primary-hero/PrimaryHero.stories.tsx +23 -23
- package/src/contentful/blocks/primary-hero/index.test.tsx +286 -286
- package/src/contentful/blocks/primary-hero/index.tsx +239 -239
- package/src/contentful/blocks/primary-hero/types.ts +37 -37
- package/src/contentful/blocks/search-block/index.test.tsx +268 -268
- package/src/contentful/blocks/search-block/index.tsx +90 -90
- package/src/contentful/blocks/search-block/types.ts +15 -15
- package/src/contentful/blocks/shape-background-wrapper/ShapeBackgroundWrapper.stories.tsx +26 -26
- package/src/contentful/blocks/shape-background-wrapper/index.test.tsx +284 -284
- package/src/contentful/blocks/shape-background-wrapper/index.tsx +124 -124
- package/src/contentful/blocks/shape-background-wrapper/types.ts +36 -36
- package/src/contentful/blocks/text/Text.stories.tsx +23 -23
- package/src/contentful/blocks/text/index.test.tsx +36 -36
- package/src/contentful/blocks/text/index.tsx +12 -12
- package/src/contentful/blocks/text/types.ts +1 -1
- package/src/contentful/index.test.ts +45 -45
- package/src/contentful/index.ts +105 -105
- package/src/global-mocks/contentful/to-document.ts +25 -25
- package/src/global-mocks/cookie.ts +48 -48
- package/src/global-mocks/cx.ts +37 -37
- package/src/global-mocks/index.ts +89 -89
- package/src/global-mocks/speed-card-bg.ts +27 -27
- package/src/global-mocks/utm.ts +49 -49
- package/src/hooks/contentful/use-contentful-rich-text.test.tsx +1758 -1758
- package/src/hooks/contentful/use-contentful-rich-text.tsx +309 -309
- package/src/hooks/contentful/use-processed-check-list.test.tsx +277 -277
- package/src/hooks/contentful/use-processed-check-list.ts +63 -63
- package/src/hooks/use-body-scroll-lock.test.ts +134 -134
- package/src/hooks/use-body-scroll-lock.ts +34 -34
- package/src/hooks/use-carousel-swipe.test.ts +393 -393
- package/src/hooks/use-carousel-swipe.ts +264 -264
- package/src/hooks/use-outside-click.test.ts +142 -142
- package/src/hooks/use-outside-click.ts +17 -17
- package/src/index.ts +107 -107
- package/src/next/index.test.ts +7 -7
- package/src/next/index.ts +5 -5
- package/src/setupTests.ts +52 -52
- package/src/stories/DocsTemplate.tsx +24 -24
- package/src/styles/globals.css +343 -343
- package/src/types/global.d.ts +9 -9
- package/src/types/micro-components.ts +99 -99
- package/src/types/utm.ts +49 -49
- package/src/utils/contentful/to-document.test.ts +85 -85
- package/src/utils/contentful/to-document.ts +24 -24
- package/src/utils/cookie.test.ts +180 -180
- package/src/utils/cookie.ts +84 -84
- package/src/utils/cx.test.ts +90 -90
- package/src/utils/cx.ts +49 -49
- package/src/utils/index.test.ts +115 -115
- package/src/utils/index.ts +41 -41
- package/src/utils/speed-card-bg.test.ts +46 -46
- package/src/utils/speed-card-bg.ts +24 -24
- package/src/utils/utm.test.ts +359 -359
- package/src/utils/utm.ts +221 -221
|
@@ -1,218 +1,218 @@
|
|
|
1
|
-
import Accordion from "./index";
|
|
2
|
-
import { AccordionItem } from "./types";
|
|
3
|
-
|
|
4
|
-
import { fireEvent, render, screen } from "@testing-library/react";
|
|
5
|
-
|
|
6
|
-
const items: AccordionItem[] = [
|
|
7
|
-
{ anchorId: "item-1", title: "First Question", description: "Answer one" },
|
|
8
|
-
{ anchorId: "item-2", title: "Second Question", description: "Answer two" },
|
|
9
|
-
{ anchorId: "item-3", title: "Third Question", description: "Answer three" },
|
|
10
|
-
];
|
|
11
|
-
|
|
12
|
-
describe("Contentful Accordion", () => {
|
|
13
|
-
beforeEach(() => {
|
|
14
|
-
Object.defineProperty(window, "location", {
|
|
15
|
-
writable: true,
|
|
16
|
-
value: { hash: "" },
|
|
17
|
-
});
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it("renders the title as h2 by default", () => {
|
|
21
|
-
render(<Accordion items={items} title="FAQ" />);
|
|
22
|
-
const heading = screen.getByText("FAQ");
|
|
23
|
-
expect(heading.tagName).toBe("H2");
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it("renders the title as h1 when enableHeading is true", () => {
|
|
27
|
-
render(<Accordion items={items} title="FAQ" enableHeading={true} />);
|
|
28
|
-
const heading = screen.getByText("FAQ");
|
|
29
|
-
expect(heading.tagName).toBe("H1");
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it("renders all accordion item titles", () => {
|
|
33
|
-
render(<Accordion items={items} title="FAQ" />);
|
|
34
|
-
expect(screen.getByText("First Question")).toBeInTheDocument();
|
|
35
|
-
expect(screen.getByText("Second Question")).toBeInTheDocument();
|
|
36
|
-
expect(screen.getByText("Third Question")).toBeInTheDocument();
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it("renders item descriptions", () => {
|
|
40
|
-
render(<Accordion items={items} title="FAQ" />);
|
|
41
|
-
expect(screen.getByText("Answer one")).toBeInTheDocument();
|
|
42
|
-
expect(screen.getByText("Answer two")).toBeInTheDocument();
|
|
43
|
-
expect(screen.getByText("Answer three")).toBeInTheDocument();
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it("applies anchorId to the section", () => {
|
|
47
|
-
const { container } = render(
|
|
48
|
-
<Accordion items={items} title="FAQ" anchorId="faq-section" />
|
|
49
|
-
);
|
|
50
|
-
expect(container.querySelector("#faq-section")).toBeInTheDocument();
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it("applies white background by default", () => {
|
|
54
|
-
const { container } = render(<Accordion items={items} title="FAQ" />);
|
|
55
|
-
expect(container.querySelector(".bg-white")).toBeInTheDocument();
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it("applies navy background", () => {
|
|
59
|
-
const { container } = render(
|
|
60
|
-
<Accordion items={items} title="FAQ" background="navy" />
|
|
61
|
-
);
|
|
62
|
-
expect(
|
|
63
|
-
container.querySelector('section[class*="bg-[#00002D]"]')
|
|
64
|
-
).toBeInTheDocument();
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it("applies blue background", () => {
|
|
68
|
-
const { container } = render(
|
|
69
|
-
<Accordion items={items} title="FAQ" background="blue" />
|
|
70
|
-
);
|
|
71
|
-
expect(
|
|
72
|
-
container.querySelector('section[class*="bg-[#07B2E2]"]')
|
|
73
|
-
).toBeInTheDocument();
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it("applies green background", () => {
|
|
77
|
-
const { container } = render(
|
|
78
|
-
<Accordion items={items} title="FAQ" background="green" />
|
|
79
|
-
);
|
|
80
|
-
expect(
|
|
81
|
-
container.querySelector('section[class*="bg-[#26B170]"]')
|
|
82
|
-
).toBeInTheDocument();
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it("applies yellow background", () => {
|
|
86
|
-
const { container } = render(
|
|
87
|
-
<Accordion items={items} title="FAQ" background="yellow" />
|
|
88
|
-
);
|
|
89
|
-
expect(
|
|
90
|
-
container.querySelector('section[class*="bg-[#F5FF1E]"]')
|
|
91
|
-
).toBeInTheDocument();
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
it("applies purple background", () => {
|
|
95
|
-
const { container } = render(
|
|
96
|
-
<Accordion items={items} title="FAQ" background="purple" />
|
|
97
|
-
);
|
|
98
|
-
expect(
|
|
99
|
-
container.querySelector('section[class*="bg-[#931D69]"]')
|
|
100
|
-
).toBeInTheDocument();
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
it("applies cream500 background", () => {
|
|
104
|
-
const { container } = render(
|
|
105
|
-
<Accordion items={items} title="FAQ" background="cream500" />
|
|
106
|
-
);
|
|
107
|
-
expect(
|
|
108
|
-
container.querySelector('section[class*="bg-[#FFFEEF]"]')
|
|
109
|
-
).toBeInTheDocument();
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
it("applies maxWidth class by default", () => {
|
|
113
|
-
const { container } = render(<Accordion items={items} title="FAQ" />);
|
|
114
|
-
expect(container.querySelector(".max-w-120")).toBeInTheDocument();
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
it("does not apply maxWidth class when maxWidth is false", () => {
|
|
118
|
-
const { container } = render(
|
|
119
|
-
<Accordion items={items} title="FAQ" maxWidth={false} />
|
|
120
|
-
);
|
|
121
|
-
expect(container.querySelector(".max-w-120")).not.toBeInTheDocument();
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
it("renders dividers between items but not after the last", () => {
|
|
125
|
-
const { container } = render(<Accordion items={items} title="FAQ" />);
|
|
126
|
-
const dividers = container.querySelectorAll(
|
|
127
|
-
".bg-bg-surface-tertiary-active"
|
|
128
|
-
);
|
|
129
|
-
expect(dividers).toHaveLength(items.length - 1);
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
it("expands items in initialExpandedItems", () => {
|
|
133
|
-
render(
|
|
134
|
-
<Accordion items={items} title="FAQ" initialExpandedItems={["item-1"]} />
|
|
135
|
-
);
|
|
136
|
-
const arrowsUp = screen.getAllByText("keyboard_arrow_up");
|
|
137
|
-
expect(arrowsUp.length).toBeGreaterThanOrEqual(1);
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it("auto-expands item matching URL hash when hashAutoExpand is true", () => {
|
|
141
|
-
Object.defineProperty(window, "location", {
|
|
142
|
-
writable: true,
|
|
143
|
-
value: { hash: "#item-2" },
|
|
144
|
-
});
|
|
145
|
-
render(<Accordion items={items} title="FAQ" hashAutoExpand={true} />);
|
|
146
|
-
expect(document.getElementById("item-2")).toBeInTheDocument();
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
it("does not auto-expand when hashAutoExpand is false", () => {
|
|
150
|
-
Object.defineProperty(window, "location", {
|
|
151
|
-
writable: true,
|
|
152
|
-
value: { hash: "#item-2" },
|
|
153
|
-
});
|
|
154
|
-
render(<Accordion items={items} title="FAQ" hashAutoExpand={false} />);
|
|
155
|
-
const arrowsDown = screen.getAllByText("keyboard_arrow_down");
|
|
156
|
-
expect(arrowsDown.length).toBe(items.length);
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
it("does not duplicate item in expandedItems if already present", () => {
|
|
160
|
-
Object.defineProperty(window, "location", {
|
|
161
|
-
writable: true,
|
|
162
|
-
value: { hash: "#item-1" },
|
|
163
|
-
});
|
|
164
|
-
render(
|
|
165
|
-
<Accordion
|
|
166
|
-
items={items}
|
|
167
|
-
title="FAQ"
|
|
168
|
-
hashAutoExpand={true}
|
|
169
|
-
initialExpandedItems={["item-1"]}
|
|
170
|
-
/>
|
|
171
|
-
);
|
|
172
|
-
expect(document.getElementById("item-1")).toBeInTheDocument();
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
it("applies itemContainerClassName", () => {
|
|
176
|
-
const { container } = render(
|
|
177
|
-
<Accordion items={items} title="FAQ" itemContainerClassName="gap-4" />
|
|
178
|
-
);
|
|
179
|
-
expect(container.querySelector(".gap-4")).toBeInTheDocument();
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
it("applies descriptionMaxWidth class", () => {
|
|
183
|
-
const { container } = render(
|
|
184
|
-
<Accordion
|
|
185
|
-
items={items}
|
|
186
|
-
title="FAQ"
|
|
187
|
-
descriptionMaxWidth="max-w-[500px]"
|
|
188
|
-
/>
|
|
189
|
-
);
|
|
190
|
-
expect(container.querySelector(".max-w-\\[500px\\]")).toBeInTheDocument();
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
it("sets id on items with anchorId", () => {
|
|
194
|
-
render(<Accordion items={items} title="FAQ" />);
|
|
195
|
-
expect(document.getElementById("item-1")).toBeInTheDocument();
|
|
196
|
-
expect(document.getElementById("item-2")).toBeInTheDocument();
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
it("handles items without anchorId using index as key", () => {
|
|
200
|
-
const noAnchorItems: AccordionItem[] = [
|
|
201
|
-
{ title: "Q1", description: "A1" },
|
|
202
|
-
{ title: "Q2", description: "A2" },
|
|
203
|
-
];
|
|
204
|
-
render(<Accordion items={noAnchorItems} title="FAQ" />);
|
|
205
|
-
expect(screen.getByText("Q1")).toBeInTheDocument();
|
|
206
|
-
expect(screen.getByText("Q2")).toBeInTheDocument();
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
it("toggles expanded state when an accordion item button is clicked", () => {
|
|
210
|
-
render(
|
|
211
|
-
<Accordion items={items} title="FAQ" initialExpandedItems={["item-1"]} />
|
|
212
|
-
);
|
|
213
|
-
const buttons = screen.getAllByRole("button");
|
|
214
|
-
fireEvent.click(buttons[0]);
|
|
215
|
-
fireEvent.click(buttons[0]);
|
|
216
|
-
expect(screen.getByText("First Question")).toBeInTheDocument();
|
|
217
|
-
});
|
|
218
|
-
});
|
|
1
|
+
import Accordion from "./index";
|
|
2
|
+
import { AccordionItem } from "./types";
|
|
3
|
+
|
|
4
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
5
|
+
|
|
6
|
+
const items: AccordionItem[] = [
|
|
7
|
+
{ anchorId: "item-1", title: "First Question", description: "Answer one" },
|
|
8
|
+
{ anchorId: "item-2", title: "Second Question", description: "Answer two" },
|
|
9
|
+
{ anchorId: "item-3", title: "Third Question", description: "Answer three" },
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
describe("Contentful Accordion", () => {
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
Object.defineProperty(window, "location", {
|
|
15
|
+
writable: true,
|
|
16
|
+
value: { hash: "" },
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("renders the title as h2 by default", () => {
|
|
21
|
+
render(<Accordion items={items} title="FAQ" />);
|
|
22
|
+
const heading = screen.getByText("FAQ");
|
|
23
|
+
expect(heading.tagName).toBe("H2");
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("renders the title as h1 when enableHeading is true", () => {
|
|
27
|
+
render(<Accordion items={items} title="FAQ" enableHeading={true} />);
|
|
28
|
+
const heading = screen.getByText("FAQ");
|
|
29
|
+
expect(heading.tagName).toBe("H1");
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("renders all accordion item titles", () => {
|
|
33
|
+
render(<Accordion items={items} title="FAQ" />);
|
|
34
|
+
expect(screen.getByText("First Question")).toBeInTheDocument();
|
|
35
|
+
expect(screen.getByText("Second Question")).toBeInTheDocument();
|
|
36
|
+
expect(screen.getByText("Third Question")).toBeInTheDocument();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("renders item descriptions", () => {
|
|
40
|
+
render(<Accordion items={items} title="FAQ" />);
|
|
41
|
+
expect(screen.getByText("Answer one")).toBeInTheDocument();
|
|
42
|
+
expect(screen.getByText("Answer two")).toBeInTheDocument();
|
|
43
|
+
expect(screen.getByText("Answer three")).toBeInTheDocument();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("applies anchorId to the section", () => {
|
|
47
|
+
const { container } = render(
|
|
48
|
+
<Accordion items={items} title="FAQ" anchorId="faq-section" />
|
|
49
|
+
);
|
|
50
|
+
expect(container.querySelector("#faq-section")).toBeInTheDocument();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("applies white background by default", () => {
|
|
54
|
+
const { container } = render(<Accordion items={items} title="FAQ" />);
|
|
55
|
+
expect(container.querySelector(".bg-white")).toBeInTheDocument();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("applies navy background", () => {
|
|
59
|
+
const { container } = render(
|
|
60
|
+
<Accordion items={items} title="FAQ" background="navy" />
|
|
61
|
+
);
|
|
62
|
+
expect(
|
|
63
|
+
container.querySelector('section[class*="bg-[#00002D]"]')
|
|
64
|
+
).toBeInTheDocument();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("applies blue background", () => {
|
|
68
|
+
const { container } = render(
|
|
69
|
+
<Accordion items={items} title="FAQ" background="blue" />
|
|
70
|
+
);
|
|
71
|
+
expect(
|
|
72
|
+
container.querySelector('section[class*="bg-[#07B2E2]"]')
|
|
73
|
+
).toBeInTheDocument();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("applies green background", () => {
|
|
77
|
+
const { container } = render(
|
|
78
|
+
<Accordion items={items} title="FAQ" background="green" />
|
|
79
|
+
);
|
|
80
|
+
expect(
|
|
81
|
+
container.querySelector('section[class*="bg-[#26B170]"]')
|
|
82
|
+
).toBeInTheDocument();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("applies yellow background", () => {
|
|
86
|
+
const { container } = render(
|
|
87
|
+
<Accordion items={items} title="FAQ" background="yellow" />
|
|
88
|
+
);
|
|
89
|
+
expect(
|
|
90
|
+
container.querySelector('section[class*="bg-[#F5FF1E]"]')
|
|
91
|
+
).toBeInTheDocument();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("applies purple background", () => {
|
|
95
|
+
const { container } = render(
|
|
96
|
+
<Accordion items={items} title="FAQ" background="purple" />
|
|
97
|
+
);
|
|
98
|
+
expect(
|
|
99
|
+
container.querySelector('section[class*="bg-[#931D69]"]')
|
|
100
|
+
).toBeInTheDocument();
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("applies cream500 background", () => {
|
|
104
|
+
const { container } = render(
|
|
105
|
+
<Accordion items={items} title="FAQ" background="cream500" />
|
|
106
|
+
);
|
|
107
|
+
expect(
|
|
108
|
+
container.querySelector('section[class*="bg-[#FFFEEF]"]')
|
|
109
|
+
).toBeInTheDocument();
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("applies maxWidth class by default", () => {
|
|
113
|
+
const { container } = render(<Accordion items={items} title="FAQ" />);
|
|
114
|
+
expect(container.querySelector(".max-w-120")).toBeInTheDocument();
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("does not apply maxWidth class when maxWidth is false", () => {
|
|
118
|
+
const { container } = render(
|
|
119
|
+
<Accordion items={items} title="FAQ" maxWidth={false} />
|
|
120
|
+
);
|
|
121
|
+
expect(container.querySelector(".max-w-120")).not.toBeInTheDocument();
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("renders dividers between items but not after the last", () => {
|
|
125
|
+
const { container } = render(<Accordion items={items} title="FAQ" />);
|
|
126
|
+
const dividers = container.querySelectorAll(
|
|
127
|
+
".bg-bg-surface-tertiary-active"
|
|
128
|
+
);
|
|
129
|
+
expect(dividers).toHaveLength(items.length - 1);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("expands items in initialExpandedItems", () => {
|
|
133
|
+
render(
|
|
134
|
+
<Accordion items={items} title="FAQ" initialExpandedItems={["item-1"]} />
|
|
135
|
+
);
|
|
136
|
+
const arrowsUp = screen.getAllByText("keyboard_arrow_up");
|
|
137
|
+
expect(arrowsUp.length).toBeGreaterThanOrEqual(1);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it("auto-expands item matching URL hash when hashAutoExpand is true", () => {
|
|
141
|
+
Object.defineProperty(window, "location", {
|
|
142
|
+
writable: true,
|
|
143
|
+
value: { hash: "#item-2" },
|
|
144
|
+
});
|
|
145
|
+
render(<Accordion items={items} title="FAQ" hashAutoExpand={true} />);
|
|
146
|
+
expect(document.getElementById("item-2")).toBeInTheDocument();
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it("does not auto-expand when hashAutoExpand is false", () => {
|
|
150
|
+
Object.defineProperty(window, "location", {
|
|
151
|
+
writable: true,
|
|
152
|
+
value: { hash: "#item-2" },
|
|
153
|
+
});
|
|
154
|
+
render(<Accordion items={items} title="FAQ" hashAutoExpand={false} />);
|
|
155
|
+
const arrowsDown = screen.getAllByText("keyboard_arrow_down");
|
|
156
|
+
expect(arrowsDown.length).toBe(items.length);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it("does not duplicate item in expandedItems if already present", () => {
|
|
160
|
+
Object.defineProperty(window, "location", {
|
|
161
|
+
writable: true,
|
|
162
|
+
value: { hash: "#item-1" },
|
|
163
|
+
});
|
|
164
|
+
render(
|
|
165
|
+
<Accordion
|
|
166
|
+
items={items}
|
|
167
|
+
title="FAQ"
|
|
168
|
+
hashAutoExpand={true}
|
|
169
|
+
initialExpandedItems={["item-1"]}
|
|
170
|
+
/>
|
|
171
|
+
);
|
|
172
|
+
expect(document.getElementById("item-1")).toBeInTheDocument();
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it("applies itemContainerClassName", () => {
|
|
176
|
+
const { container } = render(
|
|
177
|
+
<Accordion items={items} title="FAQ" itemContainerClassName="gap-4" />
|
|
178
|
+
);
|
|
179
|
+
expect(container.querySelector(".gap-4")).toBeInTheDocument();
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it("applies descriptionMaxWidth class", () => {
|
|
183
|
+
const { container } = render(
|
|
184
|
+
<Accordion
|
|
185
|
+
items={items}
|
|
186
|
+
title="FAQ"
|
|
187
|
+
descriptionMaxWidth="max-w-[500px]"
|
|
188
|
+
/>
|
|
189
|
+
);
|
|
190
|
+
expect(container.querySelector(".max-w-\\[500px\\]")).toBeInTheDocument();
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it("sets id on items with anchorId", () => {
|
|
194
|
+
render(<Accordion items={items} title="FAQ" />);
|
|
195
|
+
expect(document.getElementById("item-1")).toBeInTheDocument();
|
|
196
|
+
expect(document.getElementById("item-2")).toBeInTheDocument();
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it("handles items without anchorId using index as key", () => {
|
|
200
|
+
const noAnchorItems: AccordionItem[] = [
|
|
201
|
+
{ title: "Q1", description: "A1" },
|
|
202
|
+
{ title: "Q2", description: "A2" },
|
|
203
|
+
];
|
|
204
|
+
render(<Accordion items={noAnchorItems} title="FAQ" />);
|
|
205
|
+
expect(screen.getByText("Q1")).toBeInTheDocument();
|
|
206
|
+
expect(screen.getByText("Q2")).toBeInTheDocument();
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it("toggles expanded state when an accordion item button is clicked", () => {
|
|
210
|
+
render(
|
|
211
|
+
<Accordion items={items} title="FAQ" initialExpandedItems={["item-1"]} />
|
|
212
|
+
);
|
|
213
|
+
const buttons = screen.getAllByRole("button");
|
|
214
|
+
fireEvent.click(buttons[0]);
|
|
215
|
+
fireEvent.click(buttons[0]);
|
|
216
|
+
expect(screen.getByText("First Question")).toBeInTheDocument();
|
|
217
|
+
});
|
|
218
|
+
});
|
|
@@ -1,114 +1,114 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import React, { useEffect, useState } from "react";
|
|
4
|
-
import { AccordionItem, AccordionProps, ThemeKey } from "./types";
|
|
5
|
-
|
|
6
|
-
import { Accordion as AccordionComponent } from "@shared/components/accordion";
|
|
7
|
-
import { Divider } from "@shared/components/divider";
|
|
8
|
-
import { Text } from "@shared/components/text";
|
|
9
|
-
|
|
10
|
-
export const Accordion: React.FC<AccordionProps> = ({
|
|
11
|
-
items,
|
|
12
|
-
title,
|
|
13
|
-
anchorId,
|
|
14
|
-
background = "white",
|
|
15
|
-
enableHeading = false,
|
|
16
|
-
maxWidth = true,
|
|
17
|
-
initialExpandedItems: initialExpandedItemsProp = [],
|
|
18
|
-
hashAutoExpand = false,
|
|
19
|
-
descriptionMaxWidth = "max-w-[980px]",
|
|
20
|
-
itemContainerClassName,
|
|
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
|
-
/* istanbul ignore next -- passed to AccordionComponent which does not forward onClick */
|
|
40
|
-
const handleToggle = (itemAnchorId: string) => {
|
|
41
|
-
setExpandedItems(prev =>
|
|
42
|
-
prev.includes(itemAnchorId)
|
|
43
|
-
? prev.filter(id => id !== itemAnchorId)
|
|
44
|
-
: [...prev, itemAnchorId]
|
|
45
|
-
);
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
const bgColorClasses: Record<ThemeKey, string> = {
|
|
49
|
-
blue: "bg-[#07B2E2]",
|
|
50
|
-
green: "bg-[#26B170]",
|
|
51
|
-
yellow: "bg-[#F5FF1E]",
|
|
52
|
-
purple: "bg-[#931D69]",
|
|
53
|
-
white: "bg-white",
|
|
54
|
-
navy: "bg-[#00002D]",
|
|
55
|
-
cream500: "bg-[#FFFEEF]",
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
return (
|
|
59
|
-
<section
|
|
60
|
-
id={anchorId}
|
|
61
|
-
className={`${bgColorClasses[background]} flex flex-col px-5 pb-20 pt-4 md:px-10`}
|
|
62
|
-
>
|
|
63
|
-
<div className={`${maxWidth ? "max-w-120 xl:mx-auto" : ""}`}>
|
|
64
|
-
<Text
|
|
65
|
-
as={enableHeading ? "h1" : "h2"}
|
|
66
|
-
className="heading2 mb-10 pt-12 text-left text-text md:heading1 lg:text-center"
|
|
67
|
-
>
|
|
68
|
-
{title}
|
|
69
|
-
</Text>
|
|
70
|
-
<div className={`pt-6 md:pt-10 ${itemContainerClassName ?? ""}`}>
|
|
71
|
-
{items?.map((item: AccordionItem, index: number) => {
|
|
72
|
-
const itemKey = item.anchorId || `item-${index}`;
|
|
73
|
-
const isOpen = item.anchorId
|
|
74
|
-
? expandedItems.includes(item.anchorId)
|
|
75
|
-
: undefined;
|
|
76
|
-
|
|
77
|
-
return (
|
|
78
|
-
<div
|
|
79
|
-
key={itemKey}
|
|
80
|
-
id={item.anchorId}
|
|
81
|
-
className="snap-start scroll-mt-48 lg:scroll-mt-60"
|
|
82
|
-
>
|
|
83
|
-
<AccordionComponent
|
|
84
|
-
title={item.title}
|
|
85
|
-
defaultOpen={isOpen}
|
|
86
|
-
containerClassName="border-none"
|
|
87
|
-
buttonClassName="p-0 label1"
|
|
88
|
-
titleClassName="label3 md:label1 text-text"
|
|
89
|
-
className="p-0 pt-6 text-text"
|
|
90
|
-
iconClassName="text-icon"
|
|
91
|
-
borderRadiusNone={true}
|
|
92
|
-
openOnlyOnDesktop={false}
|
|
93
|
-
{...(item.anchorId && {
|
|
94
|
-
onClick: /* istanbul ignore next */ () =>
|
|
95
|
-
handleToggle(item.anchorId!),
|
|
96
|
-
})}
|
|
97
|
-
>
|
|
98
|
-
<div className={descriptionMaxWidth}>
|
|
99
|
-
<Text as="div">{item.description}</Text>
|
|
100
|
-
</div>
|
|
101
|
-
</AccordionComponent>
|
|
102
|
-
{index < items.length - 1 && (
|
|
103
|
-
<Divider key={`divider-${index}`} className="my-6 md:my-10" />
|
|
104
|
-
)}
|
|
105
|
-
</div>
|
|
106
|
-
);
|
|
107
|
-
})}
|
|
108
|
-
</div>
|
|
109
|
-
</div>
|
|
110
|
-
</section>
|
|
111
|
-
);
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
export default Accordion;
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import React, { useEffect, useState } from "react";
|
|
4
|
+
import { AccordionItem, AccordionProps, ThemeKey } from "./types";
|
|
5
|
+
|
|
6
|
+
import { Accordion as AccordionComponent } from "@shared/components/accordion";
|
|
7
|
+
import { Divider } from "@shared/components/divider";
|
|
8
|
+
import { Text } from "@shared/components/text";
|
|
9
|
+
|
|
10
|
+
export const Accordion: React.FC<AccordionProps> = ({
|
|
11
|
+
items,
|
|
12
|
+
title,
|
|
13
|
+
anchorId,
|
|
14
|
+
background = "white",
|
|
15
|
+
enableHeading = false,
|
|
16
|
+
maxWidth = true,
|
|
17
|
+
initialExpandedItems: initialExpandedItemsProp = [],
|
|
18
|
+
hashAutoExpand = false,
|
|
19
|
+
descriptionMaxWidth = "max-w-[980px]",
|
|
20
|
+
itemContainerClassName,
|
|
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
|
+
/* istanbul ignore next -- passed to AccordionComponent which does not forward onClick */
|
|
40
|
+
const handleToggle = (itemAnchorId: string) => {
|
|
41
|
+
setExpandedItems(prev =>
|
|
42
|
+
prev.includes(itemAnchorId)
|
|
43
|
+
? prev.filter(id => id !== itemAnchorId)
|
|
44
|
+
: [...prev, itemAnchorId]
|
|
45
|
+
);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const bgColorClasses: Record<ThemeKey, string> = {
|
|
49
|
+
blue: "bg-[#07B2E2]",
|
|
50
|
+
green: "bg-[#26B170]",
|
|
51
|
+
yellow: "bg-[#F5FF1E]",
|
|
52
|
+
purple: "bg-[#931D69]",
|
|
53
|
+
white: "bg-white",
|
|
54
|
+
navy: "bg-[#00002D]",
|
|
55
|
+
cream500: "bg-[#FFFEEF]",
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<section
|
|
60
|
+
id={anchorId}
|
|
61
|
+
className={`${bgColorClasses[background]} flex flex-col px-5 pb-20 pt-4 md:px-10`}
|
|
62
|
+
>
|
|
63
|
+
<div className={`${maxWidth ? "max-w-120 xl:mx-auto" : ""}`}>
|
|
64
|
+
<Text
|
|
65
|
+
as={enableHeading ? "h1" : "h2"}
|
|
66
|
+
className="heading2 mb-10 pt-12 text-left text-text md:heading1 lg:text-center"
|
|
67
|
+
>
|
|
68
|
+
{title}
|
|
69
|
+
</Text>
|
|
70
|
+
<div className={`pt-6 md:pt-10 ${itemContainerClassName ?? ""}`}>
|
|
71
|
+
{items?.map((item: AccordionItem, index: number) => {
|
|
72
|
+
const itemKey = item.anchorId || `item-${index}`;
|
|
73
|
+
const isOpen = item.anchorId
|
|
74
|
+
? expandedItems.includes(item.anchorId)
|
|
75
|
+
: undefined;
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<div
|
|
79
|
+
key={itemKey}
|
|
80
|
+
id={item.anchorId}
|
|
81
|
+
className="snap-start scroll-mt-48 lg:scroll-mt-60"
|
|
82
|
+
>
|
|
83
|
+
<AccordionComponent
|
|
84
|
+
title={item.title}
|
|
85
|
+
defaultOpen={isOpen}
|
|
86
|
+
containerClassName="border-none"
|
|
87
|
+
buttonClassName="p-0 label1"
|
|
88
|
+
titleClassName="label3 md:label1 text-text"
|
|
89
|
+
className="p-0 pt-6 text-text"
|
|
90
|
+
iconClassName="text-icon"
|
|
91
|
+
borderRadiusNone={true}
|
|
92
|
+
openOnlyOnDesktop={false}
|
|
93
|
+
{...(item.anchorId && {
|
|
94
|
+
onClick: /* istanbul ignore next */ () =>
|
|
95
|
+
handleToggle(item.anchorId!),
|
|
96
|
+
})}
|
|
97
|
+
>
|
|
98
|
+
<div className={descriptionMaxWidth}>
|
|
99
|
+
<Text as="div">{item.description}</Text>
|
|
100
|
+
</div>
|
|
101
|
+
</AccordionComponent>
|
|
102
|
+
{index < items.length - 1 && (
|
|
103
|
+
<Divider key={`divider-${index}`} className="my-6 md:my-10" />
|
|
104
|
+
)}
|
|
105
|
+
</div>
|
|
106
|
+
);
|
|
107
|
+
})}
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
</section>
|
|
111
|
+
);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
export default Accordion;
|