@nuskin/foundation-ui-components 1.0.0-cft-35.13 → 1.0.0-develop.10

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 (247) hide show
  1. package/package.json +21 -11
  2. package/src/common/accordion/NsAccordion.tsx +69 -0
  3. package/src/common/accordion/NsAccordionHeader.tsx +77 -0
  4. package/src/common/accordion/NsAccordionItem.tsx +59 -0
  5. package/src/common/accordion/NsCollapse.tsx +110 -0
  6. package/src/common/accordion/NsToggleSection.tsx +43 -0
  7. package/src/common/accordion/ToggleSection.styled.tsx +32 -0
  8. package/src/common/accordion/colorMap.ts +117 -0
  9. package/src/common/accordion/enums.ts +8 -0
  10. package/src/common/accordion/index.ts +7 -0
  11. package/src/common/accordion/specs/NsAccordion.spec.tsx +163 -0
  12. package/src/common/accordion/specs/NsAccordionHeader.spec.tsx +130 -0
  13. package/src/common/accordion/specs/NsAccordionItem.spec.tsx +79 -0
  14. package/src/common/accordion/specs/NsCollapse.spec.tsx +129 -0
  15. package/src/common/accordion/specs/NsToggleSection.spec.tsx +74 -0
  16. package/src/common/accordion/stories/NsAccordion.stories.tsx +65 -0
  17. package/src/common/accordion/stories/NsAccordionHeader.stories.tsx +44 -0
  18. package/src/common/accordion/stories/NsAccordionItem.stories.tsx +45 -0
  19. package/src/common/accordion/stories/NsCollapse.stories.tsx +50 -0
  20. package/src/common/accordion/stories/NsToggleSection.stories.tsx +26 -0
  21. package/src/common/accordion/stories/data.tsx +143 -0
  22. package/src/common/accordion/types.d.ts +81 -0
  23. package/src/common/alert/Header.tsx +29 -0
  24. package/src/common/alert/NsAlert.spec.tsx +62 -29
  25. package/src/common/alert/NsAlert.stories.tsx +18 -17
  26. package/src/common/alert/NsAlert.styled.tsx +124 -0
  27. package/src/common/alert/NsAlert.tsx +27 -110
  28. package/src/common/alert/index.ts +2 -2
  29. package/src/common/alert/types.d.ts +23 -23
  30. package/src/common/auth-dropdown/NsAuthDropdown.spec.tsx +24 -6
  31. package/src/common/auth-dropdown/NsAuthDropdown.stories.tsx +2 -2
  32. package/src/common/auth-dropdown/NsAuthDropdown.styled.ts +21 -16
  33. package/src/common/auth-dropdown/NsAuthDropdown.tsx +7 -6
  34. package/src/common/auth-dropdown/index.ts +1 -1
  35. package/src/common/auth-dropdown/types.d.ts +3 -1
  36. package/src/common/autocomplete/NsAutocomplete.spec.tsx +69 -24
  37. package/src/common/autocomplete/NsAutocomplete.stories.tsx +64 -7
  38. package/src/common/autocomplete/NsAutocomplete.styled.tsx +12 -0
  39. package/src/common/autocomplete/NsAutocomplete.tsx +100 -46
  40. package/src/common/autocomplete/index.ts +2 -1
  41. package/src/common/autocomplete/mock/MockData.ts +50 -7
  42. package/src/common/autocomplete/mock/MockUI.tsx +2 -1
  43. package/src/common/autocomplete/{types.ts → types.d.ts} +18 -8
  44. package/src/common/banner/NsBanner.spec.tsx +13 -4
  45. package/src/common/banner/NsBanner.stories.tsx +2 -2
  46. package/src/common/banner/NsBanner.styled.tsx +1 -1
  47. package/src/common/banner/NsBanner.tsx +1 -1
  48. package/src/common/banner/index.ts +1 -1
  49. package/src/common/brand-components/NsBrand.stories.tsx +2 -2
  50. package/src/common/brand-components/NsBrandComponent.tsx +6 -3
  51. package/src/common/brand-components/index.ts +1 -1
  52. package/src/common/breadcrumb/NsBreadcrumb.spec.tsx +8 -9
  53. package/src/common/breadcrumb/NsBreadcrumb.stories.tsx +3 -5
  54. package/src/common/breadcrumb/NsBreadcrumb.tsx +5 -3
  55. package/src/common/breadcrumb/data.ts +10 -0
  56. package/src/common/breadcrumb/index.ts +1 -1
  57. package/src/common/button/NsButton.spec.tsx +66 -51
  58. package/src/common/button/NsButton.stories.tsx +61 -4
  59. package/src/common/button/NsButton.styled.tsx +54 -72
  60. package/src/common/button/NsButton.tsx +9 -3
  61. package/src/common/button/helper.ts +82 -0
  62. package/src/common/button/index.ts +1 -1
  63. package/src/common/button/types.d.ts +3 -0
  64. package/src/common/card/NsFfgCard.tsx +14 -8
  65. package/src/common/card/specs/NsFfgCard.spec.tsx +33 -0
  66. package/src/common/card/stories/NsBgCard.stories.tsx +2 -4
  67. package/src/common/card/stories/NsBrandProductCard.stories.tsx +2 -2
  68. package/src/common/card/stories/NsFfgCard.stories.tsx +49 -16
  69. package/src/common/card/stories/{data.js → data.ts} +1 -25
  70. package/src/common/card/styled/NsFfgStyled.tsx +9 -7
  71. package/src/common/card/types.d.ts +7 -4
  72. package/src/common/carousal/NsScrollingCarousal.tsx +61 -0
  73. package/src/common/carousal/index.ts +3 -0
  74. package/src/common/carousal/{tests → specs}/NsCarousal.spec.tsx +2 -2
  75. package/src/common/carousal/specs/NsScrollingCarousal.spec.tsx +61 -0
  76. package/src/common/carousal/stories/NSCarousal.stories.tsx +2 -2
  77. package/src/common/carousal/stories/NsScrollingCarousal.stories.tsx +52 -0
  78. package/src/common/carousal/types.d.ts +23 -0
  79. package/src/common/cart-icon/NsCartIcon.spec.tsx +1 -1
  80. package/src/common/cart-icon/NsCartIcon.stories.tsx +2 -2
  81. package/src/common/cart-icon/NsCartIcon.tsx +1 -1
  82. package/src/common/cart-icon/index.ts +1 -1
  83. package/src/common/checkbox/NsCheckbox.spec.tsx +2 -2
  84. package/src/common/checkbox/NsCheckbox.stories.tsx +2 -2
  85. package/src/common/checkbox/NsCheckbox.styled.tsx +15 -16
  86. package/src/common/checkbox/NsCheckbox.tsx +2 -2
  87. package/src/common/checkbox/index.ts +1 -1
  88. package/src/common/checkbox/types.d.ts +1 -7
  89. package/src/common/column-control/NsColumnControl.tsx +1 -1
  90. package/src/common/column-control/NsFlexColumns.tsx +22 -0
  91. package/src/common/column-control/NsGridColumns.tsx +22 -0
  92. package/src/common/column-control/index.ts +3 -1
  93. package/src/common/column-control/{NsColumnControl.spec.tsx → specs/NsColumnControl.spec.tsx} +3 -3
  94. package/src/common/column-control/specs/NsFlexColumns.spec.tsx +24 -0
  95. package/src/common/column-control/specs/NsGridColumns.spec.tsx +24 -0
  96. package/src/common/column-control/stories/DivArray.stories.tsx +18 -0
  97. package/src/common/column-control/stories/DivArray.tsx +63 -0
  98. package/src/common/column-control/{NsColumnControl.stories.tsx → stories/NsColumnControl.stories.tsx} +9 -16
  99. package/src/common/column-control/stories/NsFlexColumns.stories.tsx +63 -0
  100. package/src/common/column-control/stories/NsGridColumns.stories.tsx +63 -0
  101. package/src/common/column-control/stories/common.tsx +14 -0
  102. package/src/common/column-control/styled/StyledFlex.tsx +45 -0
  103. package/src/common/column-control/styled/StyledGrid.tsx +40 -0
  104. package/src/common/column-control/styled/common.ts +27 -0
  105. package/src/common/column-control/types.d.ts +15 -16
  106. package/src/common/column-control/utils.ts +5 -5
  107. package/src/common/common.types.d.ts +21 -0
  108. package/src/common/dropdown/NsDropdown.spec.tsx +1 -1
  109. package/src/common/dropdown/NsDropdown.styled.tsx +23 -18
  110. package/src/common/dropdown/NsDropdown.tsx +1 -1
  111. package/src/common/dropdown/NsDropdownOption.tsx +1 -1
  112. package/src/common/dropdown/index.ts +1 -1
  113. package/src/common/dropdown/stories/NsDropdown.stories.tsx +2 -2
  114. package/src/common/dropdown/stories/NsDropdownCountry.stories.tsx +2 -2
  115. package/src/common/dropdown/types.d.ts +3 -1
  116. package/src/common/email-simple/NsEmailSimple.spec.tsx +145 -0
  117. package/src/common/email-simple/NsEmailSimple.stories.tsx +61 -0
  118. package/src/common/email-simple/NsEmailSimple.tsx +71 -0
  119. package/src/common/email-simple/index.ts +2 -0
  120. package/src/common/email-simple/types.d.ts +14 -0
  121. package/src/common/flag/NsFlag.spec.tsx +5 -25
  122. package/src/common/flag/NsFlag.stories.tsx +2 -2
  123. package/src/common/flag/NsFlag.styled.tsx +7 -9
  124. package/src/common/flag/NsFlag.tsx +1 -3
  125. package/src/common/flag/index.ts +1 -1
  126. package/src/common/flag/types.d.ts +0 -2
  127. package/src/common/hooks/index.ts +2 -0
  128. package/src/common/hooks/specs/useWindowSize.spec.tsx +19 -0
  129. package/src/common/hooks/useAccordionMap.tsx +39 -0
  130. package/src/common/hooks/useWindowSize.tsx +30 -0
  131. package/src/common/icon/NsIcon.spec.tsx +1 -1
  132. package/src/common/icon/NsIcon.stories.tsx +2 -2
  133. package/src/common/icon/NsIcon.styled.tsx +1 -1
  134. package/src/common/icon/NsIcon.tsx +1 -1
  135. package/src/common/icon/NsIconVariants.ts +9 -4
  136. package/src/common/icon/icons/AlertErrorIcon.tsx +15 -6
  137. package/src/common/icon/icons/HamburgerIcon.tsx +29 -0
  138. package/src/common/icon/icons/UserIcon.tsx +30 -0
  139. package/src/common/icon/icons/WarningIcon.tsx +14 -5
  140. package/src/common/icon/index.ts +1 -1
  141. package/src/common/icon/types.d.ts +1 -0
  142. package/src/common/image/NsImage.spec.tsx +57 -7
  143. package/src/common/image/NsImage.stories.tsx +2 -2
  144. package/src/common/image/NsImage.tsx +24 -12
  145. package/src/common/image/NsNextImage.spec.tsx +1 -1
  146. package/src/common/image/NsNextImage.stories.tsx +2 -2
  147. package/src/common/image/NsNextImage.tsx +1 -1
  148. package/src/common/image/index.ts +1 -1
  149. package/src/common/image/types.d.ts +1 -0
  150. package/src/common/index.ts +14 -10
  151. package/src/common/input/InputFieldWrapper.tsx +4 -4
  152. package/src/common/input/InputWrapper.tsx +12 -7
  153. package/src/common/input/NsInputField.stories.tsx +13 -10
  154. package/src/common/input/NsInputField.tsx +13 -6
  155. package/src/common/input/getAdornmentProps.tsx +5 -1
  156. package/src/common/input/index.ts +1 -1
  157. package/src/common/input/types.d.ts +18 -1
  158. package/src/common/label/NsLabel.stories.tsx +6 -1
  159. package/src/common/label/NsLabel.tsx +21 -20
  160. package/src/common/label/index.ts +1 -1
  161. package/src/common/label/types.d.ts +2 -1
  162. package/src/common/link/NsLink.spec.tsx +1 -1
  163. package/src/common/link/NsLink.stories.tsx +2 -2
  164. package/src/common/link/NsLink.tsx +1 -1
  165. package/src/common/link/index.ts +1 -1
  166. package/src/common/modal/NsModal.spec.tsx +46 -0
  167. package/src/common/modal/NsModal.styled.tsx +28 -0
  168. package/src/common/modal/NsModal.tsx +37 -0
  169. package/src/common/modal/helper-component/NsModalContentBox.tsx +32 -0
  170. package/src/common/modal/helper-component/NsModalDefault.tsx +25 -0
  171. package/src/common/modal/helper-component/NsModalStatus.tsx +15 -0
  172. package/src/common/modal/helper-component/NsModalStatusIcon.tsx +14 -0
  173. package/src/common/modal/helper-component/NsModalTitle.tsx +26 -0
  174. package/src/common/modal/index.ts +2 -0
  175. package/src/common/modal/model/NsModalVariantMap.tsx +24 -0
  176. package/src/common/modal/stories/NsModal.stories.tsx +86 -0
  177. package/src/common/modal/stories/mock.tsx +46 -0
  178. package/src/common/modal/types.ts +56 -0
  179. package/src/common/nav-product-card/NsNavProductCard.spec.tsx +1 -1
  180. package/src/common/nav-product-card/NsNavProductCard.stories.tsx +2 -2
  181. package/src/common/nav-product-card/NsNavProductCard.tsx +1 -1
  182. package/src/common/nav-product-card/index.ts +1 -1
  183. package/src/common/nav-tab/NsNavTab.spec.tsx +2 -7
  184. package/src/common/nav-tab/NsNavTab.stories.tsx +2 -2
  185. package/src/common/nav-tab/NsNavTab.styled.tsx +7 -4
  186. package/src/common/nav-tab/NsNavTab.tsx +1 -1
  187. package/src/common/nav-tab/index.ts +1 -1
  188. package/src/common/nav-tab/types.d.ts +2 -2
  189. package/src/common/radiogroup/NsRadioGroup.spec.tsx +63 -0
  190. package/src/common/radiogroup/NsRadioGroup.stories.tsx +84 -0
  191. package/src/common/radiogroup/NsRadioGroup.styled.tsx +52 -0
  192. package/src/common/radiogroup/NsRadioGroup.tsx +62 -0
  193. package/src/common/radiogroup/index.ts +2 -0
  194. package/src/common/radiogroup/types.d.ts +20 -0
  195. package/src/common/search-bar/NsSeachBar.spec.tsx +1 -1
  196. package/src/common/search-bar/NsSearchBar.tsx +1 -3
  197. package/src/common/select/NsSelect.spec.tsx +193 -0
  198. package/src/common/select/NsSelect.styled.tsx +104 -0
  199. package/src/common/select/NsSelect.tsx +117 -0
  200. package/src/common/select/NsSelectOption.tsx +30 -0
  201. package/src/common/select/index.ts +3 -0
  202. package/src/common/select/stories/NsSelect.stories.tsx +134 -0
  203. package/src/common/select/types.d.ts +34 -0
  204. package/src/common/spinner/NsSpinner.spec.tsx +21 -0
  205. package/src/common/spinner/NsSpinner.stories.tsx +26 -0
  206. package/src/common/spinner/NsSpinner.styled.tsx +344 -0
  207. package/src/common/spinner/NsSpinner.tsx +14 -0
  208. package/src/common/spinner/icons/Spinner.tsx +161 -0
  209. package/src/common/spinner/index.ts +2 -0
  210. package/src/common/spinner/types.ts +5 -0
  211. package/src/common/table/NsExpandableRow.tsx +68 -0
  212. package/src/common/table/NsTable.spec.tsx +174 -0
  213. package/src/common/table/NsTable.stories.tsx +161 -0
  214. package/src/common/table/NsTable.styled.ts +127 -0
  215. package/src/common/table/NsTable.tsx +133 -0
  216. package/src/common/table/NsTableHeader.tsx +41 -0
  217. package/src/common/table/NsTablePagination.tsx +28 -0
  218. package/src/common/table/helper.ts +33 -0
  219. package/src/common/table/index.ts +2 -0
  220. package/src/common/table/types.d.ts +57 -0
  221. package/src/common/text-strip/NsTextStrip.spec.tsx +30 -0
  222. package/src/common/text-strip/NsTextStrip.stories.tsx +33 -0
  223. package/src/common/text-strip/NsTextStrip.tsx +47 -0
  224. package/src/common/text-strip/index.ts +2 -0
  225. package/src/common/text-strip/types.d.ts +17 -0
  226. package/src/common/typography/NsTypography.stories.tsx +2 -2
  227. package/src/common/typography/NsTypography.tsx +1 -1
  228. package/src/common/typography/Typography.styled.tsx +4 -4
  229. package/src/common/typography/index.ts +1 -1
  230. package/src/common/util.ts +1 -0
  231. package/src/common/utility/Show.tsx +13 -0
  232. package/src/common/utility/index.ts +1 -0
  233. package/src/common/validations/regex.ts +3 -0
  234. package/src/common/videos/NsVideo.stories.tsx +2 -2
  235. package/src/common/videos/NsVideo.tsx +1 -1
  236. package/src/common/videos/index.ts +1 -1
  237. package/src/common/videos/types.d.ts +1 -1
  238. package/src/common/alert/NsAlert.styled.ts +0 -124
  239. package/src/common/card/tests/NsFfgCard.spec.tsx +0 -23
  240. package/src/common/column-control/NDivs.story.tsx +0 -35
  241. package/src/common/common.types.ts +0 -10
  242. /package/src/common/brand-components/{NsBrandContanier.styled.tsx → NsBrandContainer.styled.tsx} +0 -0
  243. /package/src/common/card/{tests → specs}/BrandLogo.spec.tsx +0 -0
  244. /package/src/common/card/{tests → specs}/NsBgCard.spec.tsx +0 -0
  245. /package/src/common/card/{tests → specs}/NsBrandProductCard.spec.tsx +0 -0
  246. /package/src/common/carousal/{tests → specs}/Chevron.spec.tsx +0 -0
  247. /package/src/common/carousal/{tests → specs}/RenderBrand.spec.tsx +0 -0
@@ -1,11 +1,11 @@
1
1
  import React from 'react';
2
2
  import { render } from '@testing-library/react';
3
- import { NsBanner } from './';
3
+ import { NsBanner } from '@/common/';
4
4
 
5
5
  describe('Hero component', () => {
6
- it('renders banner image and title', () => {
7
- const childText = 'Welcome to My Website';
8
- const imageURL = 'https://example.com/banner.jpg';
6
+ const childText = 'Welcome to My Website';
7
+ const imageURL = 'https://example.com/banner.jpg';
8
+ it('1. renders banner image and title', () => {
9
9
  const { getByAltText, getByText } = render(
10
10
  <NsBanner imageUrl={imageURL} altText="Banner image">
11
11
  <h1>{childText}</h1>
@@ -16,4 +16,13 @@ describe('Hero component', () => {
16
16
  expect(childElement).toBeInTheDocument();
17
17
  expect(imageElement).toBeInTheDocument();
18
18
  });
19
+ it('2. renders banner image and title without altText', () => {
20
+ const { getByAltText } = render(
21
+ <NsBanner imageUrl={imageURL}>
22
+ <h1>{childText}</h1>
23
+ </NsBanner>
24
+ );
25
+ const imageElement = getByAltText('NsBanner');
26
+ expect(imageElement).toBeInTheDocument();
27
+ });
19
28
  });
@@ -7,14 +7,14 @@
7
7
  import React from 'react';
8
8
  import type { StoryObj, Meta } from '@storybook/react';
9
9
  import { NsBanner, NsTypography, NsButton } from '../';
10
- import { withCenterDecorator } from '../../stories/decorators/withCenterDecorator';
10
+ import { withCenterDecorator } from '@/stories/decorators/withCenterDecorator';
11
11
 
12
12
  type ComponentType = typeof NsBanner;
13
13
  type Story = StoryObj<ComponentType>;
14
14
  type MetaStory = Meta<ComponentType>;
15
15
 
16
16
  export default {
17
- title: 'Components/NsBanner',
17
+ title: 'Components/Data Display/NsBanner',
18
18
  component: NsBanner,
19
19
  decorators: [withCenterDecorator],
20
20
  argTypes: {
@@ -1,5 +1,5 @@
1
1
  import { styled } from '@nuskin/foundation-theme';
2
- import { AlignmentType } from './types';
2
+ import { AlignmentType } from './types.d';
3
3
 
4
4
  export const StyledBanner = styled.section`
5
5
  position: relative;
@@ -6,7 +6,7 @@
6
6
 
7
7
  import React, { PropsWithChildren } from 'react';
8
8
 
9
- import { NsBannerProps } from './types';
9
+ import { NsBannerProps } from './types.d';
10
10
  import { StyledBanner, StyledHeroText } from './NsBanner.styled';
11
11
  import { NsImage } from '../';
12
12
 
@@ -1,2 +1,2 @@
1
1
  export { default as NsBanner } from './NsBanner';
2
- export type { NsBannerProps } from './types';
2
+ export type { NsBannerProps } from './types.d';
@@ -1,13 +1,13 @@
1
1
  import type { StoryObj, Meta } from '@storybook/react';
2
2
  import { NsBrandComponent } from './';
3
- import { withCenterDecorator } from '../../stories/decorators/withCenterDecorator';
3
+ import { withCenterDecorator } from '@/stories/decorators/withCenterDecorator';
4
4
 
5
5
  type ComponentType = typeof NsBrandComponent;
6
6
  type Story = StoryObj<ComponentType>;
7
7
  type MetaStory = Meta<ComponentType>;
8
8
 
9
9
  export default {
10
- title: 'Components/NsBrandComponent',
10
+ title: 'Components/Data Display/NsBrandComponent',
11
11
  component: NsBrandComponent,
12
12
  decorators: [withCenterDecorator],
13
13
  argTypes: {
@@ -1,11 +1,13 @@
1
1
  import React, { PropsWithChildren, useCallback } from 'react';
2
+
2
3
  import NSLogoHorizontal from './icons/NSLogoHorizontal';
3
4
  import NSLogoMark from './icons/NSLogoMark';
4
5
  import NSLogoPoweredBy from './icons/NSLogoPoweredBy';
5
6
  import NSLogoStacked from './icons/NSLogoStacked';
6
7
  import NSLogoWordMark from './icons/NSWordMark';
7
- import LogoContainer from './NsBrandContanier.styled';
8
- import { NsBrandComponentProps } from './types';
8
+ import LogoContainer from './NsBrandContainer.styled';
9
+
10
+ import { NsBrandComponentProps } from './types.d';
9
11
 
10
12
  const VariantMap = {
11
13
  stacked: NSLogoStacked,
@@ -18,7 +20,8 @@ const VariantMap = {
18
20
  const NsBrandComponent = (props: PropsWithChildren<NsBrandComponentProps>) => {
19
21
  const { variant = 'stacked', size = '108px', color = 'primary' } = props;
20
22
  const renderBrand = useCallback(() => {
21
- const BrandComponent = VariantMap[variant || 'stacked'];
23
+ const BrandComponent = VariantMap[variant];
24
+ // [Todo - Add neutral as FoundationTheme.PaletteColor]
22
25
  return <BrandComponent color={color as any} />;
23
26
  }, [color, variant]);
24
27
  return <LogoContainer size={size}>{renderBrand()}</LogoContainer>;
@@ -1,2 +1,2 @@
1
1
  export { default as NsBrandComponent } from './NsBrandComponent';
2
- export type { NsBrandComponentProps } from './types';
2
+ export type { NsBrandComponentProps } from './types.d';
@@ -1,17 +1,11 @@
1
1
  import React from 'react';
2
2
  import { render, screen } from '@testing-library/react';
3
3
  import { NsBreadcrumb } from './';
4
- import { ItemProps } from './types';
4
+ import { breadcrumbItems, dummyItems } from './data';
5
5
  const { getByText } = screen;
6
- export const breadcrumbItems: ItemProps[] = [
7
- { label: 'Home', href: '/', icon: 'home' },
8
- { label: 'Products', href: '/products' },
9
- { label: 'Shirts', href: '/products/shirts' },
10
- { label: 'Blue shirt', href: '/products/shirts/blue' },
11
- ];
12
6
 
13
7
  describe('Breadcrumb', () => {
14
- it('renders breadcrumb items', () => {
8
+ it('1. renders breadcrumb items', () => {
15
9
  render(<NsBreadcrumb items={breadcrumbItems} />);
16
10
  expect(getByText('Home')).toBeInTheDocument();
17
11
  expect(getByText('Products')).toBeInTheDocument();
@@ -19,11 +13,16 @@ describe('Breadcrumb', () => {
19
13
  expect(getByText('Blue shirt')).toBeInTheDocument();
20
14
  });
21
15
 
22
- it('renders breadcrumb items with navigation icons', () => {
16
+ it('2. renders breadcrumb items with navigation icons', () => {
23
17
  render(<NsBreadcrumb items={breadcrumbItems} iconVisibility />);
24
18
  expect(getByText('Home')).toBeInTheDocument();
25
19
  expect(getByText('Products')).toBeInTheDocument();
26
20
  expect(getByText('Shirts')).toBeInTheDocument();
27
21
  expect(getByText('Blue shirt')).toBeInTheDocument();
28
22
  });
23
+
24
+ it('3. renders breadcrumb items with navigation icons', () => {
25
+ render(<NsBreadcrumb items={dummyItems} iconVisibility />);
26
+ expect(getByText('Home')).toBeInTheDocument();
27
+ });
29
28
  });
@@ -1,21 +1,19 @@
1
1
  /**
2
- * @author [Vijayaprathap Kumar] (vpkumar@nuskin.com)
3
- * NsBanner.stories.tsx
4
2
  * @description NsBanner component.
5
3
  */
6
4
 
7
5
  import type { Meta, StoryObj } from '@storybook/react';
8
6
 
9
7
  import { NsBreadcrumb } from './';
10
- import { withCenterDecorator } from '../../stories/decorators/withCenterDecorator';
11
- import { breadcrumbItems } from './NsBreadcrumb.spec';
8
+ import { withCenterDecorator } from '@/stories/decorators/withCenterDecorator';
9
+ import { breadcrumbItems } from './data';
12
10
 
13
11
  type ComponentType = typeof NsBreadcrumb;
14
12
  type Story = StoryObj<ComponentType>;
15
13
  type MetaStory = Meta<ComponentType>;
16
14
 
17
15
  export default {
18
- title: 'Components/NsBreadcrumb',
16
+ title: 'Components/Navigation/NsBreadcrumb',
19
17
  component: NsBreadcrumb,
20
18
  decorators: [withCenterDecorator],
21
19
  argTypes: {
@@ -8,16 +8,18 @@ import { PropsWithChildren } from 'react';
8
8
 
9
9
  import { BreadcrumbContainer, BreadcrumbItem, BreadcrumbList } from './NsBreadcrumb.styled';
10
10
  import { NsTypography, NsLink, NsIcon } from '../';
11
- import { NsBreadcrumbProps, ItemProps } from './types';
11
+ import { NsBreadcrumbProps, ItemProps } from './types.d';
12
12
  import { useTheme } from '@mui/material/styles';
13
13
  import { ColorUtils } from '@nuskin/foundation-theme';
14
14
 
15
+ const { color } = ColorUtils;
16
+
15
17
  const NsBreadcrumb = (props: PropsWithChildren<NsBreadcrumbProps>) => {
16
18
  const { items, iconVisibility } = props;
17
19
 
18
20
  const theme = useTheme();
19
- const neutral80 = ColorUtils.getAppColor(theme, 'neutral', '80') as string;
20
- const neutral60 = ColorUtils.getAppColor(theme, 'neutral', '60') as string;
21
+ const neutral80 = color('neutral', '80')({ theme });
22
+ const neutral60 = color('neutral', '60')({ theme });
21
23
 
22
24
  const getLabel = (item: ItemProps) => {
23
25
  if (item?.href) {
@@ -0,0 +1,10 @@
1
+ import {ItemProps} from './types';
2
+ export const breadcrumbItems: ItemProps[] = [
3
+ {label: 'Home', href: '/', icon: 'home'},
4
+ {label: 'Products', href: '/products'},
5
+ {label: 'Shirts', href: '/products/shirts'},
6
+ {label: 'Blue shirt', href: '/products/shirts/blue'},
7
+ ];
8
+ export const dummyItems: ItemProps[] = [
9
+ {label: 'Home', icon: 'home'}
10
+ ]
@@ -1,2 +1,2 @@
1
1
  export { default as NsBreadcrumb } from './NsBreadcrumb';
2
- export type { NsBreadcrumbProps } from './types';
2
+ export type { NsBreadcrumbProps } from './types.d';
@@ -1,69 +1,84 @@
1
1
  import React from 'react';
2
- import { render, screen } from '../../../test-utils/index';
3
- import nuskinTheme from '@nuskin/foundation-theme/src/themes/genome-foundation';
4
- import Button from './NsButton';
2
+ import { render, screen } from '@/test-utils/index';
3
+ import { NsButton } from '../';
4
+ import { nuskinTheme } from '@nuskin/foundation-theme';
5
5
 
6
6
  const { palette } = nuskinTheme;
7
7
 
8
8
  describe('<Button />', () => {
9
- describe(' button primary', () => {
10
- test('should render default button styles', () => {
11
- render(
12
- <Button color="primary" variant="contained">
13
- Click Me
14
- </Button>
15
- );
9
+ it('1. should render default primary button styles ', () => {
10
+ const text = 'Click Me';
11
+ render(
12
+ <NsButton color="primary" variant="contained">
13
+ {text}
14
+ </NsButton>
15
+ );
16
16
 
17
- const button = screen.getByText('Click Me');
17
+ const button = screen.getByText(text);
18
+ expect(button).toBeInTheDocument();
19
+ expect(button).toHaveStyle(`color: ${palette?.primary?.contrastText}`);
20
+ expect(button).toHaveStyle(`background-color: ${palette?.primary?.buttonState?.pressed}`);
21
+ });
22
+ it('2. should render default secondary button styles', () => {
23
+ const text = 'Click Me';
24
+ render(
25
+ <NsButton color="success" variant="contained" size="large">
26
+ {text}
27
+ </NsButton>
28
+ );
29
+
30
+ const button = screen.getByText(text);
18
31
 
19
- expect(button).toBeInTheDocument();
20
- expect(button).toHaveStyle(`color: ${palette.primary.contrastText}`);
21
- expect(button).toHaveStyle(`background-color: ${palette.primary.main}`);
22
- });
32
+ expect(button).toBeInTheDocument();
33
+ expect(button).toHaveStyle(`color: ${palette.success.contrastText}`);
34
+ expect(button).toHaveStyle(`background-color: ${palette.success.buttonState?.pressed}`);
23
35
  });
24
- describe('button secondary', () => {
25
- test('should render default button styles', () => {
26
- render(
27
- <Button color="success" variant="contained" size="large">
28
- Click Me
29
- </Button>
30
- );
36
+ it('3. should render outlined success button', () => {
37
+ render(
38
+ <NsButton color="success" variant="outlined" size="large">
39
+ Click Me
40
+ </NsButton>
41
+ );
31
42
 
32
- const button = screen.getByText('Click Me');
43
+ const button = screen.getByText('Click Me');
44
+ expect(button).toBeInTheDocument();
45
+ expect(button).toHaveStyle(`color: ${palette.success.main}`);
46
+ });
47
+ it('4. should render outlined accentColorA button', () => {
48
+ render(
49
+ <NsButton color="accentColorA" variant="outlined" size="large">
50
+ Click Me
51
+ </NsButton>
52
+ );
33
53
 
34
- expect(button).toBeInTheDocument();
35
- expect(button).toHaveStyle(`color: ${palette.success.contrastText}`);
36
- expect(button).toHaveStyle(`background-color: ${palette.success.main}`);
37
- });
54
+ const button = screen.getByText('Click Me');
55
+ expect(button).toBeInTheDocument();
56
+ expect(button).toHaveStyle(`color: ${palette?.accentColorA?.main}`);
38
57
  });
39
- describe('button outline success', () => {
40
- test('should render outlined sucess button', () => {
41
- render(
42
- <Button color="success" variant="outlined" size="large">
43
- Click Me
44
- </Button>
45
- );
58
+ it('5. should render text button styles', () => {
59
+ const text = 'Click Me';
60
+ render(
61
+ <NsButton color="success" variant="text" size="large">
62
+ {text}
63
+ </NsButton>
64
+ );
46
65
 
47
- const button = screen.getByText('Click Me');
66
+ const button = screen.getByText(text);
48
67
 
49
- expect(button).toBeInTheDocument();
50
- expect(button).toHaveStyle(`color: ${palette.success.main}`);
51
- expect(button).toHaveStyle(`border-color: ${palette.success.main}`);
52
- });
68
+ expect(button).toBeInTheDocument();
69
+ expect(button).toHaveStyle(`color: ${palette.success.main}`);
53
70
  });
54
- describe('button outline accentColorA', () => {
55
- test('should render outlined sucess button', () => {
56
- render(
57
- <Button color="accentColorA" variant="outlined" size="large">
58
- Click Me
59
- </Button>
60
- );
71
+ it('6. iconOnly variant', () => {
72
+ const text = 'Click Me';
73
+ render(
74
+ <NsButton color="success" variant="text" size="large" iconOnly>
75
+ {text}
76
+ </NsButton>
77
+ );
61
78
 
62
- const button = screen.getByText('Click Me');
79
+ const button = screen.getByText(text);
63
80
 
64
- expect(button).toBeInTheDocument();
65
- expect(button).toHaveStyle(`color: ${palette?.accentColorA?.main}`);
66
- expect(button).toHaveStyle(`border-color: ${palette?.accentColorA?.main}`);
67
- });
81
+ expect(button).toBeInTheDocument();
82
+ expect(button).toHaveStyle(`color: ${palette.success.main}`);
68
83
  });
69
84
  });
@@ -2,14 +2,19 @@ import React from 'react';
2
2
  import type { StoryObj, Meta } from '@storybook/react';
3
3
  import { NsButton } from './';
4
4
  import { ShoppingCart } from '@mui/icons-material';
5
- import { withCenterDecorator } from '../../stories/decorators/withCenterDecorator';
5
+ import { withCenterDecorator } from '@/stories/decorators/withCenterDecorator';
6
+ import { within } from '@storybook/testing-library';
7
+ import { expect } from '@storybook/jest';
8
+ import { nuskinTheme } from '@nuskin/foundation-theme';
9
+
10
+ const { palette } = nuskinTheme;
6
11
 
7
12
  type ComponentType = typeof NsButton;
8
13
  type Story = StoryObj<ComponentType>;
9
14
  type MetaStory = Meta<ComponentType>;
10
15
 
11
16
  export default {
12
- title: 'Components/NsButton',
17
+ title: 'Components/Inputs/NsButton',
13
18
  component: NsButton,
14
19
  decorators: [withCenterDecorator],
15
20
  argTypes: {
@@ -21,6 +26,7 @@ export default {
21
26
  color: { name: 'Color Variants' },
22
27
  disabled: { control: 'boolean' },
23
28
  fullWidth: { control: 'boolean' },
29
+
24
30
  iconOnly: { control: 'hide' },
25
31
  },
26
32
  args: {
@@ -30,14 +36,16 @@ export default {
30
36
  disabled: false,
31
37
  variant: 'contained',
32
38
  fullWidth: false,
39
+ startIcon: '',
40
+ endIcon: '',
33
41
  },
34
42
  } as MetaStory;
35
43
 
36
44
  export const button: Story = {};
37
45
 
38
46
  export const IconOnlyButton: Story = {
39
- render: (args) => (
40
- <NsButton {...args} iconOnly>
47
+ render: (args: any) => (
48
+ <NsButton {...args} iconOnly darkModeEnabled={false}>
41
49
  <ShoppingCart />
42
50
  </NsButton>
43
51
  ),
@@ -53,3 +61,52 @@ export const IconOnlyButton: Story = {
53
61
  iconOnly: { control: 'hide' },
54
62
  },
55
63
  };
64
+ export const ButtonWithIcon: Story = {
65
+ render: (args: any) => (
66
+ <NsButton {...args} darkModeEnabled={false} startIcon={<ShoppingCart />}>
67
+ Add to Cart
68
+ </NsButton>
69
+ ),
70
+ argTypes: {
71
+ children: {
72
+ control: 'hide',
73
+ },
74
+ color: { name: 'Color Variants' },
75
+ disabled: { control: 'boolean' },
76
+ fullWidth: { control: 'boolean' },
77
+ iconOnly: { control: 'hide' },
78
+ },
79
+ };
80
+
81
+ export const TextVariant: Story = {
82
+ args: {
83
+ color: 'success',
84
+ variant: 'text',
85
+ size: 'large',
86
+ children: 'click me! icon',
87
+ },
88
+ play: ({ canvasElement }) => {
89
+ const canvas = within(canvasElement);
90
+ const button = canvas.getByText('click me! icon');
91
+ expect(button).toBeInTheDocument();
92
+ expect(button).toHaveStyle(`color: ${palette.success.main}`);
93
+ expect(button).toHaveStyle('background-color: rgba(0, 0, 0, 0);');
94
+ },
95
+ };
96
+
97
+ export const IconOnly: Story = {
98
+ args: {
99
+ iconOnly: true,
100
+ color: 'success',
101
+ variant: 'text',
102
+ size: 'large',
103
+ children: 'click me! icon',
104
+ },
105
+ play: ({ canvasElement }) => {
106
+ const canvas = within(canvasElement);
107
+ const button = canvas.getByText('click me! icon');
108
+ expect(button).toBeInTheDocument();
109
+ expect(button).toHaveStyle(`color: ${palette.success.main}`);
110
+ expect(button).toHaveStyle('background-color: rgba(0, 0, 0, 0);');
111
+ },
112
+ };
@@ -1,90 +1,72 @@
1
1
  import { Button as MUIButton } from '@mui/material';
2
2
 
3
3
  import { styled, ColorUtils, FoundationTheme } from '@nuskin/foundation-theme';
4
- import { ButtonConfig } from '@nuskin/foundation-theme/src/themes/types/button';
5
- import { NsButtonProps } from './types';
4
+ import { ButtonConfig } from '@nuskin/foundation-theme/src/common/themes/types/button';
6
5
 
7
- const {
8
- getPaletteColor,
9
- getButtonStateColor,
10
- } = ColorUtils;
6
+ import { NsButtonProps } from './types.d';
7
+ import { generateContainedStyle, generateIconOnlyStyles, generateOutlinedStyle, generateTextStyles } from './helper';
8
+ import { skipDarkModeEnabled } from '../util';
9
+
10
+ const { buttonColor, paletteColor } = ColorUtils;
11
11
 
12
12
  const getButtonConfig = (theme: FoundationTheme.Theme, attribute: keyof ButtonConfig) => {
13
13
  const { config } = theme || {};
14
14
  return config?.components?.button?.[attribute] || '';
15
15
  };
16
-
17
- const StyledButton = styled(MUIButton)<NsButtonProps>`
16
+ const options = {
17
+ shouldForwardProp: skipDarkModeEnabled,
18
+ };
19
+ const StyledButton = styled(MUIButton, options)<NsButtonProps>`
18
20
  gap: 10px;
19
- border-radius: ${({ theme}) => getButtonConfig(theme, 'borderRadius')} || 0;
20
- :focus {
21
- border: 1px solid ${({ theme}) => getButtonConfig(theme, 'focusColor')} !important;
21
+ border-radius: ${({ theme }) => {
22
+ const borderRadius = getButtonConfig(theme, 'borderRadius');
23
+ return borderRadius || 0;
24
+ }};
25
+
26
+ &:focus {
27
+ border: 1px solid ${({ theme }) => getButtonConfig(theme, 'focusColor')} !important;
22
28
  }
23
- :disabled {
24
- background-color: ${({ theme, color }) => getButtonStateColor(theme, color, 'disabled')};
25
- color: ${({ theme, color }) => getButtonStateColor(theme, color, 'disabledText')};
29
+
30
+ &:disabled {
31
+ background-color: ${({ color }) => buttonColor(color, 'disabled')};
32
+ color: ${({ color }) => buttonColor(color, 'disabledText')};
26
33
  }
34
+
27
35
  ${({ theme: { config }, size }) => {
28
- return size === 'medium' ? config?.components?.button?.size?.medium?.padding : ''
36
+ if (size === 'medium') {
37
+ return config?.components?.button?.size?.medium?.padding;
38
+ } else if (size === 'large') {
39
+ return config?.components?.button?.size?.large?.padding;
40
+ } else {
41
+ return '';
42
+ }
29
43
  }}
30
- ${({ theme: { config}, size }) => {
31
- return size === 'large' ? config?.components?.button?.size?.large?.padding : ''
32
- }}
33
- ${({ variant, theme, color = 'primary' }) => {
34
- return variant === 'contained' ?
35
- `
36
- background-color: ${getPaletteColor(theme, color)};
37
- :hover {
38
- background-color: ${getButtonStateColor(theme, color, 'hovered')};
39
- }
40
- :active {
41
- background-color: ${getButtonStateColor(theme, color, 'pressed')};
42
- }
43
- :focus {
44
- background-color: ${getButtonStateColor(theme, color, 'focused')};
45
- }
46
- `
47
- : ''
44
+
45
+ ${({ variant, theme, color = 'primary', darkModeEnabled, iconOnly }) => {
46
+ if (variant === 'contained') {
47
+ const hovered = buttonColor(color, 'hovered')({ theme });
48
+ const pressed = buttonColor(color, 'pressed')({ theme });
49
+ const focused = buttonColor(color, 'focused')({ theme });
50
+ const textColor = paletteColor(color, 'contrastText')({ theme, darkModeEnabled });
51
+ const backgroundColor = paletteColor(color)({ theme, darkModeEnabled });
52
+ return generateContainedStyle({ backgroundColor, textColor, hovered, pressed, focused });
53
+ } else if (variant === 'outlined') {
54
+ const borderColor = paletteColor(color)({ theme, darkModeEnabled });
55
+ const activeColor = paletteColor(color)({ theme });
56
+ const hovered = buttonColor(color, 'hovered')({ theme });
57
+ const pressed = buttonColor(color, 'pressed')({ theme });
58
+ return generateOutlinedStyle({ borderColor, hovered, pressed, activeColor });
59
+ } else if (variant === 'text') {
60
+ const underlineColor = paletteColor(color)({ theme, darkModeEnabled });
61
+ const hovered = buttonColor(color, 'hovered')({ theme });
62
+ const pressed = buttonColor(color, 'pressed')({ theme });
63
+ return generateTextStyles({ underlineColor, hovered, pressed });
64
+ } else if (iconOnly) {
65
+ return generateIconOnlyStyles();
66
+ } else {
67
+ return '';
68
+ }
48
69
  }}
49
- ${({ variant, theme, color = 'primary' }) =>
50
- variant === 'outlined' &&
51
- `
52
- border-color: ${getPaletteColor(theme, color)};
53
- color: ${getPaletteColor(theme, color)};
54
- :hover {
55
- border-color: ${getButtonStateColor(theme, color, 'hovered')};
56
- color: ${getPaletteColor(theme, color)};
57
- }
58
- :active {
59
- border-color: ${getButtonStateColor(theme, color, 'pressed')};
60
- color: ${getPaletteColor(theme, color)};
61
- }
62
- `}
63
- ${({ variant, theme, color = 'primary' }) =>
64
- variant === 'text' &&
65
- `
66
- text-decoration: underline 1px !important;
67
- text-underline-offset: 4px;
68
- padding: 0;
69
- min-width: auto;
70
- background-color: transparent !important;
71
- text-decoration-color: ${getPaletteColor(theme, color)};
72
- color: ${getPaletteColor(theme, color)};
73
- :hover {
74
- color: ${getButtonStateColor(theme, color, 'hovered')};
75
- text-decoration-color: ${getButtonStateColor(theme, color, 'hovered')};
76
- }
77
- :active {
78
- color: ${getPaletteColor(theme, color)};
79
- text-decoration-color: ${getButtonStateColor(theme, color, 'pressed')};
80
- }
81
- `}
82
- ${({ iconOnly }) =>
83
- iconOnly &&
84
- `
85
- padding: 10px;
86
- min-width: unset;
87
- `}
88
70
  `;
89
71
 
90
72
  export default StyledButton;
@@ -1,10 +1,16 @@
1
1
  import { PropsWithChildren } from 'react';
2
+ import { useTheme } from '@mui/material/styles';
3
+
2
4
  import StyledButton from './NsButton.styled';
3
- import { NsButtonProps } from './types';
4
5
 
5
- const NsButton = ({ children, ...props }: PropsWithChildren<NsButtonProps>) => {
6
+ import { NsButtonProps } from './types.d';
7
+
8
+ const NsButton = ({ children, darkModeEnabled = true, ...props }: PropsWithChildren<NsButtonProps>) => {
9
+ const { color } = props;
10
+ const { palette } = useTheme();
11
+ const btnColor = color && palette?.[color] ? color : 'primary';
6
12
  return (
7
- <StyledButton {...props} disableRipple>
13
+ <StyledButton {...props} color={btnColor} disableRipple darkModeEnabled={darkModeEnabled}>
8
14
  {children}
9
15
  </StyledButton>
10
16
  );