@agilant/toga-blox 1.0.5
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/Dockerfile +9 -0
- package/README.md +69 -0
- package/assets/Logo.png +0 -0
- package/assets/compass-card-image-2.png +0 -0
- package/assets/compass-card-image-3.png +0 -0
- package/assets/compass-card-image-4.png +0 -0
- package/assets/compass-card-image.png +0 -0
- package/assets/compass-logo.png +0 -0
- package/assets/compass-tech-hero-bg.png +0 -0
- package/assets/contact-image.png +0 -0
- package/assets/green-laptop.png +0 -0
- package/assets/heroImage.png +0 -0
- package/assets/placeholder-no-image-available.png +0 -0
- package/assets/team.png +0 -0
- package/declarations.d.ts +4 -0
- package/docker-compose.yml +22 -0
- package/global.css +4 -0
- package/index.js +4 -0
- package/nodemon.json +5 -0
- package/package.json +70 -0
- package/postcss.config.js +6 -0
- package/src/components/Badge/Badge.stories.tsx +284 -0
- package/src/components/Badge/Badge.test.tsx +185 -0
- package/src/components/Badge/Badge.tsx +137 -0
- package/src/components/Badge/Badge.types.tsx +28 -0
- package/src/components/Badge/badgeClassNames.tsx +152 -0
- package/src/components/Badge/index.ts +2 -0
- package/src/components/Card/Card.stories.tsx +91 -0
- package/src/components/Card/Card.test.tsx +53 -0
- package/src/components/Card/Card.tsx +30 -0
- package/src/components/Card/Card.types.ts +11 -0
- package/src/components/Card/DUMMYPRODUCTDATA.json +670 -0
- package/src/components/Card/cardClassNames.ts +49 -0
- package/src/components/Card/index.ts +3 -0
- package/src/components/Card/templates/CompassCardTemplate.tsx +58 -0
- package/src/components/Card/templates/HorizontalCardTemplate.tsx +184 -0
- package/src/components/Card/templates/VerticalCardTemplate.tsx +154 -0
- package/src/components/Footer/ContactInfoItem.tsx +20 -0
- package/src/components/Footer/DUMMYFOOTERDATA.json +132 -0
- package/src/components/Footer/Footer.stories.tsx +292 -0
- package/src/components/Footer/Footer.test.tsx +90 -0
- package/src/components/Footer/Footer.tsx +159 -0
- package/src/components/Footer/Footer.types.tsx +61 -0
- package/src/components/Footer/footerClassNames.tsx +57 -0
- package/src/components/FormButton/FormButton.stories.tsx +199 -0
- package/src/components/FormButton/FormButton.test.tsx +73 -0
- package/src/components/FormButton/FormButton.tsx +116 -0
- package/src/components/FormButton/FormButton.types.ts +32 -0
- package/src/components/FormButton/formButtonClassNames.tsx +153 -0
- package/src/components/FormButton/index.ts +2 -0
- package/src/components/GenericList/DUMMYLISTDATA.json +560 -0
- package/src/components/GenericList/GenericList.stories.tsx +104 -0
- package/src/components/GenericList/GenericList.test.tsx +29 -0
- package/src/components/GenericList/GenericList.tsx +146 -0
- package/src/components/GenericList/genericListClassNames.tsx +8 -0
- package/src/components/GenericList/templates/DummyDataList.tsx +23 -0
- package/src/components/GenericList/templates/DynamicIconList.tsx +74 -0
- package/src/components/HamburgerButton/HamburgerButton.tsx +68 -0
- package/src/components/HamburgerButton/HamburgerButton.types.tsx +6 -0
- package/src/components/HamburgerButton/index.ts +2 -0
- package/src/components/Header/DUMMYICONDATA.json +136 -0
- package/src/components/Header/Header.stories.tsx +521 -0
- package/src/components/Header/Header.test.tsx +323 -0
- package/src/components/Header/Header.tsx +289 -0
- package/src/components/Header/Header.types.ts +52 -0
- package/src/components/Header/headerClassNames.tsx +50 -0
- package/src/components/Header/headerContext.tsx +125 -0
- package/src/components/Header/index.ts +2 -0
- package/src/components/Hero/Hero.stories.tsx +69 -0
- package/src/components/Hero/Hero.test.tsx +109 -0
- package/src/components/Hero/Hero.tsx +58 -0
- package/src/components/Hero/Hero.types.ts +9 -0
- package/src/components/Hero/index.ts +2 -0
- package/src/components/Icon/Icon.stories.tsx +227 -0
- package/src/components/Icon/Icon.test.tsx +53 -0
- package/src/components/Icon/Icon.tsx +208 -0
- package/src/components/Icon/Icon.types.ts +24 -0
- package/src/components/Icon/iconClassNames.ts +79 -0
- package/src/components/Icon/index.ts +2 -0
- package/src/components/Image/Image.stories.tsx +79 -0
- package/src/components/Image/Image.test.tsx +87 -0
- package/src/components/Image/Image.tsx +49 -0
- package/src/components/Image/Image.types.ts +11 -0
- package/src/components/Image/index.ts +2 -0
- package/src/components/Input/Input.stories.tsx +651 -0
- package/src/components/Input/Input.test.tsx +90 -0
- package/src/components/Input/Input.tsx +226 -0
- package/src/components/Input/Input.types.ts +52 -0
- package/src/components/Input/InputMemoTypes.tsx +32 -0
- package/src/components/Input/index.ts +2 -0
- package/src/components/Input/inputClassNames.tsx +169 -0
- package/src/components/MobileMenu/MobileMenu.tsx +41 -0
- package/src/components/MobileMenu/MobileMenu.types.tsx +30 -0
- package/src/components/MobileMenu/index.ts +2 -0
- package/src/components/Nav/DUMMYNAVDATA.json +234 -0
- package/src/components/Nav/Nav.stories.tsx +181 -0
- package/src/components/Nav/Nav.test.tsx +89 -0
- package/src/components/Nav/Nav.tsx +242 -0
- package/src/components/Nav/Nav.types.tsx +35 -0
- package/src/components/Nav/index.ts +2 -0
- package/src/components/Nav/navClassNames.tsx +192 -0
- package/src/components/Page/TableDataDummy.tsx +216 -0
- package/src/components/Page/ViewPageTemplate.stories.tsx +546 -0
- package/src/components/Page/ViewPageTemplate.test.tsx +361 -0
- package/src/components/Page/ViewPageTemplate.tsx +10 -0
- package/src/components/Page/ViewPageTemplate.types.ts +6 -0
- package/src/components/Page/index.ts +2 -0
- package/src/components/PageSection/PageSection.stories.tsx +114 -0
- package/src/components/PageSection/PageSection.tsx +12 -0
- package/src/components/PageSection/PageSection.types.ts +6 -0
- package/src/components/PageSection/PageSections.test.tsx +88 -0
- package/src/components/PageSection/index.ts +2 -0
- package/src/components/Text/Text.stories.tsx +60 -0
- package/src/components/Text/Text.test.tsx +52 -0
- package/src/components/Text/Text.tsx +80 -0
- package/src/components/Text/Text.types.ts +12 -0
- package/src/components/Text/index.ts +2 -0
- package/src/components/Toaster/Toaster.stories.tsx +122 -0
- package/src/components/Toaster/Toaster.test.tsx +61 -0
- package/src/components/Toaster/Toaster.tsx +80 -0
- package/src/components/Toaster/Toaster.types.ts +12 -0
- package/src/components/Toaster/index.ts +2 -0
- package/src/hoc/index.ts +2 -0
- package/src/hoc/styling/withStoryBook.tsx +19 -0
- package/src/main.css +3 -0
- package/src/setupTests.ts +1 -0
- package/src/userHoc/index.ts +1 -0
- package/src/userHoc/withMemo.tsx +20 -0
- package/src/utils/assertTagName.tsx +7 -0
- package/src/utils/generateAccordionItem.tsx +102 -0
- package/src/utils/generateFooterContacts.tsx +75 -0
- package/src/utils/generateNavMenu.tsx +54 -0
- package/src/utils/generateSocialList.tsx +34 -0
- package/src/utils/getFontAwesomeIcon.tsx +25 -0
- package/src/utils/inputValidation.tsx +26 -0
- package/tailwind.config.js +32 -0
- package/tsconfig.json +25 -0
- package/vite.config.ts +33 -0
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Meta, StoryFn } from "@storybook/react";
|
|
3
|
+
import Footer from "./Footer";
|
|
4
|
+
import { FooterProps } from "./Footer.types";
|
|
5
|
+
import Image from "../Image/Image";
|
|
6
|
+
import Text from "../Text/Text";
|
|
7
|
+
|
|
8
|
+
import { withStoryBook } from "../../hoc";
|
|
9
|
+
|
|
10
|
+
// Wrap your component with the HOC
|
|
11
|
+
const StoryBookViewFooter = withStoryBook(Footer);
|
|
12
|
+
|
|
13
|
+
export default {
|
|
14
|
+
title: "Footers/Footer",
|
|
15
|
+
argTypes: {
|
|
16
|
+
// LOGO & BACKGROUND & FOOTER BAR
|
|
17
|
+
logo: {
|
|
18
|
+
control: "none",
|
|
19
|
+
description: "The logo displayed in the footer",
|
|
20
|
+
},
|
|
21
|
+
logoBorderRadius: {
|
|
22
|
+
control: "boolean",
|
|
23
|
+
description: "Whether the logo has a border radius.",
|
|
24
|
+
},
|
|
25
|
+
logoHoverColor: {
|
|
26
|
+
control: "select",
|
|
27
|
+
options: ["green", "blue", "none"],
|
|
28
|
+
description: "Whether the logo has a background color on hover.",
|
|
29
|
+
},
|
|
30
|
+
backgroundColor: {
|
|
31
|
+
control: "color",
|
|
32
|
+
description: "Whether the footer has a background color.",
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
// TITLE AND SLOGAN
|
|
36
|
+
title: {
|
|
37
|
+
control: "text",
|
|
38
|
+
description: "The title displayed in the footer",
|
|
39
|
+
},
|
|
40
|
+
slogan: {
|
|
41
|
+
control: "text",
|
|
42
|
+
description: "The slogan displayed in the footer",
|
|
43
|
+
},
|
|
44
|
+
hasTitle: {
|
|
45
|
+
control: "boolean",
|
|
46
|
+
description: "Whether the footer has a title displayed",
|
|
47
|
+
},
|
|
48
|
+
hasSlogan: {
|
|
49
|
+
control: "boolean",
|
|
50
|
+
description: "Whether the footer has a slogan displayed",
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
// NAV
|
|
54
|
+
hasNavItems: {
|
|
55
|
+
control: "boolean",
|
|
56
|
+
description: "Whether the footer has navigation items.",
|
|
57
|
+
},
|
|
58
|
+
accordionGap: {
|
|
59
|
+
table: {
|
|
60
|
+
disable: true,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
accordionParentStyle: {
|
|
64
|
+
table: {
|
|
65
|
+
disable: true,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
accordionExpandedStyle: {
|
|
69
|
+
table: {
|
|
70
|
+
disable: true,
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
// SOCIAL
|
|
75
|
+
socialTitle: {
|
|
76
|
+
table: {
|
|
77
|
+
disable: true,
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
socialPlacement: {
|
|
81
|
+
control: "select",
|
|
82
|
+
options: ["left", "center", "right"],
|
|
83
|
+
description: "Where the social icons are placed.",
|
|
84
|
+
},
|
|
85
|
+
hasSocial: {
|
|
86
|
+
control: "boolean",
|
|
87
|
+
description: "Whether the footer has social icons displayed",
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
// CONTACT
|
|
91
|
+
contactTitle: {
|
|
92
|
+
table: {
|
|
93
|
+
disable: true,
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
// COPYRIGHT
|
|
98
|
+
copyRightTextPlacement: {
|
|
99
|
+
control: "select",
|
|
100
|
+
options: ["left", "center", "right"],
|
|
101
|
+
description: "Where the copyright statement is placed.",
|
|
102
|
+
},
|
|
103
|
+
copyRightText: {
|
|
104
|
+
table: {
|
|
105
|
+
disable: true,
|
|
106
|
+
},
|
|
107
|
+
description: "Whether the footer displays a copyright statement.",
|
|
108
|
+
},
|
|
109
|
+
hasCopyRight: {
|
|
110
|
+
control: "boolean",
|
|
111
|
+
description:
|
|
112
|
+
"Whether the footer has a copyright statement displayed",
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
} as Meta<FooterProps>;
|
|
116
|
+
|
|
117
|
+
const Template: StoryFn<typeof StoryBookViewFooter> = (args) => (
|
|
118
|
+
<StoryBookViewFooter
|
|
119
|
+
{...args}
|
|
120
|
+
storybookStyle={{
|
|
121
|
+
backgroundColor: args.backgroundColor,
|
|
122
|
+
}}
|
|
123
|
+
/>
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
export const Default = Template.bind({});
|
|
127
|
+
Default.args = {
|
|
128
|
+
logoBorderRadius: true,
|
|
129
|
+
hasNavItems: false,
|
|
130
|
+
hasSocial: true,
|
|
131
|
+
logoHoverColor: "blue",
|
|
132
|
+
backgroundColor: "gray",
|
|
133
|
+
contactTitle: (
|
|
134
|
+
<Text
|
|
135
|
+
size={"md"}
|
|
136
|
+
color={"black"}
|
|
137
|
+
text="Contact Us:"
|
|
138
|
+
fontFamily={""}
|
|
139
|
+
additionalClasses="font-bold uppercase"
|
|
140
|
+
/>
|
|
141
|
+
),
|
|
142
|
+
copyRightText: (
|
|
143
|
+
<Text
|
|
144
|
+
size={"md"}
|
|
145
|
+
color={"black"}
|
|
146
|
+
text="Copyright © 2024 - All right reserved by Generic Company"
|
|
147
|
+
fontFamily={""}
|
|
148
|
+
additionalClasses="text-center"
|
|
149
|
+
/>
|
|
150
|
+
),
|
|
151
|
+
copyRightTextPlacement: "center",
|
|
152
|
+
socialPlacement: "center",
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
export const CompassFooter = Template.bind({});
|
|
156
|
+
CompassFooter.args = {
|
|
157
|
+
logo: (
|
|
158
|
+
<Image
|
|
159
|
+
src="../../../assets/compass-logo.png"
|
|
160
|
+
alt="Generic Compass Logo."
|
|
161
|
+
background={false}
|
|
162
|
+
additionalClasses=" w-40 p-2"
|
|
163
|
+
/>
|
|
164
|
+
),
|
|
165
|
+
title: (
|
|
166
|
+
<Text
|
|
167
|
+
size={"xl"}
|
|
168
|
+
color={""}
|
|
169
|
+
text={"Compass Website"}
|
|
170
|
+
fontFamily={""}
|
|
171
|
+
tag={"h2"}
|
|
172
|
+
additionalClasses="font-bold uppercase pl-2 mt-2 max-md:text-sm"
|
|
173
|
+
/>
|
|
174
|
+
),
|
|
175
|
+
slogan: (
|
|
176
|
+
<Text
|
|
177
|
+
size={"md"}
|
|
178
|
+
color={""}
|
|
179
|
+
text={"Great slogan goes here."}
|
|
180
|
+
fontFamily={""}
|
|
181
|
+
tag={"p"}
|
|
182
|
+
additionalClasses="pl-2"
|
|
183
|
+
/>
|
|
184
|
+
),
|
|
185
|
+
copyRightText: (
|
|
186
|
+
<Text
|
|
187
|
+
size={"md"}
|
|
188
|
+
color={"black"}
|
|
189
|
+
text="Copyright © 2024 - All right reserved by Generic Company"
|
|
190
|
+
fontFamily={""}
|
|
191
|
+
additionalClasses="text-center"
|
|
192
|
+
/>
|
|
193
|
+
),
|
|
194
|
+
socialTitle: (
|
|
195
|
+
<Text
|
|
196
|
+
size={"md"}
|
|
197
|
+
color={"black"}
|
|
198
|
+
text="Connect"
|
|
199
|
+
fontFamily={""}
|
|
200
|
+
additionalClasses="font-bold uppercase w-full"
|
|
201
|
+
/>
|
|
202
|
+
),
|
|
203
|
+
contactTitle: (
|
|
204
|
+
<Text
|
|
205
|
+
size={"md"}
|
|
206
|
+
color={"black"}
|
|
207
|
+
text="Contact Us:"
|
|
208
|
+
fontFamily={""}
|
|
209
|
+
additionalClasses="font-bold uppercase"
|
|
210
|
+
/>
|
|
211
|
+
),
|
|
212
|
+
logoBorderRadius: true,
|
|
213
|
+
hasNavItems: true,
|
|
214
|
+
hasSocial: true,
|
|
215
|
+
logoHoverColor: "green",
|
|
216
|
+
backgroundColor: "green",
|
|
217
|
+
accordionGap: "gap-1",
|
|
218
|
+
copyRightTextPlacement: "center",
|
|
219
|
+
socialPlacement: "center",
|
|
220
|
+
accordionParentStyle: "border-b border-black p-2 w-full",
|
|
221
|
+
accordionExpandedStyle: "pl-3 py-3",
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
export const AlternateMobileNavStyle = Template.bind({});
|
|
225
|
+
AlternateMobileNavStyle.args = {
|
|
226
|
+
logo: (
|
|
227
|
+
<Image
|
|
228
|
+
src="../../../assets/compass-logo.png"
|
|
229
|
+
alt="Generic Compass Logo."
|
|
230
|
+
background={false}
|
|
231
|
+
additionalClasses=" w-40 p-2"
|
|
232
|
+
/>
|
|
233
|
+
),
|
|
234
|
+
title: (
|
|
235
|
+
<Text
|
|
236
|
+
size={"xl"}
|
|
237
|
+
color={""}
|
|
238
|
+
text={"Compass Website"}
|
|
239
|
+
fontFamily={""}
|
|
240
|
+
tag={"h2"}
|
|
241
|
+
additionalClasses="font-bold uppercase pl-2 mt-2 max-md:text-sm"
|
|
242
|
+
/>
|
|
243
|
+
),
|
|
244
|
+
slogan: (
|
|
245
|
+
<Text
|
|
246
|
+
size={"md"}
|
|
247
|
+
color={""}
|
|
248
|
+
text={"Great slogan goes here."}
|
|
249
|
+
fontFamily={""}
|
|
250
|
+
tag={"p"}
|
|
251
|
+
additionalClasses="pl-2"
|
|
252
|
+
/>
|
|
253
|
+
),
|
|
254
|
+
copyRightText: (
|
|
255
|
+
<Text
|
|
256
|
+
size={"md"}
|
|
257
|
+
color={"black"}
|
|
258
|
+
text="Copyright © 2024 - All right reserved by Generic Company"
|
|
259
|
+
fontFamily={""}
|
|
260
|
+
additionalClasses="text-center"
|
|
261
|
+
/>
|
|
262
|
+
),
|
|
263
|
+
socialTitle: (
|
|
264
|
+
<Text
|
|
265
|
+
size={"md"}
|
|
266
|
+
color={"black"}
|
|
267
|
+
text="Connect"
|
|
268
|
+
fontFamily={""}
|
|
269
|
+
additionalClasses="font-bold uppercase w-full"
|
|
270
|
+
/>
|
|
271
|
+
),
|
|
272
|
+
contactTitle: (
|
|
273
|
+
<Text
|
|
274
|
+
size={"md"}
|
|
275
|
+
color={"black"}
|
|
276
|
+
text="Contact Us:"
|
|
277
|
+
fontFamily={""}
|
|
278
|
+
additionalClasses="font-bold uppercase"
|
|
279
|
+
/>
|
|
280
|
+
),
|
|
281
|
+
logoBorderRadius: true,
|
|
282
|
+
hasNavItems: true,
|
|
283
|
+
hasSocial: true,
|
|
284
|
+
accordionGap: "gap-2",
|
|
285
|
+
logoHoverColor: "green",
|
|
286
|
+
backgroundColor: "green",
|
|
287
|
+
copyRightTextPlacement: "center",
|
|
288
|
+
socialPlacement: "center",
|
|
289
|
+
accordionParentStyle:
|
|
290
|
+
"rounded-md border-black p-2 w-full bg-teal-700 text-white",
|
|
291
|
+
accordionExpandedStyle: "pl-2 py-3",
|
|
292
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import "../../../dist/main.css";
|
|
2
|
+
import { render, screen, within } from "@testing-library/react";
|
|
3
|
+
import { describe, test, expect, beforeEach } from "vitest";
|
|
4
|
+
|
|
5
|
+
import Footer from "./Footer";
|
|
6
|
+
import Image from "../Image/Image";
|
|
7
|
+
import {
|
|
8
|
+
DUMMYCONTACTDATA,
|
|
9
|
+
DUMMYNAVDATA,
|
|
10
|
+
DUMMYSOCIALDATA,
|
|
11
|
+
} from "./DUMMYFOOTERDATA.json";
|
|
12
|
+
|
|
13
|
+
describe("<Footer /> with all props (pill, icons, input, logo)", () => {
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
render(
|
|
16
|
+
<Footer
|
|
17
|
+
logo={
|
|
18
|
+
<Image
|
|
19
|
+
src="../../../assets/Logo.png"
|
|
20
|
+
alt="Generic Company Logo."
|
|
21
|
+
background={false}
|
|
22
|
+
additionalClasses=" w-40 "
|
|
23
|
+
/>
|
|
24
|
+
}
|
|
25
|
+
hasSlogan={true}
|
|
26
|
+
hasTitle={false}
|
|
27
|
+
slogan="Great slogan goes here."
|
|
28
|
+
backgroundColor={"gray"}
|
|
29
|
+
logoBorderRadius
|
|
30
|
+
logoHoverColor={"blue"}
|
|
31
|
+
hasNavItems={true}
|
|
32
|
+
hasSocial={true}
|
|
33
|
+
hasContact={true}
|
|
34
|
+
socialData={DUMMYSOCIALDATA}
|
|
35
|
+
navData={DUMMYNAVDATA}
|
|
36
|
+
contactData={DUMMYCONTACTDATA}
|
|
37
|
+
/>
|
|
38
|
+
);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test("renders Footer component", () => {
|
|
42
|
+
expect(screen.getByTestId("footer")).toBeInTheDocument();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test("renders correct background color class", () => {
|
|
46
|
+
const footer = screen.getByTestId("footer");
|
|
47
|
+
expect(footer).toHaveClass("bg-slate-200");
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("contains correct logo from Image component", () => {
|
|
51
|
+
const footerLogo = screen.getByTestId("footer-logo");
|
|
52
|
+
const logoImage = footerLogo.querySelector("img");
|
|
53
|
+
expect(logoImage).toHaveAttribute("src", "../../../assets/Logo.png");
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test("contains correct alt text from Image component", () => {
|
|
57
|
+
const footerLogo = screen.getByTestId("footer-logo");
|
|
58
|
+
const logoImage = footerLogo.querySelector("img");
|
|
59
|
+
expect(logoImage).toHaveAttribute("alt", "Generic Company Logo.");
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("contains correct slogan", () => {
|
|
63
|
+
const titleSloganElement = screen.getByTestId("title-slogan");
|
|
64
|
+
|
|
65
|
+
const sloganElement = within(titleSloganElement).getByTestId("slogan");
|
|
66
|
+
expect(sloganElement).toBeInTheDocument();
|
|
67
|
+
expect(sloganElement).toHaveTextContent("Great slogan goes here.");
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test("contains correct site navigation ", () => {
|
|
71
|
+
expect(
|
|
72
|
+
screen.getByTestId("footer-site-navigation")
|
|
73
|
+
).toBeInTheDocument();
|
|
74
|
+
|
|
75
|
+
expect(screen.getByTestId("About")).toBeInTheDocument();
|
|
76
|
+
expect(screen.getByTestId("Projects")).toBeInTheDocument();
|
|
77
|
+
expect(screen.getByTestId("Community")).toBeInTheDocument();
|
|
78
|
+
expect(screen.getByTestId("Store")).toBeInTheDocument();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("contains correct social navigation ", () => {
|
|
82
|
+
expect(
|
|
83
|
+
screen.getByTestId("footer-social-navigation")
|
|
84
|
+
).toBeInTheDocument();
|
|
85
|
+
|
|
86
|
+
expect(screen.getByTestId("Twitter")).toBeInTheDocument();
|
|
87
|
+
expect(screen.getByTestId("YouTube")).toBeInTheDocument();
|
|
88
|
+
expect(screen.getByTestId("Facebook")).toBeInTheDocument();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import Image from "../Image/Image";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
DUMMYCONTACTDATA,
|
|
6
|
+
DUMMYNAVDATA,
|
|
7
|
+
DUMMYSOCIALDATA,
|
|
8
|
+
} from "./DUMMYFOOTERDATA.json";
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
getLogoClasses,
|
|
12
|
+
getBackgroundColor,
|
|
13
|
+
getSocialPlacement,
|
|
14
|
+
getCopyRightPlacement,
|
|
15
|
+
} from "./footerClassNames";
|
|
16
|
+
|
|
17
|
+
import type { FooterProps } from "./Footer.types";
|
|
18
|
+
import { SocialList } from "../../utils/generateSocialList";
|
|
19
|
+
import { NavList } from "../../utils/generateNavMenu";
|
|
20
|
+
import { Accordion } from "../../utils/generateAccordionItem";
|
|
21
|
+
import { FooterContacts } from "../../utils/generateFooterContacts";
|
|
22
|
+
|
|
23
|
+
const Footer: React.FC<FooterProps> = ({
|
|
24
|
+
logo = (
|
|
25
|
+
<Image
|
|
26
|
+
src="../../../assets/Logo.png"
|
|
27
|
+
alt="Generic Company Logo."
|
|
28
|
+
background={false}
|
|
29
|
+
additionalClasses=" w-40 p-2"
|
|
30
|
+
/>
|
|
31
|
+
),
|
|
32
|
+
hasTitle,
|
|
33
|
+
hasSlogan,
|
|
34
|
+
title,
|
|
35
|
+
slogan,
|
|
36
|
+
backgroundColor,
|
|
37
|
+
logoBorderRadius,
|
|
38
|
+
logoHoverColor,
|
|
39
|
+
hasNavItems = true,
|
|
40
|
+
hasSocial = true,
|
|
41
|
+
hasContact = true,
|
|
42
|
+
hasCopyRight = true,
|
|
43
|
+
copyRightText,
|
|
44
|
+
socialData = DUMMYSOCIALDATA,
|
|
45
|
+
navData = DUMMYNAVDATA,
|
|
46
|
+
contactData = DUMMYCONTACTDATA,
|
|
47
|
+
socialTitle,
|
|
48
|
+
contactTitle,
|
|
49
|
+
copyRightTextPlacement,
|
|
50
|
+
socialPlacement,
|
|
51
|
+
accordionParentStyle = "border-2 rounded-md border-black p-2 w-full",
|
|
52
|
+
accordionExpandedStyle = "pl-3",
|
|
53
|
+
accordionGap,
|
|
54
|
+
}) => {
|
|
55
|
+
let logoClasses = getLogoClasses(logoHoverColor, logoBorderRadius);
|
|
56
|
+
let backgroundColorClasses = getBackgroundColor(backgroundColor);
|
|
57
|
+
let socialPlacementClasses = getSocialPlacement(socialPlacement);
|
|
58
|
+
let copyRightTextPlacementClasses = getCopyRightPlacement(
|
|
59
|
+
copyRightTextPlacement
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
// TODO: screen reader does not read all content of footer.
|
|
64
|
+
// not sure if this is a storybook issue, or if it is a code issue
|
|
65
|
+
<footer
|
|
66
|
+
className={`footer flex flex-col ${backgroundColorClasses} py-6 px-6`}
|
|
67
|
+
data-testid="footer"
|
|
68
|
+
>
|
|
69
|
+
<div className="flex justify-between w-full max-xl:px-2 max-lg:flex max-lg:flex-col max-xl:gap-10">
|
|
70
|
+
<div className="max-lg:flex max-lg:justify-between max-lg:w-full">
|
|
71
|
+
<div className={logoClasses}>
|
|
72
|
+
<a tabIndex={0} href="" data-testid="footer-logo">
|
|
73
|
+
{logo}
|
|
74
|
+
</a>
|
|
75
|
+
</div>
|
|
76
|
+
<div data-testid="title-slogan">
|
|
77
|
+
{hasTitle ? (
|
|
78
|
+
<div data-testid="title">{title}</div>
|
|
79
|
+
) : (
|
|
80
|
+
<></>
|
|
81
|
+
)}
|
|
82
|
+
{hasSlogan ? (
|
|
83
|
+
<div data-testid="slogan">{slogan}</div>
|
|
84
|
+
) : (
|
|
85
|
+
<></>
|
|
86
|
+
)}
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
{hasNavItems ? (
|
|
90
|
+
<>
|
|
91
|
+
<nav
|
|
92
|
+
className={`flex gap-12 max-sm:hidden`}
|
|
93
|
+
aria-label="Site navigation."
|
|
94
|
+
data-testid="footer-site-navigation"
|
|
95
|
+
tabIndex={0}
|
|
96
|
+
>
|
|
97
|
+
<NavList navDataList={navData} />
|
|
98
|
+
</nav>
|
|
99
|
+
<nav
|
|
100
|
+
className={`hidden flex-col ${accordionGap} col-span-6 w-3/4 max-sm:w-full max-sm:flex`}
|
|
101
|
+
aria-label="Site navigation."
|
|
102
|
+
data-testid="footer-mobile-navigation"
|
|
103
|
+
>
|
|
104
|
+
<>
|
|
105
|
+
<Accordion
|
|
106
|
+
navData={navData}
|
|
107
|
+
accordionParentStyle={accordionParentStyle}
|
|
108
|
+
accordionExpandedStyle={
|
|
109
|
+
accordionExpandedStyle
|
|
110
|
+
}
|
|
111
|
+
/>
|
|
112
|
+
</>
|
|
113
|
+
</nav>
|
|
114
|
+
</>
|
|
115
|
+
) : (
|
|
116
|
+
<></>
|
|
117
|
+
)}
|
|
118
|
+
{hasContact ? (
|
|
119
|
+
<div
|
|
120
|
+
className="flex flex-col space-between"
|
|
121
|
+
data-testid="footer-contact-info"
|
|
122
|
+
>
|
|
123
|
+
{contactTitle ? contactTitle : <></>}
|
|
124
|
+
<FooterContacts contactDataList={contactData} />
|
|
125
|
+
</div>
|
|
126
|
+
) : (
|
|
127
|
+
<></>
|
|
128
|
+
)}
|
|
129
|
+
</div>
|
|
130
|
+
{hasSocial ? (
|
|
131
|
+
<nav
|
|
132
|
+
className={`w-full ${socialPlacementClasses}`}
|
|
133
|
+
aria-hidden="false"
|
|
134
|
+
aria-label="Social media navigation."
|
|
135
|
+
data-testid="footer-social-navigation"
|
|
136
|
+
>
|
|
137
|
+
{socialTitle ? socialTitle : <></>}
|
|
138
|
+
<div className="grid grid-flow-col gap-3">
|
|
139
|
+
<SocialList socialDataList={socialData} />
|
|
140
|
+
</div>
|
|
141
|
+
</nav>
|
|
142
|
+
) : (
|
|
143
|
+
<></>
|
|
144
|
+
)}
|
|
145
|
+
{hasCopyRight ? (
|
|
146
|
+
<div
|
|
147
|
+
className={`w-full ${copyRightTextPlacementClasses}`}
|
|
148
|
+
aria-hidden="false"
|
|
149
|
+
>
|
|
150
|
+
{copyRightText}
|
|
151
|
+
</div>
|
|
152
|
+
) : (
|
|
153
|
+
<></>
|
|
154
|
+
)}
|
|
155
|
+
</footer>
|
|
156
|
+
);
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
export default Footer;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DUMMYCONTACTDATA,
|
|
3
|
+
DUMMYNAVDATA,
|
|
4
|
+
DUMMYSOCIALDATA,
|
|
5
|
+
} from "./DUMMYFOOTERDATA.json";
|
|
6
|
+
|
|
7
|
+
export interface NavItem {
|
|
8
|
+
title: string;
|
|
9
|
+
links: Array<{ link: string; menuItem: string }>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface SocialItem {
|
|
13
|
+
href: string;
|
|
14
|
+
xmlns: string;
|
|
15
|
+
ariaLabel: string;
|
|
16
|
+
path: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
export interface FooterProps {
|
|
21
|
+
onClick?: (
|
|
22
|
+
e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>
|
|
23
|
+
) => void;
|
|
24
|
+
// LOGO
|
|
25
|
+
hasLogo?: boolean;
|
|
26
|
+
logo?: React.ReactNode;
|
|
27
|
+
backgroundColor?: string;
|
|
28
|
+
logoHoverColor?: string;
|
|
29
|
+
logoBorderRadius?: boolean;
|
|
30
|
+
|
|
31
|
+
// TITLE AND SLOGAN
|
|
32
|
+
hasTitle?: boolean;
|
|
33
|
+
hasSlogan?: boolean;
|
|
34
|
+
title?: React.ReactNode;
|
|
35
|
+
slogan?: React.ReactNode;
|
|
36
|
+
|
|
37
|
+
// NAV
|
|
38
|
+
hasNavItems?: boolean;
|
|
39
|
+
navData?: typeof DUMMYNAVDATA;
|
|
40
|
+
accordionParentStyle?: string;
|
|
41
|
+
accordionExpandedStyle?: string;
|
|
42
|
+
accordionGap?: string;
|
|
43
|
+
|
|
44
|
+
// SOCIAL
|
|
45
|
+
hasSocial?: boolean;
|
|
46
|
+
socialData?: typeof DUMMYSOCIALDATA;
|
|
47
|
+
socialTitle?: React.ReactNode;
|
|
48
|
+
socialPlacement?: "left" | "center" | "right";
|
|
49
|
+
|
|
50
|
+
// CONTACT
|
|
51
|
+
contactTitle?: React.ReactNode;
|
|
52
|
+
hasContact?: boolean;
|
|
53
|
+
contactData?: typeof DUMMYCONTACTDATA;
|
|
54
|
+
|
|
55
|
+
// COPYRIGHT
|
|
56
|
+
hasCopyRight?: boolean;
|
|
57
|
+
copyRightText?: React.ReactNode;
|
|
58
|
+
copyRightTextPlacement?: "left" | "center" | "right";
|
|
59
|
+
|
|
60
|
+
children?: React.ReactNode;
|
|
61
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import classNames from "classNames";
|
|
2
|
+
|
|
3
|
+
export const getLogoClasses = (
|
|
4
|
+
logoHoverColor: string | undefined,
|
|
5
|
+
logoBorderRadius: boolean | undefined
|
|
6
|
+
) => {
|
|
7
|
+
return classNames(
|
|
8
|
+
"flex",
|
|
9
|
+
"justify-center",
|
|
10
|
+
{
|
|
11
|
+
"rounded-full": logoBorderRadius === true,
|
|
12
|
+
"rounded-none": logoBorderRadius === false,
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"hover:bg-blue-300": logoHoverColor === "blue",
|
|
16
|
+
"hover:bg-teal-300": logoHoverColor === "green",
|
|
17
|
+
}
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
export const getBackgroundColor = (
|
|
23
|
+
backgroundColor: string | undefined,
|
|
24
|
+
) => {
|
|
25
|
+
return classNames(
|
|
26
|
+
{
|
|
27
|
+
"bg-teal-50": backgroundColor === "green",
|
|
28
|
+
"bg-slate-200": backgroundColor === "gray",
|
|
29
|
+
"bg-transparent": backgroundColor === "none",
|
|
30
|
+
},
|
|
31
|
+
);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const getSocialPlacement = (
|
|
35
|
+
socialPlacement: string | undefined,
|
|
36
|
+
) => {
|
|
37
|
+
return classNames(
|
|
38
|
+
{
|
|
39
|
+
"justify-start pl-4": socialPlacement === "left",
|
|
40
|
+
"justify-center text-center": socialPlacement === "center",
|
|
41
|
+
"justify-end": socialPlacement === "right",
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const getCopyRightPlacement = (
|
|
47
|
+
copyRightTextPlacement: string | undefined,
|
|
48
|
+
) => {
|
|
49
|
+
return classNames(
|
|
50
|
+
{
|
|
51
|
+
"justify-start pl-4": copyRightTextPlacement === "left",
|
|
52
|
+
"justify-center": copyRightTextPlacement === "center",
|
|
53
|
+
"justify-end": copyRightTextPlacement === "right",
|
|
54
|
+
}
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|