@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,90 @@
1
+ import "../../../dist/main.css";
2
+ import { render, screen } from "@testing-library/react";
3
+ import { describe, test, expect, beforeEach } from "vitest";
4
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
5
+ import { faCircleArrowRight } from "@fortawesome/free-solid-svg-icons";
6
+ import Input from "./Input";
7
+ import Text from "../Text/Text";
8
+ import FormButton from "../FormButton/FormButton";
9
+
10
+ describe("<Input /> with all props", () => {
11
+ beforeEach(() => {
12
+ render(
13
+ <Input
14
+ hasValidation={false}
15
+ // LABEL
16
+ label={
17
+ <Text
18
+ size="md"
19
+ color="primary"
20
+ fontFamily="serif"
21
+ text="Search for items"
22
+ tag="h2"
23
+ additionalClasses="mb-0 pb-2 pl-2"
24
+ />
25
+ }
26
+ labelVisible={true}
27
+ labelPlacement="left"
28
+ // INPUT DETAILS
29
+ inputName="search"
30
+ inputType="text"
31
+ // PLACEHOLDER
32
+ hasPlaceholder={true}
33
+ placeholder="Search for items"
34
+ // ICONS
35
+ hasLeftIcon={false}
36
+ hasRightIcon={false}
37
+ iconColor="black"
38
+ // INPUT STYLES
39
+ inputTextSize="medium"
40
+ inputShape="cornered"
41
+ borderColor="green"
42
+ backgroundColor="none"
43
+ inputWidth="w-96"
44
+ // BUTTON
45
+ hasButton={true}
46
+ button={
47
+ <FormButton
48
+ text="Submit"
49
+ as="button"
50
+ hoverBackground="green"
51
+ color="green"
52
+ icon={<FontAwesomeIcon icon={faCircleArrowRight} />}
53
+ fontColor="white"
54
+ additionalClasses="items-center px-4"
55
+ borderColor="green"
56
+ hoverFontColor="black"
57
+ shape="cornered"
58
+ />
59
+ }
60
+ />
61
+ );
62
+ });
63
+
64
+ test("renders Input component", () => {
65
+ expect(screen.getByTestId("input-container")).toBeInTheDocument();
66
+ expect(screen.getByTestId("input-element")).toBeInTheDocument();
67
+ });
68
+
69
+ test("renders correct Input label", () => {
70
+ expect(screen.getByTestId("input-label")).toBeInTheDocument();
71
+ expect(screen.getByTestId("input-label")).toHaveTextContent(
72
+ "Search for items"
73
+ );
74
+ });
75
+
76
+ test("renders correct button", () => {
77
+ expect(screen.getByTestId("submit-button")).toBeInTheDocument();
78
+ expect(screen.getByTestId("submit-button")).toHaveTextContent("Submit");
79
+ });
80
+
81
+ test("contains correct placeholder text", () => {
82
+ const input = screen.getByTestId("input-element");
83
+ expect(input).toHaveAttribute("placeholder", "Search for items");
84
+ });
85
+
86
+ test("renders correct border color class", () => {
87
+ const inputElement = screen.getByTestId("input-element");
88
+ expect(inputElement).toHaveClass("border-teal-500");
89
+ });
90
+ });
@@ -0,0 +1,226 @@
1
+ import React, { useState } from "react";
2
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
3
+ import { faCircleArrowRight } from "@fortawesome/free-solid-svg-icons";
4
+ import FormButton from "../FormButton/FormButton";
5
+ import { InputTypes } from ".";
6
+ import { validateInput } from "../../utils/inputValidation";
7
+
8
+ import {
9
+ getInputBorderClassNames,
10
+ getInputPaddingClassNames,
11
+ getInputBackgroundClassNames,
12
+ getInputTextClasses,
13
+ getInputShape,
14
+ getLabelPlacement,
15
+ getLabelVisibility,
16
+ getSuccessColorClasses,
17
+ getErrorColorClasses,
18
+ getIconClasses,
19
+ inputButtonWithClasses,
20
+ } from "./inputClassNames";
21
+
22
+ const Input: React.FC<InputTypes> = ({
23
+ // FUNCTIONALITY
24
+ hasValidation = false,
25
+ errorMessage,
26
+ regex,
27
+ setControlledState,
28
+ controlledState,
29
+ // LABEL
30
+ label,
31
+ labelVisible = true,
32
+ labelPlacement,
33
+
34
+ // INPUT DETAILS
35
+ inputName,
36
+ inputType,
37
+
38
+ // PLACEHOLDER
39
+ hasPlaceholder = true,
40
+ placeholder,
41
+
42
+ // ICONS
43
+ hasLeftIcon,
44
+ hasRightIcon,
45
+ leftIcon,
46
+ rightIcon,
47
+ iconColor,
48
+ iconBackgroundColor,
49
+
50
+ // INPUT STYLES
51
+ inputTextSize,
52
+ inputShape,
53
+ borderColor = "primary",
54
+ backgroundColor,
55
+ inputWidth,
56
+ errorBorder,
57
+ successBorder,
58
+
59
+ // BUTTON
60
+ hasButton,
61
+ button = (
62
+ <FormButton
63
+ text="Submit"
64
+ as="button"
65
+ hoverBackground="green"
66
+ color="red"
67
+ icon={<FontAwesomeIcon icon={faCircleArrowRight} />}
68
+ fontColor="white"
69
+ borderColor="green"
70
+ hoverFontColor="black"
71
+ shape="cornered"
72
+ additionalClasses="h-full"
73
+ />
74
+ ),
75
+ }) => {
76
+ const [isValid, setIsValid] = useState<string>("");
77
+ const [termInternal, setTermInternal] = useState<string>("");
78
+ const [inputBorderClasses, setInputBorderClasses] = useState<string>(
79
+ getInputBorderClassNames(borderColor)
80
+ );
81
+
82
+ let iconClasses = getIconClasses(
83
+ iconColor,
84
+ iconBackgroundColor,
85
+ inputShape
86
+ );
87
+
88
+ let errorColor = getErrorColorClasses(errorBorder);
89
+ let successColor = getSuccessColorClasses(successBorder);
90
+ let inputPaddingClasses = getInputPaddingClassNames(
91
+ hasButton,
92
+ hasLeftIcon,
93
+ hasRightIcon
94
+ );
95
+ let inputBackgroundClasses = getInputBackgroundClassNames(backgroundColor);
96
+ let inputShapeClasses = getInputShape(inputShape);
97
+ let inputWithButtonClasses = inputButtonWithClasses(inputShape);
98
+ let labelVisibility = getLabelVisibility(labelVisible);
99
+ let labelPlacementClasses = getLabelPlacement(labelPlacement);
100
+ let inputTextClasses = getInputTextClasses(inputTextSize);
101
+ let inputBorderColor = getInputBorderClassNames(borderColor);
102
+ const inputValue = termInternal || controlledState || "";
103
+ const setTerm = setControlledState || setTermInternal;
104
+
105
+ const handleBorderStyles = () => {
106
+ if (isValid !== "Success" && isValid !== "") {
107
+ setInputBorderClasses(errorColor);
108
+ } else if (isValid === "Success") {
109
+ setInputBorderClasses(successColor);
110
+ } else if (isValid === "") {
111
+ setInputBorderClasses(getInputBorderClassNames(borderColor));
112
+ }
113
+ };
114
+
115
+ const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
116
+ setTerm(e.target.value);
117
+
118
+ if (hasValidation) {
119
+ let validation =
120
+ validateInput &&
121
+ regex &&
122
+ errorMessage &&
123
+ validateInput(inputValue, regex, errorMessage);
124
+ setIsValid(validation || "");
125
+ handleBorderStyles();
126
+ }
127
+ };
128
+
129
+ return (
130
+ <div
131
+ className={`${labelPlacementClasses} w-full`}
132
+ data-testid="input-container"
133
+ >
134
+ <label
135
+ htmlFor={`pb-1 pl-1 ${inputName}`}
136
+ className={`${labelVisibility}`}
137
+ data-testid="input-label"
138
+ >
139
+ {label}
140
+ </label>
141
+ {hasButton ? (
142
+ <div className={`relative ${inputWidth} flex`}>
143
+ <div className="flex-1">
144
+ {hasLeftIcon && (
145
+ <div
146
+ className={`absolute bottom-1 flex items-center justify-center size-10 pointer-events-none ${iconClasses} `}
147
+ >
148
+ {leftIcon}
149
+ </div>
150
+ )}
151
+ <input
152
+ type={inputType}
153
+ placeholder={
154
+ hasPlaceholder ? placeholder : undefined
155
+ }
156
+ name={inputName}
157
+ id={inputName}
158
+ onChange={handleChange}
159
+ value={inputValue}
160
+ data-testid="input-element"
161
+ className={`block w-full border-2 p-2 ${inputTextClasses} ${inputWithButtonClasses} ${inputBackgroundClasses} ${inputPaddingClasses} ${
162
+ !hasValidation
163
+ ? inputBorderColor
164
+ : inputBorderClasses
165
+ }`}
166
+ />
167
+ </div>
168
+
169
+ <div>
170
+ {hasButton && (
171
+ <div
172
+ className={`${inputShape} flex items-center justify-center h-full`}
173
+ data-testid="submit-button"
174
+ >
175
+ <div className="h-full bg-red-500">
176
+ {button}
177
+ </div>
178
+ </div>
179
+ )}
180
+ </div>
181
+ </div>
182
+ ) : (
183
+ <div className={`relative ${inputWidth} flex`}>
184
+ {hasLeftIcon && (
185
+ <div
186
+ className={`absolute top-[1px] flex items-center justify-center size-10 pointer-events-none ${iconClasses} `}
187
+ >
188
+ {leftIcon}
189
+ </div>
190
+ )}
191
+ <input
192
+ type={inputType}
193
+ placeholder={hasPlaceholder ? placeholder : undefined}
194
+ name={inputName}
195
+ id={inputName}
196
+ onChange={handleChange}
197
+ value={inputValue}
198
+ data-testid="input-element"
199
+ className={`block w-full border-2 ${inputTextClasses} ${inputShapeClasses} ${inputBackgroundClasses} ${inputPaddingClasses} ${
200
+ !hasValidation
201
+ ? inputBorderColor
202
+ : inputBorderClasses
203
+ }`}
204
+ />
205
+ {hasRightIcon && (
206
+ <div
207
+ className={`absolute end-1 flex items-center justify-center size-10 pointer-events-none ${iconClasses}`}
208
+ >
209
+ {rightIcon}
210
+ </div>
211
+ )}
212
+ {hasButton && (
213
+ <div
214
+ className={`${inputShape} flex items-center inset-y-0 end-1.5`}
215
+ data-testid="submit-button"
216
+ >
217
+ {button}
218
+ </div>
219
+ )}
220
+ </div>
221
+ )}
222
+ </div>
223
+ );
224
+ };
225
+ Input.displayName = "Memo(Input)";
226
+ export default Input;
@@ -0,0 +1,52 @@
1
+ import React from "react";
2
+
3
+ export interface InputTypes {
4
+ // FUNCTIONALITY
5
+ onChange?: (
6
+ e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>
7
+ ) => void;
8
+ value?: string;
9
+ hasValidation?: boolean;
10
+ validateInput?: (inputValue: string | number, inputType: string) => string;
11
+ hasErrorMessage?: boolean;
12
+ errorMessage?: string;
13
+ regex?: RegExp;
14
+ setControlledState?: (value: string) => void;
15
+ controlledState?: string;
16
+ // LABEL
17
+ labelVisible: boolean;
18
+ label: React.ReactNode; // text that is displayed as the label, required bc it's either shown or only shown to screen readers
19
+ labelPlacement?: "top" | "left";
20
+ // INPUT DETAILS
21
+ inputType: string;
22
+ inputName: string; // required bc connects the label to the input
23
+ // PLACEHOLDER
24
+ hasPlaceholder: boolean;
25
+ placeholder: string;
26
+ // ICONS
27
+ hasLeftIcon?: boolean;
28
+ hasRightIcon?: boolean;
29
+ leftIcon?: React.ReactNode;
30
+ rightIcon?: React.ReactNode;
31
+ iconColor?: "green" | "blue" | "black" | string;
32
+ iconBackgroundColor?:
33
+ | "green"
34
+ | "white"
35
+ | "blue"
36
+ | "green"
37
+ | "none"
38
+ | string;
39
+ // INPUT STYLE
40
+ inputTextSize?: "small" | "medium" | "large" | string;
41
+ inputWidth?: string;
42
+ inputShape?: "cornered" | "semiRounded" | "rounded" | string;
43
+ borderColor?: "green" | "blue" | "grey" | "black" | "none" | string;
44
+ backgroundColor?: "white" | "blue" | "green" | "none" | string;
45
+ additionalClasses?: string | undefined;
46
+ errorBorder?: "red" | "orange" | string;
47
+ successBorder?: "green" | "blue" | "grey" | "black" | string;
48
+ // BUTTON
49
+ hasButton?: boolean;
50
+ button?: React.ReactNode;
51
+ onButtonClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
52
+ }
@@ -0,0 +1,32 @@
1
+ import { InputTypes } from ".";
2
+
3
+ export const arePropsEqual = (prevProps: InputTypes, nextProps: InputTypes) => {
4
+ return (
5
+ prevProps.hasValidation === nextProps.hasValidation &&
6
+ prevProps.errorMessage === nextProps.errorMessage &&
7
+ prevProps.regex === nextProps.regex &&
8
+ prevProps.label === nextProps.label &&
9
+ prevProps.labelVisible === nextProps.labelVisible &&
10
+ prevProps.labelPlacement === nextProps.labelPlacement &&
11
+ prevProps.inputName === nextProps.inputName &&
12
+ prevProps.inputType === nextProps.inputType &&
13
+ prevProps.hasPlaceholder === nextProps.hasPlaceholder &&
14
+ prevProps.placeholder === nextProps.placeholder &&
15
+ prevProps.hasLeftIcon === nextProps.hasLeftIcon &&
16
+ prevProps.hasRightIcon === nextProps.hasRightIcon &&
17
+ prevProps.leftIcon === nextProps.leftIcon &&
18
+ prevProps.rightIcon === nextProps.rightIcon &&
19
+ prevProps.iconColor === nextProps.iconColor &&
20
+ prevProps.iconBackgroundColor === nextProps.iconBackgroundColor &&
21
+ prevProps.inputTextSize === nextProps.inputTextSize &&
22
+ prevProps.inputShape === nextProps.inputShape &&
23
+ prevProps.borderColor === nextProps.borderColor &&
24
+ prevProps.backgroundColor === nextProps.backgroundColor &&
25
+ prevProps.inputWidth === nextProps.inputWidth &&
26
+ prevProps.errorBorder === nextProps.errorBorder &&
27
+ prevProps.successBorder === nextProps.successBorder &&
28
+ prevProps.additionalClasses === nextProps.additionalClasses &&
29
+ prevProps.hasButton === nextProps.hasButton &&
30
+ prevProps.button === nextProps.button
31
+ );
32
+ };
@@ -0,0 +1,2 @@
1
+ export { default as Input } from "./Input";
2
+ export * from "./Input.types";
@@ -0,0 +1,169 @@
1
+ import classNames from "classNames";
2
+
3
+ // edits the input container border color & focus outline color
4
+ export const getInputBorderClassNames = (borderColor: string | undefined) =>
5
+ classNames({
6
+ "border-teal-500 focus-within:outline-teal-500 focus-within:outline focus-within:outline-2 focus-within:outline-offset-1":
7
+ borderColor === "green",
8
+ "border-blue-500 focus-within:outline-blue-500 focus-within:outline focus-within:outline-2 focus-within:outline-offset-1":
9
+ borderColor === "blue",
10
+ "border-slate-400 focus-within:outline-slate-400 focus-within:outline focus-within:outline-2 focus-within:outline-offset-1":
11
+ borderColor === "grey",
12
+ "border-black focus-within:outline-black focus-within:outline focus-within:outline-2 focus-within:outline-offset-1":
13
+ borderColor === "black",
14
+ "border-transparent focus-within:outline-transparent focus-within:outline focus-within:outline-2 focus-within:outline-offset-1":
15
+ borderColor === "none",
16
+ [`border-${borderColor} focus-within:outline-${borderColor} focus-within:outline focus-within:outline-2 focus-within:outline-offset-1`]:
17
+ borderColor !== undefined,
18
+ });
19
+
20
+ export const getSuccessColorClasses = (successBorder: string | undefined) =>
21
+ classNames({
22
+ "focus-within:outline-green-500 border-green-500 focus-within:outline focus-within:outline-2 focus-within:outline-offset-1":
23
+ successBorder === "green",
24
+ "focus-within:outline-blue-500 border-blue-500 focus-within:outline focus-within:outline-2 focus-within:outline-offset-1":
25
+ successBorder === "blue",
26
+ "focus-within:outline-grey-500 border-grey-500 focus-within:outline focus-within:outline-2 focus-within:outline-offset-1":
27
+ successBorder === "grey",
28
+ "focus-within:outline-black border-black focus-within:outline focus-within:outline-2 focus-within:outline-offset-1":
29
+ successBorder === "black",
30
+ [`focus-within:outline-${successBorder} border-${successBorder} focus-within:outline focus-within:outline-2 focus-within:outline-offset-1`]:
31
+ successBorder !== undefined,
32
+ });
33
+
34
+ export const getErrorColorClasses = (errorBorder: string | undefined) =>
35
+ classNames({
36
+ "focus-within:outline-red-500 border-red-500 focus-within:outline focus-within:outline-2 focus-within:outline-offset-1":
37
+ errorBorder === "red",
38
+ "focus-within:outline-orange-500 border-orange-500 focus-within:outline focus-within:outline-2 focus-within:outline-offset-1":
39
+ errorBorder === "orange",
40
+ "focus-within:outline-black border-black focus-within:outline focus-within:outline-2 focus-within:outline-offset-1":
41
+ errorBorder === "black",
42
+ [`focus-within:outline-${errorBorder} border-${errorBorder} focus-within:outline focus-within:outline-2 focus-within:outline-offset-1`]:
43
+ errorBorder !== undefined,
44
+ });
45
+
46
+ export const getInputPaddingClassNames = (
47
+ hasButton: boolean | undefined,
48
+ hasLeftIcon: boolean | undefined,
49
+ hasRightIcon: boolean | undefined
50
+ ) =>
51
+ classNames({
52
+ // NO ICONS OR BUTTON
53
+ "py-2 px-3":
54
+ hasButton === false &&
55
+ hasLeftIcon === false &&
56
+ hasRightIcon === false,
57
+
58
+ // LEFT ICON AND BUTTON
59
+ "py-3 pl-14":
60
+ hasButton === true &&
61
+ hasLeftIcon === true &&
62
+ hasRightIcon === false,
63
+
64
+ // BUTTON ONLY
65
+ "py-3 px-3":
66
+ hasButton === true &&
67
+ hasLeftIcon === false &&
68
+ hasRightIcon === false,
69
+
70
+ // LEFT ICON ONLY
71
+ "pl-12 py-2":
72
+ hasLeftIcon === true &&
73
+ hasRightIcon === false &&
74
+ hasButton === false,
75
+
76
+ // RIGHT ICON ONLY
77
+ "pr-10 py-2 pl-3":
78
+ hasRightIcon === true &&
79
+ hasLeftIcon === false &&
80
+ hasButton === false,
81
+
82
+ // DUAL ICONS ONLY
83
+ "py-2 pl-12":
84
+ hasRightIcon === true &&
85
+ hasLeftIcon === true &&
86
+ hasButton === false,
87
+ });
88
+
89
+ // edits the background color of the input element
90
+ export const getInputBackgroundClassNames = (
91
+ backgroundColor: string | undefined
92
+ ) =>
93
+ classNames({
94
+ "bg-white": backgroundColor === "white",
95
+ "bg-blue-100": backgroundColor === "blue",
96
+ "bg-slate-100": backgroundColor === "grey",
97
+ "bg-transparent": backgroundColor === "none",
98
+ [`bg-${backgroundColor}`]: backgroundColor !== undefined,
99
+ });
100
+
101
+ // edits text styles of the input element
102
+ export const getInputTextClasses = (inputTextSize: string | undefined) => {
103
+ return classNames({
104
+ "text-sm": inputTextSize === "small",
105
+ "text-md": inputTextSize === "medium",
106
+ "text-lg": inputTextSize === "large",
107
+ [`text-${inputTextSize}`]: inputTextSize !== undefined,
108
+ });
109
+ };
110
+
111
+ // manages the border radius of the input
112
+ export const getInputShape = (inputShape: string | undefined) =>
113
+ classNames({
114
+ "rounded-none": inputShape === "cornered",
115
+ "rounded-md": inputShape === "semiRounded",
116
+ "rounded-full": inputShape === "rounded",
117
+ });
118
+
119
+ // manages the border radius of the input when the input has a button with it
120
+ export const inputButtonWithClasses = (inputShape: string | undefined) =>
121
+ classNames({
122
+ "rounded-tl-none rounded-bl-none": true,
123
+ "rounded-tr-none rounded-br-none": inputShape === "cornered",
124
+ "rounded-tr-md rounded-br-md": inputShape === "semiRounded",
125
+ "rounded-tr-full rounded-br-full": inputShape === "rounded",
126
+ });
127
+
128
+ // manages the placement of the label
129
+ export const getLabelPlacement = (labelPlacement: string | undefined) =>
130
+ classNames({
131
+ "flex items-center pr-3": labelPlacement === "left",
132
+ "": labelPlacement === "top",
133
+ });
134
+
135
+ // toggles whether label is visible or not
136
+ export const getLabelVisibility = (labelVisible: boolean | undefined) =>
137
+ classNames({
138
+ "sr-only": labelVisible === false,
139
+ "": labelVisible === true,
140
+ });
141
+
142
+ export const getIconClasses = (
143
+ iconColor: string | undefined,
144
+ iconBackgroundColor: string | undefined,
145
+ inputShape: string | undefined
146
+ ) => {
147
+ return classNames(
148
+ {
149
+ "text-blue-500": iconColor === "blue",
150
+ "text-teal-500": iconColor === "green",
151
+ "text-black": iconColor === "black",
152
+ "text-white": iconColor === "white",
153
+ [`text-${iconColor}`]: iconColor !== undefined,
154
+ },
155
+ {
156
+ "bg-blue-200": iconBackgroundColor === "blue",
157
+ "bg-slate-200": iconBackgroundColor === "grey",
158
+ "bg-teal-100": iconBackgroundColor === "green",
159
+ "bg-black": iconBackgroundColor === "black",
160
+ "bg-transparent": iconBackgroundColor === "none",
161
+ [`bg-${iconBackgroundColor}`]: iconBackgroundColor !== undefined,
162
+ },
163
+ {
164
+ "rounded-none": inputShape === "cornered",
165
+ "rounded-md": inputShape === "semiRounded",
166
+ "rounded-full": inputShape === "rounded",
167
+ }
168
+ );
169
+ };
@@ -0,0 +1,41 @@
1
+
2
+ import { MobileMenuTypes } from "./MobileMenu.types";
3
+ import { useHeaderContext } from "../Header/headerContext";
4
+
5
+ const MobileMenu: React.FC<MobileMenuTypes> = ({
6
+ badge,
7
+ nav,
8
+ input,
9
+ icons,
10
+ mobileMenuClasses,
11
+ }) => {
12
+ const {
13
+ hasMobileIcons,
14
+ hasMobileNavItems,
15
+ hasMobileBadge,
16
+ hasMobileSearchBar,
17
+ } = useHeaderContext();
18
+
19
+ return (
20
+ <nav
21
+ data-testid="secondary-nav"
22
+ aria-label="Secondary navigation"
23
+ className={`flex flex-col justify-start z-[1000] top-0 w-full h-full pt-16 pb-12 px-4 overflow-scroll ${mobileMenuClasses}`}
24
+ >
25
+ {hasMobileNavItems && <div className="mb-12">{nav}</div>}
26
+ {hasMobileBadge && (
27
+ <div className="flex w-1/2 mb-12 mx-auto">{badge}</div>
28
+ )}
29
+ {hasMobileIcons && icons && (
30
+ <div className="flex justify-around w-full mb-12">{icons}</div>
31
+ )}
32
+ {hasMobileSearchBar && (
33
+ <div className="flex w-full [&:has(:focus-visible)]:ring-2">
34
+ {input}
35
+ </div>
36
+ )}
37
+ </nav>
38
+ );
39
+ };
40
+
41
+ export default MobileMenu;
@@ -0,0 +1,30 @@
1
+ import { DUMMYICONCOMPASSDATA, DUMMYICONTOGADATA } from "../Header/DUMMYICONDATA.json";
2
+ import { TagName } from "../Text";
3
+
4
+
5
+ export interface MobileMenuTypes {
6
+ onClick?: (
7
+ e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>
8
+ ) => void;
9
+ handleNav?: () => void;
10
+ hasSearchBar?: boolean;
11
+ hasNavItems?: boolean;
12
+ hasBadge?: boolean;
13
+ hasIcons?: boolean;
14
+
15
+ hasMobileIcons?: boolean;
16
+ hasMobileNavItems?: boolean;
17
+ hasMobileBadge?: boolean;
18
+ hasMobileSearchBar?: boolean;
19
+ mobileMenuClasses?: string;
20
+
21
+ hasGlass?: boolean;
22
+ backgroundColor?: string;
23
+
24
+ nav?: React.ReactNode;
25
+ badge?: React.ReactNode;
26
+ input?: React.ReactNode;
27
+ icons?: React.ReactNode;
28
+
29
+ mobileCloseIcon?: JSX.Element | undefined | null;
30
+ }
@@ -0,0 +1,2 @@
1
+ export { default } from "./MobileMenu";
2
+ export * from "./MobileMenu.types";