@nuskin/foundation-ui-components 1.1.0 → 1.2.0

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 (147) hide show
  1. package/package.json +18 -14
  2. package/src/common/accordion/NsAccordion.tsx +32 -40
  3. package/src/common/accordion/NsAccordionHeader.tsx +29 -8
  4. package/src/common/accordion/NsAccordionItem.tsx +24 -4
  5. package/src/common/accordion/NsCollapse.tsx +96 -35
  6. package/src/common/accordion/NsToggleSection.tsx +16 -3
  7. package/src/common/accordion/ToggleSection.styled.tsx +11 -7
  8. package/src/common/accordion/colorMap.ts +117 -0
  9. package/src/common/accordion/enums.ts +18 -0
  10. package/src/common/accordion/index.ts +1 -0
  11. package/src/common/accordion/specs/NsAccordion.spec.tsx +101 -31
  12. package/src/common/accordion/specs/NsAccordionHeader.spec.tsx +77 -10
  13. package/src/common/accordion/specs/NsAccordionItem.spec.tsx +27 -10
  14. package/src/common/accordion/specs/NsCollapse.spec.tsx +109 -17
  15. package/src/common/accordion/specs/NsToggleSection.spec.tsx +50 -14
  16. package/src/common/accordion/stories/NsAccordion.stories.tsx +31 -13
  17. package/src/common/accordion/stories/NsAccordionHeader.stories.tsx +5 -1
  18. package/src/common/accordion/stories/NsAccordionItem.stories.tsx +8 -3
  19. package/src/common/accordion/stories/NsCollapse.stories.tsx +19 -4
  20. package/src/common/accordion/stories/NsToggleSection.stories.tsx +6 -3
  21. package/src/common/accordion/stories/data.tsx +140 -19
  22. package/src/common/accordion/types.d.ts +55 -47
  23. package/src/common/alert/Header.tsx +29 -0
  24. package/src/common/alert/NsAlert.spec.tsx +46 -13
  25. package/src/common/alert/NsAlert.stories.tsx +1 -1
  26. package/src/common/alert/{NsAlert.styled.ts → NsAlert.styled.tsx} +22 -22
  27. package/src/common/alert/NsAlert.tsx +22 -87
  28. package/src/common/alert/types.d.ts +7 -7
  29. package/src/common/auth-dropdown/NsAuthDropdown.spec.tsx +23 -5
  30. package/src/common/auth-dropdown/NsAuthDropdown.styled.ts +9 -2
  31. package/src/common/auth-dropdown/NsAuthDropdown.tsx +11 -6
  32. package/src/common/autocomplete/NsAutocomplete.spec.tsx +37 -14
  33. package/src/common/autocomplete/NsAutocomplete.stories.tsx +18 -2
  34. package/src/common/autocomplete/NsAutocomplete.tsx +63 -24
  35. package/src/common/autocomplete/mock/MockData.ts +51 -7
  36. package/src/common/autocomplete/mock/MockUI.tsx +2 -1
  37. package/src/common/autocomplete/types.d.ts +7 -4
  38. package/src/common/banner/NsBanner.spec.tsx +12 -3
  39. package/src/common/brand-components/NsBrandComponent.tsx +2 -2
  40. package/src/common/breadcrumb/NsBreadcrumb.spec.tsx +8 -3
  41. package/src/common/breadcrumb/data.ts +8 -5
  42. package/src/common/button/NsButton.spec.tsx +65 -49
  43. package/src/common/button/NsButton.stories.tsx +39 -4
  44. package/src/common/button/NsButton.styled.tsx +49 -66
  45. package/src/common/button/NsButton.tsx +1 -2
  46. package/src/common/button/helper.ts +82 -0
  47. package/src/common/card/NsFfgCard.tsx +13 -7
  48. package/src/common/card/specs/NsFfgCard.spec.tsx +18 -8
  49. package/src/common/card/stories/NsFfgCard.stories.tsx +47 -14
  50. package/src/common/card/styled/NsFfgStyled.tsx +9 -7
  51. package/src/common/card/types.d.ts +7 -4
  52. package/src/common/cart-icon/NsCartIcon.spec.tsx +7 -18
  53. package/src/common/cart-icon/NsCartIcon.stories.tsx +1 -1
  54. package/src/common/cart-icon/NsCartIcon.styled.ts +7 -33
  55. package/src/common/cart-icon/NsCartIcon.tsx +5 -14
  56. package/src/common/cart-icon/types.d.ts +1 -0
  57. package/src/common/checkbox/NsCheckbox.styled.tsx +15 -16
  58. package/src/common/checkbox/NsCheckbox.tsx +1 -1
  59. package/src/common/checkbox/types.d.ts +1 -1
  60. package/src/common/column-control/styled/common.ts +1 -1
  61. package/src/common/column-control/utils.ts +4 -4
  62. package/src/common/common.types.d.ts +14 -5
  63. package/src/common/dropdown/NsDropdown.styled.tsx +23 -18
  64. package/src/common/dropdown/NsDropdown.tsx +7 -2
  65. package/src/common/hooks/index.ts +2 -0
  66. package/src/common/hooks/specs/useWindowSize.spec.tsx +19 -0
  67. package/src/common/hooks/useAccordionMap.tsx +39 -0
  68. package/src/common/hooks/useOnClickOutside.tsx +25 -0
  69. package/src/common/hooks/useWindowSize.tsx +30 -0
  70. package/src/common/icon/NsIcon.spec.tsx +1 -1
  71. package/src/common/icon/NsIcon.stories.tsx +3 -0
  72. package/src/common/icon/NsIcon.tsx +6 -2
  73. package/src/common/icon/NsIconVariants.ts +3 -0
  74. package/src/common/icon/icons/AlertErrorIcon.tsx +2 -2
  75. package/src/common/icon/icons/ArrowLeft.tsx +3 -6
  76. package/src/common/icon/icons/ArrowRight.tsx +6 -8
  77. package/src/common/icon/icons/Cart.tsx +7 -32
  78. package/src/common/icon/icons/CartBadge.tsx +2 -2
  79. package/src/common/icon/icons/CloseIcon.tsx +1 -1
  80. package/src/common/icon/icons/ErrorIcon.tsx +2 -2
  81. package/src/common/icon/icons/HamburgerIcon.tsx +5 -2
  82. package/src/common/icon/icons/SearchIcon.tsx +1 -1
  83. package/src/common/icon/icons/SuccessIcon.tsx +2 -7
  84. package/src/common/icon/icons/TrashIcon.tsx +1 -1
  85. package/src/common/icon/icons/UserIcon.tsx +3 -6
  86. package/src/common/icon/icons/UserOutline.tsx +24 -0
  87. package/src/common/icon/icons/WarningIcon.tsx +1 -1
  88. package/src/common/icon/icons/home.tsx +1 -1
  89. package/src/common/image/NsImage.spec.tsx +56 -6
  90. package/src/common/image/NsImage.tsx +23 -11
  91. package/src/common/index.ts +7 -3
  92. package/src/common/input/InputWrapper.tsx +12 -7
  93. package/src/common/input/NsInputField.tsx +1 -1
  94. package/src/common/label/NsLabel.stories.tsx +0 -3
  95. package/src/common/label/NsLabel.tsx +1 -1
  96. package/src/common/modal/NsModal.spec.tsx +46 -0
  97. package/src/common/modal/NsModal.styled.tsx +28 -0
  98. package/src/common/modal/NsModal.tsx +37 -0
  99. package/src/common/modal/helper-component/NsModalContentBox.tsx +32 -0
  100. package/src/common/modal/helper-component/NsModalDefault.tsx +25 -0
  101. package/src/common/modal/helper-component/NsModalStatus.tsx +15 -0
  102. package/src/common/modal/helper-component/NsModalStatusIcon.tsx +14 -0
  103. package/src/common/modal/helper-component/NsModalTitle.tsx +26 -0
  104. package/src/common/modal/index.ts +2 -0
  105. package/src/common/modal/model/NsModalVariantMap.tsx +24 -0
  106. package/src/common/modal/stories/NsModal.stories.tsx +85 -0
  107. package/src/common/modal/stories/mock.tsx +46 -0
  108. package/src/common/modal/types.ts +56 -0
  109. package/src/common/nav-tab/NavDrawer.tsx +34 -0
  110. package/src/common/nav-tab/NavTitles.tsx +52 -0
  111. package/src/common/nav-tab/NsNavTab.spec.tsx +4 -5
  112. package/src/common/nav-tab/NsNavTab.stories.tsx +3 -3
  113. package/src/common/nav-tab/NsNavTab.styled.tsx +13 -7
  114. package/src/common/nav-tab/NsNavTab.tsx +21 -75
  115. package/src/common/nav-tab/index.ts +1 -1
  116. package/src/common/nav-tab/types.d.ts +3 -3
  117. package/src/common/progress/NsProgress.spec.tsx +47 -0
  118. package/src/common/progress/NsProgress.stories.tsx +37 -0
  119. package/src/common/progress/NsProgress.styled.tsx +39 -0
  120. package/src/common/progress/NsProgress.tsx +27 -0
  121. package/src/common/progress/index.ts +2 -0
  122. package/src/common/progress/types.d.ts +21 -0
  123. package/src/common/radiogroup/NsRadioGroup.spec.tsx +24 -25
  124. package/src/common/radiogroup/NsRadioGroup.stories.tsx +13 -31
  125. package/src/common/radiogroup/NsRadioGroup.styled.tsx +17 -15
  126. package/src/common/radiogroup/NsRadioGroup.tsx +6 -5
  127. package/src/common/search-bar/NsSearchBar.tsx +1 -3
  128. package/src/common/select/NsSelect.spec.tsx +107 -33
  129. package/src/common/select/NsSelect.styled.tsx +89 -39
  130. package/src/common/select/NsSelect.tsx +109 -44
  131. package/src/common/select/NsSelectOption.tsx +0 -1
  132. package/src/common/select/stories/NsSelect.stories.tsx +33 -24
  133. package/src/common/select/types.d.ts +6 -4
  134. package/src/common/spinner/NsSpinner.spec.tsx +21 -0
  135. package/src/common/spinner/NsSpinner.stories.tsx +26 -0
  136. package/src/common/spinner/NsSpinner.styled.tsx +344 -0
  137. package/src/common/spinner/NsSpinner.tsx +14 -0
  138. package/src/common/spinner/icons/Spinner.tsx +161 -0
  139. package/src/common/spinner/index.ts +2 -0
  140. package/src/common/spinner/types.ts +5 -0
  141. package/src/common/table/NsTable.tsx +32 -49
  142. package/src/common/table/NsTableHeader.tsx +30 -51
  143. package/src/common/util.ts +1 -0
  144. package/src/common/utility/Show.tsx +13 -0
  145. package/src/common/utility/index.ts +1 -0
  146. package/src/common/videos/types.d.ts +1 -1
  147. /package/src/common/brand-components/{NsBrandContanier.styled.tsx → NsBrandContainer.styled.tsx} +0 -0
@@ -4,6 +4,8 @@ import { styled, ColorUtils, FoundationTheme } from '@nuskin/foundation-theme';
4
4
  import { ButtonConfig } from '@nuskin/foundation-theme/src/common/themes/types/button';
5
5
 
6
6
  import { NsButtonProps } from './types.d';
7
+ import { generateContainedStyle, generateIconOnlyStyles, generateOutlinedStyle, generateTextStyles } from './helper';
8
+ import { skipDarkModeEnabled } from '../util';
7
9
 
8
10
  const { buttonColor, paletteColor } = ColorUtils;
9
11
 
@@ -11,79 +13,60 @@ const getButtonConfig = (theme: FoundationTheme.Theme, attribute: keyof ButtonCo
11
13
  const { config } = theme || {};
12
14
  return config?.components?.button?.[attribute] || '';
13
15
  };
14
-
15
- const StyledButton = styled(MUIButton)<NsButtonProps>`
16
+ const options = {
17
+ shouldForwardProp: skipDarkModeEnabled,
18
+ };
19
+ const StyledButton = styled(MUIButton, options)<NsButtonProps>`
16
20
  gap: 10px;
17
- border-radius: ${({ theme }) => getButtonConfig(theme, 'borderRadius')} || 0;
18
- :focus {
21
+ border-radius: ${({ theme }) => {
22
+ const borderRadius = getButtonConfig(theme, 'borderRadius');
23
+ return borderRadius || 0;
24
+ }};
25
+
26
+ &:focus {
19
27
  border: 1px solid ${({ theme }) => getButtonConfig(theme, 'focusColor')} !important;
20
28
  }
21
- :disabled {
22
- background-color: ${(btnProps) => buttonColor(btnProps?.color, 'disabled')};
23
- color: ${(btnProps) => buttonColor(btnProps?.color, 'disabledText')};
29
+
30
+ &:disabled {
31
+ background-color: ${({ color }) => buttonColor(color, 'disabled')};
32
+ color: ${({ color }) => buttonColor(color, 'disabledText')};
24
33
  }
34
+
25
35
  ${({ theme: { config }, size }) => {
26
- return size === 'medium' ? config?.components?.button?.size?.medium?.padding : '';
27
- }}
28
- ${({ theme: { config }, size }) => {
29
- return size === 'large' ? config?.components?.button?.size?.large?.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
+ }
30
43
  }}
31
- ${({ variant, theme, color = 'primary', darkModeEnabled }) => {
32
- return variant === 'contained'
33
- ? `
34
- background-color: ${paletteColor(color)({ theme, darkModeEnabled })};
35
- color: ${paletteColor(color, 'contrastText')({ theme, darkModeEnabled })} !important;
36
- :hover {
37
- background-color: ${buttonColor(color, 'hovered')({ theme })};
38
- }
39
- :active {
40
- background-color: ${buttonColor(color, 'pressed')({ theme })};
41
- }
42
- :focus {
43
- background-color: ${buttonColor(color, 'focused')({ theme })};
44
- }
45
- `
46
- : '';
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
+ }
47
69
  }}
48
- ${({ variant, theme, color = 'primary', darkModeEnabled }) =>
49
- variant === 'outlined' &&
50
- `
51
- border-color: ${paletteColor(color)({ theme, darkModeEnabled })};
52
- color: ${paletteColor(color)({ theme, darkModeEnabled })};
53
- :hover {
54
- border-color: ${buttonColor(color, 'hovered')({ theme })};
55
- color: ${paletteColor(color)({ theme, darkModeEnabled })};
56
- }
57
- :active {
58
- border-color: ${buttonColor(color, 'pressed')({ theme })};
59
- color: ${paletteColor(color)({ theme })};
60
- }
61
- `}
62
- ${({ variant, theme, color = 'primary', darkModeEnabled }) =>
63
- variant === 'text' &&
64
- `
65
- text-decoration: underline 1px !important;
66
- text-underline-offset: 4px;
67
- padding: 0;
68
- min-width: auto;
69
- background-color: transparent !important;
70
- text-decoration-color: ${paletteColor(color)({ theme, darkModeEnabled })};
71
- color: ${paletteColor(color)({ theme, darkModeEnabled })};
72
- :hover {
73
- color: ${buttonColor(color, 'hovered')({ theme })};
74
- text-decoration-color: ${buttonColor(color, 'hovered')({ theme })};
75
- }
76
- :active {
77
- color: ${paletteColor(color)};
78
- text-decoration-color: ${buttonColor(color, 'pressed')({ theme })};
79
- }
80
- `}
81
- ${({ iconOnly }) =>
82
- iconOnly &&
83
- `
84
- padding: 10px;
85
- min-width: unset;
86
- `}
87
70
  `;
88
71
 
89
72
  export default StyledButton;
@@ -4,12 +4,11 @@ import { useTheme } from '@mui/material/styles';
4
4
  import StyledButton from './NsButton.styled';
5
5
 
6
6
  import { NsButtonProps } from './types.d';
7
- import { FoundationTheme } from '@nuskin/foundation-theme';
8
7
 
9
8
  const NsButton = ({ children, darkModeEnabled = true, ...props }: PropsWithChildren<NsButtonProps>) => {
10
9
  const { color } = props;
11
10
  const { palette } = useTheme();
12
- const btnColor = (color && palette?.[color] ? color : 'primary') as FoundationTheme.PaletteColors;
11
+ const btnColor = color && palette?.[color] ? color : 'primary';
13
12
  return (
14
13
  <StyledButton {...props} color={btnColor} disableRipple darkModeEnabled={darkModeEnabled}>
15
14
  {children}
@@ -0,0 +1,82 @@
1
+ type ContainedParams = {
2
+ backgroundColor: string;
3
+ textColor: string;
4
+ hovered: string;
5
+ pressed: string;
6
+ focused: string;
7
+ };
8
+
9
+ export function generateContainedStyle({
10
+ backgroundColor,
11
+ textColor,
12
+ hovered,
13
+ pressed,
14
+ focused,
15
+ }: ContainedParams): string {
16
+ return `
17
+ background-color: ${backgroundColor};
18
+ color: ${textColor} !important;
19
+ &:hover {
20
+ background-color: ${hovered};
21
+ }
22
+ &:active {
23
+ background-color: ${pressed};
24
+ }
25
+ &:focus {
26
+ background-color: ${focused};
27
+ }
28
+ `;
29
+ }
30
+ type OutlinedParams = {
31
+ borderColor: string;
32
+ hovered: string;
33
+ pressed: string;
34
+ activeColor: string;
35
+ };
36
+ export function generateOutlinedStyle({ borderColor, hovered, pressed, activeColor }: OutlinedParams) {
37
+ return `
38
+ border-color: ${borderColor};
39
+ color: ${borderColor};
40
+ &:hover {
41
+ border-color: ${hovered};
42
+ color: ${borderColor};
43
+ }
44
+ &:active {
45
+ border-color: ${pressed};
46
+ color: ${activeColor};
47
+ }
48
+ `;
49
+ }
50
+
51
+ type TextParams = {
52
+ underlineColor: string;
53
+ hovered: string;
54
+ pressed: string;
55
+ };
56
+
57
+ export function generateTextStyles({ underlineColor, hovered, pressed }: TextParams): string {
58
+ return `
59
+ text-decoration: underline 1px !important;
60
+ text-underline-offset: 4px;
61
+ padding: 0;
62
+ min-width: auto;
63
+ background-color: transparent !important;
64
+ text-decoration-color: ${underlineColor};
65
+ color: ${underlineColor};
66
+ &:hover {
67
+ color: ${hovered};
68
+ text-decoration-color: ${hovered};
69
+ }
70
+ &:active {
71
+ color: ${underlineColor};
72
+ text-decoration-color: ${pressed};
73
+ }
74
+ `;
75
+ }
76
+
77
+ export function generateIconOnlyStyles() {
78
+ return `
79
+ padding: 10px;
80
+ min-width: unset;
81
+ `;
82
+ }
@@ -2,15 +2,21 @@ import { NsNextImage, NsLink } from '../';
2
2
  import { NsFfgStyled } from './styled/NsFfgStyled';
3
3
  import { NsFfgCardProps } from './types.d';
4
4
 
5
- const NsFfgCard = ({ actionText, actionLink, text, topImageUrl, topImageAlt, additionalProps }: NsFfgCardProps) => {
5
+ const NsFfgCard = ({ cardLink, text, topImageUrl, topImageAlt, additionalProps, cslp, onClick }: NsFfgCardProps) => {
6
6
  return (
7
- <NsFfgStyled data-testid={additionalProps?.testid}>
8
- <div className="top-image">
7
+ <NsFfgStyled
8
+ data-testid={additionalProps?.testid}
9
+ onClick={onClick}
10
+ className={additionalProps?.className ?? ''}
11
+ >
12
+ <header className="top-image">
9
13
  <NsNextImage height={192} width={288} alt={topImageAlt} src={topImageUrl} />
10
- </div>
11
- <div className="body-text">{text}</div>
12
- <NsLink className="action-link" href={actionLink}>
13
- {actionText || 'LEARN MORE'}
14
+ </header>
15
+ <article className="body-text" {...cslp?.card_text}>
16
+ {text}
17
+ </article>
18
+ <NsLink className="action-link" href={cardLink.href} additionalProps={cslp?.action_text}>
19
+ {cardLink.title || 'LEARN MORE'}
14
20
  </NsLink>
15
21
  </NsFfgStyled>
16
22
  );
@@ -1,4 +1,4 @@
1
- import { render, screen } from '@testing-library/react';
1
+ import { render, screen, fireEvent } from '@testing-library/react';
2
2
  import NsFfgCard from '../NsFfgCard';
3
3
 
4
4
  describe('NsFfgCard component', () => {
@@ -6,18 +6,28 @@ describe('NsFfgCard component', () => {
6
6
  topImageUrl: 'https://media.nuskin.com/m/6245528b8f76ad32/webimage-brand-ageLOC.png',
7
7
  topImageAlt: 'alt-text',
8
8
  text: 'card text',
9
- actionLink: 'https://www.google.com',
9
+ cardLink: { href: 'https://www.google.com', title: 'Test' },
10
+ onClick: jest.fn(),
10
11
  };
11
- it('renders with background image', () => {
12
+ it('1. renders with background image', () => {
12
13
  render(<NsFfgCard {...props} additionalProps={{ testid: 'ffg-card' }} />);
13
14
  const card = screen.getByTestId('ffg-card');
14
15
  expect(card).toHaveStyle(`
15
- background-color: #fff;
16
- `);
16
+ background-color: #fff;
17
+ `);
17
18
  });
18
- it('renders with cover size', () => {
19
- render(<NsFfgCard {...props} additionalProps={{ testid: 'ffg-card-1' }} actionText="Details" />);
20
- const card = screen.getByText('Details');
19
+ it('2. renders with cover size', () => {
20
+ render(<NsFfgCard {...props} additionalProps={{ testid: 'ffg-card-1' }} />);
21
+ const card = screen.getByText(props.cardLink.title);
21
22
  expect(card).toBeInTheDocument();
22
23
  });
24
+ it('3. calls onclick', () => {
25
+ const handler = jest.fn();
26
+ const { getByTestId } = render(
27
+ <NsFfgCard {...props} onClick={handler} additionalProps={{ testid: 'ffg-card-1' }} />
28
+ );
29
+ const card = getByTestId('ffg-card-1');
30
+ fireEvent.click(card);
31
+ expect(handler).toHaveBeenCalled();
32
+ });
23
33
  });
@@ -11,30 +11,63 @@ type MetaStory = Meta<ComponentType>;
11
11
  export default {
12
12
  component: NsFfgCard,
13
13
  title: 'Components/Containers/Card/NsFfgCard',
14
- argTypes: {},
14
+ argTypes: {
15
+ onClick: {
16
+ action: 'clicked',
17
+ },
18
+ },
15
19
  decorators: [withCenterDecorator],
16
20
  } as MetaStory;
17
21
 
22
+ const text = `Every child deserves a chance to shine. Through our Nu Skin Force for Good Foundation,
23
+ we’re empowering children around the world with hope for a brighter future.`;
24
+ const host = 'https://images.contentstack.io/v3/assets';
25
+
18
26
  export const Default: Story = {
19
27
  args: {
20
- actionText: 'LEARN MORE',
21
- actionLink: 'https://www.forceforgood.org/',
22
- text: 'Every child deserves a chance to shine. Through our Nu Skin Force for Good Foundation, we’re empowering children around the world with hope for a brighter future.',
23
- topImageUrl:
24
- 'https://images.contentstack.io/v3/assets/blt594f30e2dc643eae/blt34cdb300dc9b93ff/645ccaa7520ba1a1af13a08a/nsffg-foundation.webp',
28
+ cardLink: {
29
+ href: 'https://www.forceforgood.org/',
30
+ title: 'LEARN MORE',
31
+ },
32
+ text,
33
+ topImageUrl: `${host}/blt594f30e2dc643eae/blt34cdb300dc9b93ff/645ccaa7520ba1a1af13a08a/nsffg-foundation.webp`,
34
+ topImageAlt: 'Force for Good Foundation',
35
+ additionalProps: {
36
+ testid: 'ffg-card',
37
+ },
38
+ onClick: () => {
39
+ console.log('onClick called');
40
+ },
41
+ },
42
+ play: async ({ canvasElement }: any) => {
43
+ const canvas = within(canvasElement);
44
+ userEvent.hover(canvas.getByTestId('ffg-card'));
45
+ userEvent.hover(canvas.getByRole('link'));
46
+ expect(canvas.getByText(text)).toBeInTheDocument();
47
+ },
48
+ };
49
+ const d = { count: -1 };
50
+ export const OnClick: Story = {
51
+ args: {
52
+ cardLink: {
53
+ href: 'https://www.forceforgood.org/',
54
+ title: 'LEARN MORE',
55
+ },
56
+ text,
57
+ topImageUrl: `${host}/blt594f30e2dc643eae/blt34cdb300dc9b93ff/645ccaa7520ba1a1af13a08a/nsffg-foundation.webp`,
25
58
  topImageAlt: 'Force for Good Foundation',
26
59
  additionalProps: {
27
60
  testid: 'ffg-card',
28
61
  },
62
+ onClick: () => {
63
+ d.count = 1;
64
+ console.log('on click called');
65
+ },
29
66
  },
30
- play: async ({ canvasElement }) => {
67
+ play: async ({ canvasElement }: any) => {
68
+ d.count = 0;
31
69
  const canvas = within(canvasElement);
32
- await userEvent.hover(canvas.getByTestId('ffg-card'));
33
- await userEvent.hover(canvas.getByRole('link'));
34
- await expect(
35
- canvas.getByText(
36
- 'Every child deserves a chance to shine. Through our Nu Skin Force for Good Foundation, we’re empowering children around the world with hope for a brighter future.'
37
- )
38
- ).toBeInTheDocument();
70
+ userEvent.click(canvas.getByTestId('ffg-card'));
71
+ expect(d.count).toEqual(1);
39
72
  },
40
73
  };
@@ -1,8 +1,6 @@
1
1
  import { Box } from '@mui/material';
2
2
  import { styled } from '@nuskin/foundation-theme';
3
3
 
4
- const options = {};
5
-
6
4
  const Component = () => {
7
5
  return {
8
6
  backgroundClip: 'border-box',
@@ -10,9 +8,10 @@ const Component = () => {
10
8
  border: '1px solid #eff2f7',
11
9
  borderRadius: '1rem',
12
10
  boxShadow: '0 0.75rem 1.5rem rgba(18, 38, 63, .03)',
11
+ cursor: 'pointer',
13
12
  display: 'flex',
14
13
  flexDirection: 'column' as 'column', // https://github.com/cssinjs/jss/issues/1344
15
- marginBottom: '2rem',
14
+ marginBottom: '16px',
16
15
  transition: 'all .2s ease',
17
16
  textAlign: 'center' as 'center',
18
17
  wordWrap: 'break-word' as 'break-word',
@@ -25,12 +24,15 @@ const Component = () => {
25
24
  },
26
25
  },
27
26
  '.body-text': {
28
- padding: '0 1.5rem 3rem',
29
- fontSize: '1rem',
27
+ padding: '0 1.5rem 4rem',
28
+ fontSize: '16px',
30
29
  color: '#8492a6',
31
30
  },
32
31
  '.top-image': {
33
- padding: '1.5rem 3rem',
32
+ padding: '3rem 1.5rem',
33
+ img: {
34
+ maxWidth: '100%',
35
+ },
34
36
  },
35
37
  '.action-link': {
36
38
  color: '#3c4858',
@@ -41,4 +43,4 @@ const Component = () => {
41
43
  },
42
44
  };
43
45
  };
44
- export const NsFfgStyled = styled(Box, options)<{}>(Component);
46
+ export const NsFfgStyled = styled(Box)(Component);
@@ -1,9 +1,12 @@
1
- import { AdditionalProps } from '../common.types';
2
-
1
+ import { AdditionalProps, CslpTag } from '../common.types';
3
2
  export type NsFfgCardProps = AdditionalProps & {
4
3
  topImageUrl: string;
5
4
  topImageAlt: string;
6
5
  text: string;
7
- actionLink: string;
8
- actionText?: string;
6
+ cardLink: { href: string; title: string };
7
+ onClick(): void;
8
+ cslp?: {
9
+ card_text: CslpTag;
10
+ action_text: CslpTag;
11
+ };
9
12
  };
@@ -3,27 +3,16 @@ import { render, screen } from '@/test-utils/index';
3
3
 
4
4
  const { getByTestId } = screen;
5
5
  describe('NsCartIcon', () => {
6
- it('renders Cart icon when item count is 0', () => {
6
+ it('1. renders Cart icon when item count is 0', () => {
7
7
  render(<NsCartIcon itemCount={0} color="primary" size="large" />);
8
- const cartIcon = getByTestId('cart-icon');
8
+ const cartIcon = getByTestId('cart-badge-icon');
9
9
  expect(cartIcon).toBeInTheDocument();
10
10
  });
11
- it('renders Cart icon with optional values', () => {
12
- render(<NsCartIcon itemCount={0} />);
13
- const cartIcon = getByTestId('cart-icon');
14
- expect(cartIcon).toBeInTheDocument();
15
- });
16
-
17
- it('renders Cart Badge icon when item count is greater than 0', () => {
18
- render(<NsCartIcon itemCount={5} color="primary" size="large" />);
19
- const cartBadgeIcon = getByTestId('cart-badge-icon');
20
- expect(cartBadgeIcon).toBeInTheDocument();
21
- });
22
11
 
23
- it('renders item count badge when item count is greater than 0', () => {
24
- render(<NsCartIcon itemCount={5} color="primary" size="large" />);
25
- const itemCountBadge = getByTestId('item-count-badge');
26
- expect(itemCountBadge).toBeInTheDocument();
27
- expect(itemCountBadge.textContent).toBe('5');
12
+ it('2. renders item count badge when item count is greater than 0', () => {
13
+ const itemCount = 5;
14
+ const { getByText } = render(<NsCartIcon itemCount={5} color="primary" size="large" />);
15
+ const badgeContentElement = getByText(itemCount.toString());
16
+ expect(badgeContentElement).toHaveTextContent('5'); // Adjust the value as per your badge content
28
17
  });
29
18
  });
@@ -19,7 +19,7 @@ export default {
19
19
  },
20
20
  },
21
21
  args: {
22
- itemCount: 1,
22
+ itemCount: 5,
23
23
  color: 'primary',
24
24
  size: 'large',
25
25
  },
@@ -1,40 +1,14 @@
1
- import { Theme } from '@mui/material';
1
+ import { Badge, Theme } from '@mui/material';
2
2
  import { styled, FoundationTheme } from '@nuskin/foundation-theme';
3
- import { NsIconSizeType } from '../icon/types';
4
3
 
5
4
  type ItemCountParams = {
6
- size: NsIconSizeType;
7
- color: FoundationTheme.PaletteColors;
8
5
  theme?: Theme;
6
+ bgcolor: FoundationTheme.PaletteColors;
9
7
  };
10
8
 
11
- export const CartIconContainer = styled.div`
12
- position: relative;
13
- display: inline-block;
14
- `;
15
-
16
- const BadgeFontSizeMap = {
17
- small: '8px',
18
- medium: '10px',
19
- large: '12px',
20
- xLarge: '14px',
21
- };
22
-
23
- const BadgePosMap = {
24
- small: '-8px',
25
- medium: '-6px',
26
- large: '-4px',
27
- xLarge: '-1px',
28
- };
29
-
30
- export const ItemCount = styled.span<ItemCountParams>`
31
- color: ${({ color, theme }) => theme?.palette?.[color]?.main};
32
- font-size: ${({ size }) => BadgeFontSizeMap[size]};
33
- right: ${({ size }) => BadgePosMap[size]};
34
- text-align: center;
35
- font-weight: 600;
36
- position: absolute;
37
- width: 32px;
38
- height: auto;
39
- top: -4px;
9
+ export const StyledBadge = styled(Badge) <ItemCountParams>`
10
+ & .MuiBadge-badge {
11
+ background-color: ${({ bgcolor, theme }) => theme?.palette?.[bgcolor]?.main};
12
+ color: ${({ bgcolor, theme }) => theme?.palette?.[bgcolor]?.contrastText};
13
+ }
40
14
  `;
@@ -1,21 +1,12 @@
1
1
  import { NsIcon } from '../icon';
2
- import { CartIconContainer, ItemCount } from './NsCartIcon.styled';
2
+ import { StyledBadge } from './NsCartIcon.styled';
3
3
  import { NsCartIconProps } from './types.d';
4
4
 
5
- const NsCartIcon = ({ itemCount, size = 'large', color = 'primary' }: NsCartIconProps) => {
5
+ const NsCartIcon = ({ itemCount = 0, size = 'large', color = 'primary', maxItemCount = 999 }: NsCartIconProps) => {
6
6
  return (
7
- <CartIconContainer>
8
- {itemCount > 0 ? (
9
- <NsIcon testId="cart-badge-icon" name="cartBadge" color={color} size={size} />
10
- ) : (
11
- <NsIcon testId="cart-icon" name="cart" color={color} size={size} />
12
- )}
13
- {itemCount > 0 && (
14
- <ItemCount data-testid="item-count-badge" color={color} size={size}>
15
- {itemCount}
16
- </ItemCount>
17
- )}
18
- </CartIconContainer>
7
+ <StyledBadge badgeContent={itemCount} max={maxItemCount} bgcolor={color}>
8
+ <NsIcon testId="cart-badge-icon" name="cart" size={size} color={color} />
9
+ </StyledBadge>
19
10
  );
20
11
  };
21
12
 
@@ -4,4 +4,5 @@ export type NsCartIconProps = {
4
4
  itemCount: number;
5
5
  size?: 'small' | 'medium' | 'large' | 'xLarge';
6
6
  color?: FoundationTheme.PaletteColors;
7
+ maxItemCount?:number;
7
8
  };
@@ -1,19 +1,18 @@
1
1
  /**
2
2
  * @author [vijayaprathap Kumar] (vpkumar@nuskin.com)
3
- * checkbox.tsx
4
3
  * @description Styled Components for Checkbox
5
4
  */
6
5
  import DoneIcon from '@mui/icons-material/Done';
7
6
 
8
- import { styled } from '@nuskin/foundation-theme';
7
+ import { styled, ColorUtils } from '@nuskin/foundation-theme';
9
8
  import { NsFlag } from '../flag';
10
-
9
+ const { paletteColor, buttonColor } = ColorUtils;
11
10
  /**
12
11
  * Wrapper BpIcon for checkbox.tsx
13
12
  * @params ( theme: { palette }) / Provide the color's to contaier from @nuskin/foundation-theme
14
13
  */
15
14
 
16
- export const BpIcon = styled(DoneIcon)(({ theme: { palette } }) => ({
15
+ export const BpIcon = styled(DoneIcon)(({ theme }) => ({
17
16
  border: '1px solid #8C8C8C',
18
17
  path: {
19
18
  display: 'none',
@@ -25,31 +24,31 @@ export const BpIcon = styled(DoneIcon)(({ theme: { palette } }) => ({
25
24
  outline: '3px solid #94D6E9',
26
25
  },
27
26
  'input:disabled ~ &': {
28
- background: palette?.primary?.buttonState?.hovered,
27
+ background: buttonColor('primary', 'hovered')({ theme }),
29
28
  },
30
29
  }));
31
30
 
32
31
  /**
33
32
  * Wrapper BpCheckedIcon for checkbox.tsx
34
- * @params ( theme: { palette }) / Provide the color's to contaier from @nuskin/foundation-theme
33
+ * @params ( theme: { palette }) / Provide the color's to container from @nuskin/foundation-theme
35
34
  */
36
35
 
37
- export const BpCheckedIcon = styled(BpIcon)(({ theme: { palette } }) => ({
36
+ export const BpCheckedIcon = styled(BpIcon)(({ theme }) => ({
38
37
  path: {
39
38
  display: 'block',
40
39
  },
41
- background: palette?.primary?.main ?? '#fff',
42
- color: palette?.primary?.contrastText ?? '#000',
40
+ background: paletteColor('primary', 'main')({ theme }),
41
+ color: paletteColor('primary', 'contrastText')({ theme }),
43
42
  }));
44
43
 
45
- export const StyledLabel = styled('span')<{ $hasDisabled: boolean }>`
46
- ${({ $hasDisabled, theme: { palette } }) =>
47
- $hasDisabled &&
48
- `
49
- color: ${palette?.primary?.buttonState?.hovered};
50
- `}
51
- `;
44
+ const getLabelColor = (isDisabled: boolean, color: string) => (!isDisabled ? '' : `color: ${color}`);
52
45
 
46
+ export const StyledLabel = styled('span')<{ isDisabled: boolean }>`
47
+ ${({ isDisabled, theme }) => {
48
+ const color = buttonColor('primary', 'hovered')({ theme });
49
+ return getLabelColor(isDisabled, color);
50
+ }}
51
+ `;
53
52
  export const StyledFlagLabel = styled(NsFlag)`
54
53
  margin-right: 16px;
55
54
  `;
@@ -54,7 +54,7 @@ const NsCheckbox = (props: PropsWithChildren<NsCheckboxProps>) => {
54
54
  () => (
55
55
  <NsTypography variant="p-l">
56
56
  <StyledFlagLabel {...flag} size={size} testId={`${name}-flag-label`} />
57
- <StyledLabel className="checkbox-label-text" $hasDisabled={disabled}>
57
+ <StyledLabel className="checkbox-label-text" isDisabled={disabled}>
58
58
  {label}
59
59
  </StyledLabel>
60
60
  </NsTypography>