@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.
Files changed (138) hide show
  1. package/Dockerfile +9 -0
  2. package/README.md +69 -0
  3. package/assets/Logo.png +0 -0
  4. package/assets/compass-card-image-2.png +0 -0
  5. package/assets/compass-card-image-3.png +0 -0
  6. package/assets/compass-card-image-4.png +0 -0
  7. package/assets/compass-card-image.png +0 -0
  8. package/assets/compass-logo.png +0 -0
  9. package/assets/compass-tech-hero-bg.png +0 -0
  10. package/assets/contact-image.png +0 -0
  11. package/assets/green-laptop.png +0 -0
  12. package/assets/heroImage.png +0 -0
  13. package/assets/placeholder-no-image-available.png +0 -0
  14. package/assets/team.png +0 -0
  15. package/declarations.d.ts +4 -0
  16. package/docker-compose.yml +22 -0
  17. package/global.css +4 -0
  18. package/index.js +4 -0
  19. package/nodemon.json +5 -0
  20. package/package.json +70 -0
  21. package/postcss.config.js +6 -0
  22. package/src/components/Badge/Badge.stories.tsx +284 -0
  23. package/src/components/Badge/Badge.test.tsx +185 -0
  24. package/src/components/Badge/Badge.tsx +137 -0
  25. package/src/components/Badge/Badge.types.tsx +28 -0
  26. package/src/components/Badge/badgeClassNames.tsx +152 -0
  27. package/src/components/Badge/index.ts +2 -0
  28. package/src/components/Card/Card.stories.tsx +91 -0
  29. package/src/components/Card/Card.test.tsx +53 -0
  30. package/src/components/Card/Card.tsx +30 -0
  31. package/src/components/Card/Card.types.ts +11 -0
  32. package/src/components/Card/DUMMYPRODUCTDATA.json +670 -0
  33. package/src/components/Card/cardClassNames.ts +49 -0
  34. package/src/components/Card/index.ts +3 -0
  35. package/src/components/Card/templates/CompassCardTemplate.tsx +58 -0
  36. package/src/components/Card/templates/HorizontalCardTemplate.tsx +184 -0
  37. package/src/components/Card/templates/VerticalCardTemplate.tsx +154 -0
  38. package/src/components/Footer/ContactInfoItem.tsx +20 -0
  39. package/src/components/Footer/DUMMYFOOTERDATA.json +132 -0
  40. package/src/components/Footer/Footer.stories.tsx +292 -0
  41. package/src/components/Footer/Footer.test.tsx +90 -0
  42. package/src/components/Footer/Footer.tsx +159 -0
  43. package/src/components/Footer/Footer.types.tsx +61 -0
  44. package/src/components/Footer/footerClassNames.tsx +57 -0
  45. package/src/components/FormButton/FormButton.stories.tsx +199 -0
  46. package/src/components/FormButton/FormButton.test.tsx +73 -0
  47. package/src/components/FormButton/FormButton.tsx +116 -0
  48. package/src/components/FormButton/FormButton.types.ts +32 -0
  49. package/src/components/FormButton/formButtonClassNames.tsx +153 -0
  50. package/src/components/FormButton/index.ts +2 -0
  51. package/src/components/GenericList/DUMMYLISTDATA.json +560 -0
  52. package/src/components/GenericList/GenericList.stories.tsx +104 -0
  53. package/src/components/GenericList/GenericList.test.tsx +29 -0
  54. package/src/components/GenericList/GenericList.tsx +146 -0
  55. package/src/components/GenericList/genericListClassNames.tsx +8 -0
  56. package/src/components/GenericList/templates/DummyDataList.tsx +23 -0
  57. package/src/components/GenericList/templates/DynamicIconList.tsx +74 -0
  58. package/src/components/HamburgerButton/HamburgerButton.tsx +68 -0
  59. package/src/components/HamburgerButton/HamburgerButton.types.tsx +6 -0
  60. package/src/components/HamburgerButton/index.ts +2 -0
  61. package/src/components/Header/DUMMYICONDATA.json +136 -0
  62. package/src/components/Header/Header.stories.tsx +521 -0
  63. package/src/components/Header/Header.test.tsx +323 -0
  64. package/src/components/Header/Header.tsx +289 -0
  65. package/src/components/Header/Header.types.ts +52 -0
  66. package/src/components/Header/headerClassNames.tsx +50 -0
  67. package/src/components/Header/headerContext.tsx +125 -0
  68. package/src/components/Header/index.ts +2 -0
  69. package/src/components/Hero/Hero.stories.tsx +69 -0
  70. package/src/components/Hero/Hero.test.tsx +109 -0
  71. package/src/components/Hero/Hero.tsx +58 -0
  72. package/src/components/Hero/Hero.types.ts +9 -0
  73. package/src/components/Hero/index.ts +2 -0
  74. package/src/components/Icon/Icon.stories.tsx +227 -0
  75. package/src/components/Icon/Icon.test.tsx +53 -0
  76. package/src/components/Icon/Icon.tsx +208 -0
  77. package/src/components/Icon/Icon.types.ts +24 -0
  78. package/src/components/Icon/iconClassNames.ts +79 -0
  79. package/src/components/Icon/index.ts +2 -0
  80. package/src/components/Image/Image.stories.tsx +79 -0
  81. package/src/components/Image/Image.test.tsx +87 -0
  82. package/src/components/Image/Image.tsx +49 -0
  83. package/src/components/Image/Image.types.ts +11 -0
  84. package/src/components/Image/index.ts +2 -0
  85. package/src/components/Input/Input.stories.tsx +651 -0
  86. package/src/components/Input/Input.test.tsx +90 -0
  87. package/src/components/Input/Input.tsx +226 -0
  88. package/src/components/Input/Input.types.ts +52 -0
  89. package/src/components/Input/InputMemoTypes.tsx +32 -0
  90. package/src/components/Input/index.ts +2 -0
  91. package/src/components/Input/inputClassNames.tsx +169 -0
  92. package/src/components/MobileMenu/MobileMenu.tsx +41 -0
  93. package/src/components/MobileMenu/MobileMenu.types.tsx +30 -0
  94. package/src/components/MobileMenu/index.ts +2 -0
  95. package/src/components/Nav/DUMMYNAVDATA.json +234 -0
  96. package/src/components/Nav/Nav.stories.tsx +181 -0
  97. package/src/components/Nav/Nav.test.tsx +89 -0
  98. package/src/components/Nav/Nav.tsx +242 -0
  99. package/src/components/Nav/Nav.types.tsx +35 -0
  100. package/src/components/Nav/index.ts +2 -0
  101. package/src/components/Nav/navClassNames.tsx +192 -0
  102. package/src/components/Page/TableDataDummy.tsx +216 -0
  103. package/src/components/Page/ViewPageTemplate.stories.tsx +546 -0
  104. package/src/components/Page/ViewPageTemplate.test.tsx +361 -0
  105. package/src/components/Page/ViewPageTemplate.tsx +10 -0
  106. package/src/components/Page/ViewPageTemplate.types.ts +6 -0
  107. package/src/components/Page/index.ts +2 -0
  108. package/src/components/PageSection/PageSection.stories.tsx +114 -0
  109. package/src/components/PageSection/PageSection.tsx +12 -0
  110. package/src/components/PageSection/PageSection.types.ts +6 -0
  111. package/src/components/PageSection/PageSections.test.tsx +88 -0
  112. package/src/components/PageSection/index.ts +2 -0
  113. package/src/components/Text/Text.stories.tsx +60 -0
  114. package/src/components/Text/Text.test.tsx +52 -0
  115. package/src/components/Text/Text.tsx +80 -0
  116. package/src/components/Text/Text.types.ts +12 -0
  117. package/src/components/Text/index.ts +2 -0
  118. package/src/components/Toaster/Toaster.stories.tsx +122 -0
  119. package/src/components/Toaster/Toaster.test.tsx +61 -0
  120. package/src/components/Toaster/Toaster.tsx +80 -0
  121. package/src/components/Toaster/Toaster.types.ts +12 -0
  122. package/src/components/Toaster/index.ts +2 -0
  123. package/src/hoc/index.ts +2 -0
  124. package/src/hoc/styling/withStoryBook.tsx +19 -0
  125. package/src/main.css +3 -0
  126. package/src/setupTests.ts +1 -0
  127. package/src/userHoc/index.ts +1 -0
  128. package/src/userHoc/withMemo.tsx +20 -0
  129. package/src/utils/assertTagName.tsx +7 -0
  130. package/src/utils/generateAccordionItem.tsx +102 -0
  131. package/src/utils/generateFooterContacts.tsx +75 -0
  132. package/src/utils/generateNavMenu.tsx +54 -0
  133. package/src/utils/generateSocialList.tsx +34 -0
  134. package/src/utils/getFontAwesomeIcon.tsx +25 -0
  135. package/src/utils/inputValidation.tsx +26 -0
  136. package/tailwind.config.js +32 -0
  137. package/tsconfig.json +25 -0
  138. package/vite.config.ts +33 -0
@@ -0,0 +1,125 @@
1
+ import { createContext, useContext, useState } from "react";
2
+ import { HeaderTypes } from "./Header.types";
3
+
4
+ type ContextValue = {
5
+ iconsData: HeaderTypes["iconsData"];
6
+ setIconsData: (iconsData: HeaderTypes["iconsData"]) => void;
7
+ mobileCloseIcon: JSX.Element | null;
8
+ setMobileCloseIcon: (mobileCloseIcon: JSX.Element) => void;
9
+
10
+ hasIcons: boolean;
11
+ setHasIcons: (hasNavItems: boolean) => void;
12
+ hasNavItems: boolean;
13
+ setHasNavItems: (hasNavItems: boolean) => void;
14
+ hasBadge: boolean;
15
+ setHasBadge: (hasBadge: boolean) => void;
16
+ hasSearchBar: boolean;
17
+ setHasSearchBar: (hasSearchBar: boolean) => void;
18
+
19
+ hasMobileIcons: boolean;
20
+ setHasMobileIcons: (hasMobileIcons: boolean) => void;
21
+ hasMobileNavItems: boolean;
22
+ setHasMobileNavItems: (hasMobileNavItems: boolean) => void;
23
+ hasMobileBadge: boolean;
24
+ setHasMobileBadge: (hasMobileBadge: boolean) => void;
25
+ hasMobileSearchBar: boolean;
26
+ setHasMobileSearchBar: (hasMobileSearchBar: boolean) => void;
27
+ };
28
+
29
+ type HeaderProviderProps = {
30
+ children: React.ReactNode;
31
+ hasIcons: boolean;
32
+ hasNavItems: boolean;
33
+ hasBadge: boolean;
34
+ hasSearchBar: boolean;
35
+ hasMobileIcons: boolean;
36
+ hasMobileNavItems: boolean;
37
+ hasMobileBadge: boolean;
38
+ hasMobileSearchBar: boolean;
39
+ iconsData: HeaderTypes["iconsData"];
40
+ mobileCloseIcon: JSX.Element | null;
41
+ };
42
+
43
+ const HeaderContext = createContext<ContextValue | undefined>(undefined);
44
+
45
+ export const HeaderProvider = ({
46
+ children,
47
+ hasIcons,
48
+ hasNavItems,
49
+ hasBadge,
50
+ hasSearchBar,
51
+ hasMobileIcons,
52
+ hasMobileNavItems,
53
+ hasMobileBadge,
54
+ hasMobileSearchBar,
55
+ iconsData,
56
+ mobileCloseIcon,
57
+ }: HeaderProviderProps) => {
58
+ const [hasIconsState, setHasIcons] = useState<boolean>(hasIcons);
59
+ const [hasNavItemsState, setHasNavItems] = useState<boolean>(hasNavItems);
60
+ const [hasBadgeState, setHasBadge] = useState<boolean>(hasBadge);
61
+ const [hasSearchBarState, setHasSearchBar] =
62
+ useState<boolean>(hasSearchBar);
63
+
64
+ const [hasMobileIconsState, setHasMobileIcons] =
65
+ useState<boolean>(hasMobileIcons);
66
+ const [hasMobileNavItemsState, setHasMobileNavItems] =
67
+ useState<boolean>(hasMobileNavItems);
68
+ const [hasMobileBadgeState, setHasMobileBadge] =
69
+ useState<boolean>(hasMobileBadge);
70
+ const [hasMobileSearchBarState, setHasMobileSearchBar] =
71
+ useState<boolean>(hasMobileSearchBar);
72
+ const [iconsDataState, setIconsData] =
73
+ useState<HeaderTypes["iconsData"]>(iconsData);
74
+
75
+ const [mobileCloseIconState, setMobileCloseIcon] =
76
+ useState<JSX.Element | null>(mobileCloseIcon);
77
+
78
+ return (
79
+ <HeaderContext.Provider
80
+ value={{
81
+ hasIcons: hasIconsState,
82
+ setHasIcons,
83
+
84
+ hasNavItems: hasNavItemsState,
85
+ setHasNavItems,
86
+
87
+ hasBadge: hasBadgeState,
88
+ setHasBadge,
89
+
90
+ hasSearchBar: hasSearchBarState,
91
+ setHasSearchBar,
92
+
93
+ hasMobileIcons: hasMobileIconsState,
94
+ setHasMobileIcons,
95
+
96
+ hasMobileNavItems: hasMobileNavItemsState,
97
+ setHasMobileNavItems,
98
+
99
+ hasMobileBadge: hasMobileBadgeState,
100
+ setHasMobileBadge,
101
+
102
+ hasMobileSearchBar: hasMobileSearchBarState,
103
+ setHasMobileSearchBar,
104
+
105
+ iconsData: iconsDataState,
106
+ setIconsData,
107
+ mobileCloseIcon: mobileCloseIconState,
108
+ setMobileCloseIcon,
109
+
110
+ }}
111
+ >
112
+ {children}
113
+ </HeaderContext.Provider>
114
+ );
115
+ };
116
+
117
+ export function useHeaderContext() {
118
+ const context = useContext(HeaderContext);
119
+ if (!context) {
120
+ throw new Error(
121
+ "useHeaderContext must be used within a HeaderProvider"
122
+ );
123
+ }
124
+ return context;
125
+ }
@@ -0,0 +1,2 @@
1
+ export { default } from "./Header";
2
+ export * from "./Header.types";
@@ -0,0 +1,69 @@
1
+ import React from "react";
2
+ import { Meta, StoryFn } from "@storybook/react";
3
+ import Hero, { HeroTypes } from ".";
4
+ import { withStoryBook } from "../../hoc";
5
+
6
+ interface HeroStoryTypes extends HeroTypes {
7
+ position: "left" | "right" | "center";
8
+ background: string;
9
+ text: React.ReactNode;
10
+ }
11
+
12
+ const StorybookHero = withStoryBook(Hero);
13
+
14
+ export default {
15
+ title: "Components/Hero",
16
+ argTypes: {
17
+ textAlignment: {
18
+ control: "select",
19
+ options: ["left", "right", "center"],
20
+ description:
21
+ "The position of the text in relation to the background horizontally.",
22
+ },
23
+ textVerticalAxis: {
24
+ control: "select",
25
+ options: ["items-start", "items-end", "items-center"],
26
+ description:
27
+ "The position of the text in relation to the background vertically.",
28
+ },
29
+ background: {
30
+ control: "color",
31
+ description:
32
+ "The background color. Set by Tailwind CSS in Applications",
33
+ },
34
+ text: {
35
+ control: "text",
36
+ description: "The text displayed.",
37
+ },
38
+ },
39
+ tags: ["autodocs"],
40
+ } as Meta<HeroStoryTypes>;
41
+
42
+ // const Template: StoryFn<HeroStoryProps> = (args) => <Hero {...args} />;
43
+
44
+ const Template: StoryFn<typeof StorybookHero> = (args) => (
45
+ <StorybookHero
46
+ {...args}
47
+ storybookStyle={{
48
+ backgroundColor: args.background,
49
+ }}
50
+ />
51
+ );
52
+
53
+ export const HeroColor = Template.bind({});
54
+ HeroColor.args = {
55
+ textAlignment: "right",
56
+ background: "color",
57
+ };
58
+
59
+ export const HeroGradient = Template.bind({});
60
+ HeroGradient.args = {
61
+ textAlignment: "right",
62
+ background: "gradient",
63
+ };
64
+
65
+ export const HeroDecorativeImage = Template.bind({});
66
+ HeroDecorativeImage.args = {
67
+ textAlignment: "right",
68
+ background: "image",
69
+ };
@@ -0,0 +1,109 @@
1
+ import "../../../dist/main.css";
2
+ import { render, screen } from "@testing-library/react";
3
+ import { describe, test, expect, beforeEach } from "vitest";
4
+
5
+ import Hero from "./Hero";
6
+ import Text from "../Text/Text";
7
+
8
+ describe("<Hero /> with color background", () => {
9
+ beforeEach(() => {
10
+ render(
11
+ <Hero
12
+ textAlignment="center"
13
+ background="color"
14
+ text={
15
+ <Text
16
+ size="xl"
17
+ color="primary"
18
+ fontFamily="serif"
19
+ text="This is a test heading!"
20
+ tag="h2"
21
+ />
22
+ }
23
+ />
24
+ );
25
+ });
26
+
27
+ test("renders Text component", () => {
28
+ expect(screen.getByTestId("hero")).toBeInTheDocument();
29
+ });
30
+
31
+ test("contains correct text from Text component", () => {
32
+ expect(screen.getByTestId("hero")).toHaveTextContent(
33
+ "This is a test heading!"
34
+ );
35
+ });
36
+ test("renders correct background color class", () => {
37
+ const heroElement = screen.getByTestId("hero");
38
+ expect(heroElement).toHaveClass("bg-blue-800");
39
+ });
40
+
41
+ test("renders correct position of Text component", () => {
42
+ const heroElement = screen.getByTestId("hero");
43
+ expect(heroElement).toHaveClass("justify-center");
44
+ });
45
+ test("renders Text component as correct heading type", () => {
46
+ const textComponent = screen.getByRole("heading", {
47
+ name: "This is a test heading!",
48
+ level: 2,
49
+ });
50
+ expect(textComponent).toBeInTheDocument();
51
+ expect(textComponent.tagName).toBe("H2");
52
+ });
53
+ });
54
+
55
+ describe("<Hero /> with Image background", () => {
56
+ beforeEach(() => {
57
+ render(
58
+ <Hero
59
+ textAlignment="center"
60
+ background="image"
61
+ text={
62
+ <Text
63
+ size="xl"
64
+ color="primary"
65
+ fontFamily="serif"
66
+ text="This is a test heading!"
67
+ tag="h1"
68
+ />
69
+ }
70
+ />
71
+ );
72
+ });
73
+
74
+ test("renders hero image component", () => {
75
+ expect(screen.getByTestId("image-background-hero")).toBeInTheDocument();
76
+ });
77
+
78
+ test("contains correct text from Text component", () => {
79
+ expect(screen.getByTestId("image-background-hero")).toHaveTextContent(
80
+ "This is a test heading!"
81
+ );
82
+ });
83
+
84
+ test("renders correct background image", () => {
85
+ const heroImageElement = screen.getByTestId("image-background-hero");
86
+ expect(heroImageElement.style.backgroundImage).toContain(
87
+ "heroImage.png"
88
+ );
89
+ });
90
+
91
+ // FIXME:
92
+ // test("renders correct background image alt text", () => {
93
+ // expect(screen.getByTestId("image-background-hero")).toHaveAttribute(
94
+ // "aria-label",
95
+ // ""
96
+ // );
97
+ // });
98
+
99
+ test("renders correct position of Text component", () => {
100
+ const heroElement = screen.getByTestId("image-background-hero");
101
+ expect(heroElement).toHaveClass("justify-center");
102
+ });
103
+
104
+ test("renders correct element type of Text component", () => {
105
+ expect(
106
+ screen.getByRole("heading", { name: "This is a test heading!" })
107
+ ).toBeInTheDocument();
108
+ });
109
+ });
@@ -0,0 +1,58 @@
1
+ import React from "react";
2
+ import Text from "../Text/Text";
3
+ import Image from "../Image/Image";
4
+ import { HeroTypes } from ".";
5
+
6
+ const alignmentClassesMap = {
7
+ left: "justify-start text-left",
8
+ right: "justify-end text-right",
9
+ center: "justify-center text-center",
10
+ };
11
+
12
+ const backgroundClassesMap: { [key: string]: string } = {
13
+ color: "bg-blue-800",
14
+ gradient: "bg-gradient-to-r from-cyan-700 to-blue-900",
15
+ };
16
+
17
+ const Hero: React.FC<HeroTypes> = ({
18
+ src = "../../../assets/heroImage.png",
19
+ text = (
20
+ <Text
21
+ size="xl"
22
+ color="white"
23
+ fontFamily="serif"
24
+ text="This is a test heading!"
25
+ tag="h1"
26
+ />
27
+ ),
28
+ textAlignment,
29
+ background = "color",
30
+ textVerticalAxis = "items-center",
31
+ }) => {
32
+ let heroAlignment = alignmentClassesMap[textAlignment];
33
+ const heroBackground = backgroundClassesMap[background] || "";
34
+
35
+ if (background === "image") {
36
+ heroAlignment = `flex ${alignmentClassesMap[textAlignment]} ${textVerticalAxis}`;
37
+ }
38
+
39
+ return background === "image" ? (
40
+ <Image
41
+ src={src}
42
+ alt=""
43
+ background={true}
44
+ additionalClasses={heroAlignment}
45
+ >
46
+ <span className="text-white">{text}</span>
47
+ </Image>
48
+ ) : (
49
+ <div
50
+ data-testid="hero"
51
+ className={`w-full min-h-72 p-4 flex ${heroAlignment} ${heroBackground} ${textVerticalAxis} text-white `}
52
+ >
53
+ {text}
54
+ </div>
55
+ );
56
+ };
57
+
58
+ export default Hero;
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+
3
+ export interface HeroTypes {
4
+ src?: string;
5
+ background?: string;
6
+ text?: React.ReactNode;
7
+ textAlignment: "left" | "right" | "center";
8
+ textVerticalAxis?: "items-start" | "items-end" | "items-center";
9
+ }
@@ -0,0 +1,2 @@
1
+ export { default } from "./Hero";
2
+ export * from "./Hero.types";
@@ -0,0 +1,227 @@
1
+ import { Meta, StoryFn } from "@storybook/react";
2
+ import Text from "../Text/Text";
3
+ import Icon from ".";
4
+ import { IconTypes } from ".";
5
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
6
+ import {
7
+ faUser,
8
+ faCircleInfo,
9
+ faBell,
10
+ faCartShopping,
11
+ faCircleQuestion,
12
+ } from "@fortawesome/free-solid-svg-icons";
13
+
14
+ export default {
15
+ title: "Components/Icon",
16
+ component: Icon,
17
+ argTypes: {
18
+ iconColor: {
19
+ control: "select",
20
+ options: ["blue", "green", "black"],
21
+ description: "The icon color.",
22
+ },
23
+ backgroundColor: {
24
+ control: "select",
25
+ options: ["blue", "green", "grey", "none"],
26
+ description: "The background color.",
27
+ },
28
+ size: {
29
+ control: "select",
30
+ options: ["sm", "md", "lg"],
31
+ description: "The icon size.",
32
+ },
33
+ iconBorder: {
34
+ control: "select",
35
+ options: ["border", "none"],
36
+ description: "Whether there is a border around the icon.",
37
+ },
38
+ hoverColor: {
39
+ control: "select",
40
+ options: ["green", "blue", "black"],
41
+ description: "The icon and text color on hover.",
42
+ },
43
+ hoverBackground: {
44
+ control: "select",
45
+ options: ["blue", "green", "grey", "none"],
46
+ description: "The background color of the icon on hover.",
47
+ },
48
+ hoverBorder: {
49
+ control: "select",
50
+ options: ["border", "none"],
51
+ description: "Whether there is a border around the icon on hover.",
52
+ },
53
+ limitIndicator: {
54
+ control: "boolean",
55
+ description:
56
+ "Whether the indicator number should be limited to 2 characters. If set to true and the number is greater than 99, the indicator will display '99+'.",
57
+ },
58
+ indicatorNumber: {
59
+ control: "text",
60
+ description:
61
+ "The value of notifications that is shown in the indicator. Note: if the indicator number is '' or '0', the indicator will not be displayed.",
62
+ },
63
+ indicatorSize: {
64
+ control: "select",
65
+ options: ["sm", "md", "lg"],
66
+ description:
67
+ "The indicator size displaying notifications. Note: if the indicator size is 'lg', it is recommended that the icon size is also set to 'lg'.",
68
+ },
69
+ iconLabel: {
70
+ table: {
71
+ disable: true,
72
+ },
73
+ },
74
+ onClick: {
75
+ table: {
76
+ disable: true,
77
+ },
78
+ },
79
+ to: {
80
+ table: {
81
+ disable: true,
82
+ },
83
+ },
84
+ text: {
85
+ control: "text",
86
+ description: "The text that is displayed below the icon.",
87
+ },
88
+ icon: {
89
+ table: {
90
+ disable: true,
91
+ },
92
+ },
93
+ href: {
94
+ table: {
95
+ disable: true,
96
+ },
97
+ },
98
+ additionalContainerClasses: {
99
+ table: {
100
+ disable: true,
101
+ },
102
+ },
103
+ limitCharacters: {
104
+ table: {
105
+ disable: true,
106
+ },
107
+ description:
108
+ "Pass a function to limit the number of characters in the text.",
109
+ },
110
+ },
111
+ tags: ["autodocs"],
112
+ parameters: {
113
+ // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
114
+ layout: "centered",
115
+ },
116
+ } as Meta;
117
+
118
+ const Template: StoryFn<IconTypes> = (args) => <Icon {...args} />;
119
+
120
+ export const Profile = Template.bind({});
121
+ Profile.args = {
122
+ iconColor: "green",
123
+ iconLabel: "Profile",
124
+ backgroundColor: "green",
125
+ size: "sm",
126
+ icon: <FontAwesomeIcon icon={faUser} />,
127
+ hoverBackground: "none",
128
+ hoverColor: "green",
129
+ indicatorNumber: "0",
130
+ text: (
131
+ <Text
132
+ size="md"
133
+ color="primary"
134
+ fontFamily="serif"
135
+ text="Profile"
136
+ tag="h2"
137
+ additionalClasses="p-0"
138
+ />
139
+ ),
140
+ onClick: () => alert("Redirect to profile"),
141
+ };
142
+
143
+ export const Support = Template.bind({});
144
+ Support.args = {
145
+ iconColor: "black",
146
+ iconLabel: "Support",
147
+ backgroundColor: "grey",
148
+ size: "sm",
149
+ icon: <FontAwesomeIcon icon={faCircleInfo} />,
150
+ hoverBackground: "none",
151
+ hoverColor: "blue",
152
+ indicatorNumber: "100",
153
+ limitIndicator: true,
154
+ indicatorSize: "lg",
155
+ text: (
156
+ <Text
157
+ size="md"
158
+ color="primary"
159
+ fontFamily="serif"
160
+ text="Support"
161
+ tag="h2"
162
+ additionalClasses="p-0"
163
+ />
164
+ ),
165
+ onClick: () => alert("Redirect to support"),
166
+ };
167
+
168
+ export const Messages = Template.bind({});
169
+ Messages.args = {
170
+ iconColor: "black",
171
+ iconLabel: "Messages",
172
+ backgroundColor: "grey",
173
+ size: "sm",
174
+ icon: <FontAwesomeIcon icon={faBell} />,
175
+ hoverBackground: "none",
176
+ hoverColor: "blue",
177
+ indicatorNumber: "12",
178
+ indicatorSize: "sm",
179
+ text: (
180
+ <Text
181
+ size="md"
182
+ color="primary"
183
+ fontFamily="serif"
184
+ text="Messages"
185
+ tag="h2"
186
+ additionalClasses="p-0"
187
+ />
188
+ ),
189
+ onClick: () => alert("Redirect to messages"),
190
+ };
191
+
192
+ export const Cart = Template.bind({});
193
+ Cart.args = {
194
+ iconColor: "blue",
195
+ iconLabel: "Cart",
196
+ size: "lg",
197
+ icon: <FontAwesomeIcon icon={faCartShopping} />,
198
+ hoverBackground: "blue",
199
+ hoverColor: "none",
200
+ indicatorNumber: "",
201
+ indicatorSize: "lg",
202
+ text: (
203
+ <Text
204
+ size="md"
205
+ color="primary"
206
+ fontFamily="serif"
207
+ text="Cart"
208
+ tag="h2"
209
+ additionalClasses="p-0"
210
+ />
211
+ ),
212
+ onClick: () => alert("Redirect to cart"),
213
+ };
214
+
215
+ export const NoText = Template.bind({});
216
+ NoText.args = {
217
+ iconColor: "blue",
218
+ iconLabel: "Question",
219
+ backgroundColor: "grey",
220
+ size: "lg",
221
+ icon: <FontAwesomeIcon icon={faCircleQuestion} />,
222
+ hoverBackground: "grey",
223
+ hoverColor: "black",
224
+ iconBorder: "border",
225
+ indicatorNumber: "100",
226
+ onClick: () => alert("Redirect to question page"),
227
+ };
@@ -0,0 +1,53 @@
1
+ import { render, screen } from "@testing-library/react";
2
+ import { describe, expect, beforeEach, test } from "vitest";
3
+ import Icon from "./Icon";
4
+ import Text from "../Text/Text";
5
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
6
+ import { faUser } from "@fortawesome/free-solid-svg-icons";
7
+
8
+ describe("<Icon /> Profile", () => {
9
+ beforeEach(() => {
10
+ render(
11
+ <Icon
12
+ iconLabel="Profile"
13
+ iconColor="green"
14
+ size="sm"
15
+ icon={<FontAwesomeIcon icon={faUser} />}
16
+ hoverBackground="none"
17
+ hoverColor="green"
18
+ text={
19
+ <Text
20
+ size="md"
21
+ color="green"
22
+ fontFamily="serif"
23
+ text="Profile"
24
+ tag="h2"
25
+ />
26
+ }
27
+ />
28
+ );
29
+ });
30
+
31
+ test("renders correctly", () => {
32
+ expect(screen.getByTestId("icon")).toBeInTheDocument();
33
+ });
34
+
35
+ test("has correct text", () => {
36
+ expect(screen.getByTestId("text")).toHaveTextContent("Profile");
37
+ });
38
+
39
+ test("has correct icon", () => {
40
+ expect(screen.getByTestId("user")).toBeInTheDocument();
41
+ });
42
+
43
+ // The following style-based tests may need to be adapted depending on how styles are applied in your test environment
44
+ test("has correct color", () => {
45
+ const iconElement = screen.getByTestId("icon");
46
+ expect(iconElement).toHaveClass("text-teal-800");
47
+ });
48
+
49
+ test("has correct icon size", () => {
50
+ const iconElement = screen.getByTestId("user");
51
+ expect(iconElement).toHaveClass("text-md");
52
+ });
53
+ });