@nuskin/foundation-ui-components 1.0.2 → 1.1.1

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 (161) hide show
  1. package/package.json +105 -101
  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 +32 -14
  17. package/src/common/accordion/stories/NsAccordionHeader.stories.tsx +6 -2
  18. package/src/common/accordion/stories/NsAccordionItem.stories.tsx +9 -4
  19. package/src/common/accordion/stories/NsCollapse.stories.tsx +20 -5
  20. package/src/common/accordion/stories/NsToggleSection.stories.tsx +7 -4
  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 +3 -3
  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.stories.tsx +1 -1
  31. package/src/common/auth-dropdown/NsAuthDropdown.styled.ts +11 -7
  32. package/src/common/auth-dropdown/NsAuthDropdown.tsx +4 -4
  33. package/src/common/autocomplete/NsAutocomplete.spec.tsx +34 -11
  34. package/src/common/autocomplete/NsAutocomplete.stories.tsx +19 -3
  35. package/src/common/autocomplete/NsAutocomplete.tsx +63 -24
  36. package/src/common/autocomplete/mock/MockData.ts +50 -7
  37. package/src/common/autocomplete/mock/MockUI.tsx +2 -1
  38. package/src/common/autocomplete/types.d.ts +7 -4
  39. package/src/common/banner/NsBanner.spec.tsx +12 -3
  40. package/src/common/banner/NsBanner.stories.tsx +1 -1
  41. package/src/common/brand-components/NsBrand.stories.tsx +1 -1
  42. package/src/common/brand-components/NsBrandComponent.tsx +2 -2
  43. package/src/common/breadcrumb/NsBreadcrumb.spec.tsx +8 -3
  44. package/src/common/breadcrumb/NsBreadcrumb.stories.tsx +1 -1
  45. package/src/common/breadcrumb/data.ts +8 -5
  46. package/src/common/button/NsButton.spec.tsx +65 -49
  47. package/src/common/button/NsButton.stories.tsx +59 -2
  48. package/src/common/button/NsButton.styled.tsx +49 -66
  49. package/src/common/button/NsButton.tsx +1 -2
  50. package/src/common/button/helper.ts +82 -0
  51. package/src/common/button/types.d.ts +2 -0
  52. package/src/common/card/NsFfgCard.tsx +13 -7
  53. package/src/common/card/specs/NsFfgCard.spec.tsx +18 -8
  54. package/src/common/card/stories/NsBgCard.stories.tsx +1 -1
  55. package/src/common/card/stories/NsBrandProductCard.stories.tsx +1 -1
  56. package/src/common/card/stories/NsFfgCard.stories.tsx +48 -15
  57. package/src/common/card/styled/NsFfgStyled.tsx +10 -7
  58. package/src/common/card/types.d.ts +7 -4
  59. package/src/common/carousal/NsCarousal.tsx +3 -9
  60. package/src/common/carousal/stories/NSCarousal.stories.tsx +1 -1
  61. package/src/common/carousal/stories/NsScrollingCarousal.stories.tsx +1 -1
  62. package/src/common/cart-icon/NsCartIcon.spec.tsx +5 -16
  63. package/src/common/cart-icon/NsCartIcon.stories.tsx +2 -2
  64. package/src/common/cart-icon/NsCartIcon.styled.ts +7 -33
  65. package/src/common/cart-icon/NsCartIcon.tsx +5 -14
  66. package/src/common/cart-icon/types.d.ts +1 -0
  67. package/src/common/checkbox/NsCheckbox.stories.tsx +1 -1
  68. package/src/common/checkbox/NsCheckbox.styled.tsx +15 -16
  69. package/src/common/checkbox/NsCheckbox.tsx +1 -1
  70. package/src/common/column-control/stories/DivArray.stories.tsx +1 -1
  71. package/src/common/column-control/stories/NsColumnControl.stories.tsx +1 -1
  72. package/src/common/column-control/stories/NsFlexColumns.stories.tsx +1 -1
  73. package/src/common/column-control/stories/NsGridColumns.stories.tsx +1 -1
  74. package/src/common/column-control/styled/common.ts +1 -1
  75. package/src/common/column-control/utils.ts +4 -4
  76. package/src/common/common.types.d.ts +14 -5
  77. package/src/common/dropdown/NsDropdown.styled.tsx +23 -18
  78. package/src/common/dropdown/stories/NsDropdown.stories.tsx +1 -1
  79. package/src/common/dropdown/stories/NsDropdownCountry.stories.tsx +1 -1
  80. package/src/common/flag/NsFlag.stories.tsx +1 -1
  81. package/src/common/hooks/index.ts +2 -0
  82. package/src/common/hooks/specs/useWindowSize.spec.tsx +19 -0
  83. package/src/common/hooks/useAccordionMap.tsx +39 -0
  84. package/src/common/hooks/useWindowSize.tsx +30 -0
  85. package/src/common/icon/NsIcon.spec.tsx +1 -1
  86. package/src/common/icon/NsIcon.stories.tsx +4 -1
  87. package/src/common/icon/NsIcon.tsx +6 -2
  88. package/src/common/icon/NsIconVariants.ts +4 -1
  89. package/src/common/icon/icons/AlertErrorIcon.tsx +2 -2
  90. package/src/common/icon/icons/ArrowLeft.tsx +3 -6
  91. package/src/common/icon/icons/ArrowRight.tsx +6 -8
  92. package/src/common/icon/icons/Cart.tsx +7 -32
  93. package/src/common/icon/icons/CartBadge.tsx +2 -2
  94. package/src/common/icon/icons/CloseIcon.tsx +1 -1
  95. package/src/common/icon/icons/ErrorIcon.tsx +2 -2
  96. package/src/common/icon/icons/HamburgerIcon.tsx +5 -2
  97. package/src/common/icon/icons/SearchIcon.tsx +1 -1
  98. package/src/common/icon/icons/SuccessIcon.tsx +2 -7
  99. package/src/common/icon/icons/TrashIcon.tsx +1 -1
  100. package/src/common/icon/icons/UserIcon.tsx +3 -6
  101. package/src/common/icon/icons/UserOutline.tsx +24 -0
  102. package/src/common/icon/icons/WarningIcon.tsx +1 -1
  103. package/src/common/icon/icons/home.tsx +1 -1
  104. package/src/common/image/NsImage.spec.tsx +56 -6
  105. package/src/common/image/NsImage.stories.tsx +1 -1
  106. package/src/common/image/NsImage.tsx +23 -11
  107. package/src/common/image/NsNextImage.stories.tsx +1 -1
  108. package/src/common/index.ts +6 -2
  109. package/src/common/input/InputWrapper.tsx +12 -7
  110. package/src/common/input/NsInputField.tsx +1 -1
  111. package/src/common/label/NsLabel.stories.tsx +1 -1
  112. package/src/common/link/NsLink.stories.tsx +1 -1
  113. package/src/common/modal/NsModal.spec.tsx +46 -0
  114. package/src/common/modal/NsModal.styled.tsx +28 -0
  115. package/src/common/modal/NsModal.tsx +37 -0
  116. package/src/common/modal/helper-component/NsModalContentBox.tsx +32 -0
  117. package/src/common/modal/helper-component/NsModalDefault.tsx +25 -0
  118. package/src/common/modal/helper-component/NsModalStatus.tsx +15 -0
  119. package/src/common/modal/helper-component/NsModalStatusIcon.tsx +14 -0
  120. package/src/common/modal/helper-component/NsModalTitle.tsx +26 -0
  121. package/src/common/modal/index.ts +2 -0
  122. package/src/common/modal/model/NsModalVariantMap.tsx +24 -0
  123. package/src/common/modal/stories/NsModal.stories.tsx +85 -0
  124. package/src/common/modal/stories/mock.tsx +46 -0
  125. package/src/common/modal/types.ts +56 -0
  126. package/src/common/nav-product-card/NsNavProductCard.stories.tsx +1 -1
  127. package/src/common/nav-tab/NavDrawer.tsx +34 -0
  128. package/src/common/nav-tab/NavTitles.tsx +52 -0
  129. package/src/common/nav-tab/NsNavTab.spec.tsx +4 -5
  130. package/src/common/nav-tab/NsNavTab.stories.tsx +4 -4
  131. package/src/common/nav-tab/NsNavTab.styled.tsx +13 -7
  132. package/src/common/nav-tab/NsNavTab.tsx +21 -75
  133. package/src/common/nav-tab/index.ts +1 -1
  134. package/src/common/nav-tab/types.d.ts +3 -3
  135. package/src/common/radiogroup/NsRadioGroup.spec.tsx +24 -25
  136. package/src/common/radiogroup/NsRadioGroup.stories.tsx +14 -32
  137. package/src/common/radiogroup/NsRadioGroup.styled.tsx +20 -19
  138. package/src/common/radiogroup/NsRadioGroup.tsx +6 -5
  139. package/src/common/search-bar/NsSearchBar.tsx +1 -3
  140. package/src/common/select/NsSelect.spec.tsx +10 -17
  141. package/src/common/select/NsSelect.styled.tsx +53 -34
  142. package/src/common/select/stories/NsSelect.stories.tsx +11 -11
  143. package/src/common/select/types.d.ts +3 -3
  144. package/src/common/spinner/NsSpinner.spec.tsx +21 -0
  145. package/src/common/spinner/NsSpinner.stories.tsx +26 -0
  146. package/src/common/spinner/NsSpinner.styled.tsx +344 -0
  147. package/src/common/spinner/NsSpinner.tsx +14 -0
  148. package/src/common/spinner/icons/Spinner.tsx +161 -0
  149. package/src/common/spinner/index.ts +2 -0
  150. package/src/common/spinner/types.ts +5 -0
  151. package/src/common/table/NsTable.stories.tsx +1 -1
  152. package/src/common/table/NsTable.tsx +32 -49
  153. package/src/common/table/NsTableHeader.tsx +30 -51
  154. package/src/common/text-strip/NsTextStrip.stories.tsx +1 -1
  155. package/src/common/typography/NsTypography.stories.tsx +1 -1
  156. package/src/common/util.ts +1 -0
  157. package/src/common/utility/Show.tsx +13 -0
  158. package/src/common/utility/index.ts +1 -0
  159. package/src/common/videos/NsVideo.stories.tsx +1 -1
  160. package/src/common/videos/types.d.ts +1 -1
  161. /package/src/common/brand-components/{NsBrandContanier.styled.tsx → NsBrandContainer.styled.tsx} +0 -0
@@ -3,14 +3,13 @@ import { motion } from 'framer-motion';
3
3
 
4
4
  const { paletteColor } = ColorUtils;
5
5
 
6
-
7
6
  export const NavTabContainer = styled.div`
8
7
  .shadow {
9
8
  box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.15);
10
9
  }
11
10
  `;
12
11
 
13
- export const NavTabLine = styled(motion.li)`
12
+ export const NavTabBox = styled(motion.li)`
14
13
  margin: 0px 14px;
15
14
  align-items: center;
16
15
  white-space: normal;
@@ -19,17 +18,17 @@ export const NavTabLine = styled(motion.li)`
19
18
  list-style: none;
20
19
  position: relative;
21
20
  min-width: 60px;
21
+ padding: 8px 4px;
22
22
  `;
23
23
 
24
24
  export const NavTabUnderLine = styled(motion.div)<{ color?: FoundationTheme.PaletteColors }>`
25
25
  width: 100%;
26
26
  position: absolute;
27
- bottom: -2px;
28
- height: 2px;
29
- background-color: ${({ theme, color = 'primary' }) => paletteColor(color)({ theme })};
27
+ height: 3px;
28
+ background-color: ${({ theme, color }) => paletteColor(color)({ theme })};
30
29
  `;
31
30
 
32
- export const NavDrawer = styled.div`
31
+ export const NavDrawerStyled = styled.div`
33
32
  position: absolute;
34
33
  left: 0;
35
34
  display: flex;
@@ -63,6 +62,13 @@ export const NavDrawerContainer = styled(motion.div)`
63
62
  max-height: 590px;
64
63
  overflow: auto;
65
64
  .drawer-container {
66
- max-width: 1410px;
65
+ max-width: 1024px;
66
+ margin: 0 auto;
67
+ overflow: hidden;
67
68
  }
68
69
  `;
70
+
71
+ export const NavTitlesBox = styled.div`
72
+ display: flex;
73
+ height: 39px;
74
+ `;
@@ -1,89 +1,35 @@
1
- import React, { PropsWithChildren, useState } from 'react';
1
+ import React, { useCallback, useState } from 'react';
2
2
  import { LayoutGroup } from 'framer-motion';
3
- import { NsTypography } from '../typography';
4
- import { NavDrawerContainer, NavTabContainer, NavTabLine, NavTabUnderLine, NavDrawer } from './NsNavTab.styled';
5
- import { NSNavTabComponentProps } from './types.d';
3
+ import { NavTabContainer } from './NsNavTab.styled';
4
+ import { NavDrawer } from './NavDrawer';
5
+ import { NsNavTabComponentProps } from './types.d';
6
+ import { NavTitles } from './NavTitles';
6
7
 
7
- export const NsNavTabComponent = (props: PropsWithChildren<NSNavTabComponentProps>) => {
8
- const { tabs, className, tabTitleClassName, showDrawer = true } = props;
8
+ export const NsNavTabComponent = ({
9
+ tabs,
10
+ className,
11
+ tabTitleClassName,
12
+ showDrawer = true,
13
+ }: NsNavTabComponentProps) => {
9
14
  const [active, setActive] = useState<string | null>(null);
10
15
 
11
16
  const activeTab = tabs?.find((tab) => tab.tabName === active);
12
17
 
13
- const handleLeave = () => {
18
+ const handleLeave = useCallback(() => {
14
19
  setActive(null);
15
- };
20
+ }, []);
16
21
 
17
22
  return (
18
- <NavTabContainer data-testid="nav-container" className={className}>
23
+ <NavTabContainer data-testid="nav-container" className={`${className} ns-nav-tab-component`}>
19
24
  <LayoutGroup>
20
25
  <div onMouseLeave={handleLeave} data-testid="nav-container-draw" className="p-0 m-0">
21
- <div className="pb-0.5">
22
- <div className="flex">
23
- {tabs?.map((tab) => {
24
- const handleMouseEnter = () => {
25
- setActive(tab.tabName);
26
- };
27
- return (
28
- <div
29
- key={tab?.tabName}
30
- data-testid={tab?.tabName}
31
- className="relative cursor-pointer"
32
- onMouseEnter={handleMouseEnter}
33
- >
34
- <NavTabLine
35
- data-testid={tab.tabName + '-list'}
36
- transition={{
37
- duration: 0.3,
38
- }}
39
- animate
40
- >
41
- <NsTypography
42
- variant={tab.textVariant}
43
- additionalProps={{ ...tab?.liveTag }}
44
- className={`mb-2 ${tabTitleClassName} ${!active ? 'opacity-8' : ''}`}
45
- color={tab.tabName === active ? tab.activeColor : tab.color}
46
- >
47
- {tab.tabName}
48
- </NsTypography>
49
- </NavTabLine>
50
- {active === tab.tabName && (
51
- <NavTabUnderLine
52
- data-testid="underline"
53
- layoutId="underline"
54
- color={tab.activeColor}
55
- />
56
- )}
57
- </div>
58
- );
59
- })}
60
- </div>
61
- </div>
62
- <NavDrawer data-testid="nav-drawer-container">
63
- {active && showDrawer ? (
64
- <NavDrawerContainer
65
- data-testid="nav-drawer"
66
- initial={{
67
- height: 0,
68
- }}
69
- animate={{
70
- height: 'auto',
71
- }}
72
- exit={{
73
- height: 0,
74
- }}
75
- transition={{
76
- duration: 0.3,
77
- }}
78
- >
79
- {active ? (
80
- <div className="flex w-full overflow-hidden justify-center">
81
- <div className="drawer-container w-full">{activeTab?.tabContent}</div>
82
- </div>
83
- ) : null}
84
- </NavDrawerContainer>
85
- ) : null}
86
- </NavDrawer>
26
+ <NavTitles
27
+ tabTitleClassName={tabTitleClassName}
28
+ tabs={tabs}
29
+ active={active}
30
+ setActive={setActive}
31
+ />
32
+ <NavDrawer active={active} content={activeTab?.tabContent} showDrawer={showDrawer} />
87
33
  </div>
88
34
  </LayoutGroup>
89
35
  </NavTabContainer>
@@ -1,2 +1,2 @@
1
1
  export { NsNavTabComponent as NsNavTab } from './NsNavTab';
2
- export type { NSNavTabComponentProps, NavTabs } from './types.d';
2
+ export type { NsNavTabComponentProps, NavTabs } from './types';
@@ -1,7 +1,7 @@
1
1
  import { ReactNode } from 'react';
2
2
  import { FoundationTheme } from '@nuskin/foundation-theme';
3
3
  import { Variants } from '../typography/types';
4
- import { AdditionalProps, ContentStackLiveTags } from '../common.types';
4
+ import { AdditionalProps, CslpTag } from '../common.types';
5
5
 
6
6
  export type NavTabs = {
7
7
  tabName: string;
@@ -9,10 +9,10 @@ export type NavTabs = {
9
9
  activeColor: FoundationTheme.PaletteColors;
10
10
  color?: FoundationTheme.PaletteColors;
11
11
  textVariant: Variants;
12
- liveTag?: ContentStackLiveTags;
12
+ liveTag?: CslpTag;
13
13
  };
14
14
 
15
- export type NSNavTabComponentProps = {
15
+ export type NsNavTabComponentProps = {
16
16
  tabs: NavTabs[];
17
17
  className?: string;
18
18
  tabTitleClassName?: string;
@@ -3,14 +3,12 @@ import { render, fireEvent, screen } from '@testing-library/react';
3
3
  import { NsRadioGroup } from './';
4
4
  import { FoundationTheme } from '@nuskin/foundation-theme';
5
5
 
6
-
7
6
  describe('NsRadioGroup', () => {
8
-
9
7
  const options = [
10
8
  { id: 'Option1', label: 'Option 1', value: 'Option1' },
11
9
  { id: 'Option2', label: 'Option 2', value: 'Option2' },
12
10
  { id: 'Option3', label: 'Option 3', value: 'Option3' },
13
- ]
11
+ ];
14
12
 
15
13
  const props = {
16
14
  disable: false,
@@ -27,38 +25,39 @@ describe('NsRadioGroup', () => {
27
25
  };
28
26
  const onChange = jest.fn();
29
27
 
30
- it('renders options correctly', () => {
31
- render(
32
- <NsRadioGroup {...props} onChange={onChange}
33
- />,
34
- );
28
+ it('1. renders options correctly', () => {
29
+ render(<NsRadioGroup {...props} onChange={onChange} />);
35
30
 
36
31
  options.forEach((option) => {
37
32
  const radioOption = screen.getByLabelText(option.label) as HTMLInputElement;
38
33
  expect(radioOption).toBeInTheDocument();
39
- expect(radioOption.value).toBe(option.value)
40
- })
41
-
42
- })
34
+ expect(radioOption.value).toBe(option.value);
35
+ });
36
+ });
37
+ it('2. renders options correctly without additional slot', () => {
38
+ render(<NsRadioGroup {...props} onChange={onChange} additionalSlot={''} />);
43
39
 
44
- it('calls OnChange when selecting option', () => {
40
+ options.forEach((option) => {
41
+ const radioOption = screen.getByLabelText(option.label) as HTMLInputElement;
42
+ expect(radioOption).toBeInTheDocument();
43
+ expect(radioOption.value).toBe(option.value);
44
+ });
45
+ });
45
46
 
46
- render(<NsRadioGroup {...props} onChange={onChange} />)
47
+ it('3. calls OnChange when selecting option', () => {
48
+ render(<NsRadioGroup {...props} onChange={onChange} />);
47
49
 
48
- const radioOption = screen.getByLabelText('Option 2') as HTMLInputElement
50
+ const radioOption = screen.getByLabelText('Option 2') as HTMLInputElement;
49
51
  fireEvent.click(radioOption);
50
52
  expect(onChange).toHaveBeenCalledTimes(1);
53
+ });
51
54
 
52
- })
53
-
54
- it('does not call Onchange when the same option is clicked', () => {
55
+ it('4. does not call Onchange when the same option is clicked', () => {
55
56
  const onChange = jest.fn();
56
- render(<NsRadioGroup {...props} onChange={onChange} />)
57
+ render(<NsRadioGroup {...props} onChange={onChange} />);
57
58
 
58
- const radioOption = screen.getByLabelText('Option 1') as HTMLInputElement
59
- fireEvent.click(radioOption)
59
+ const radioOption = screen.getByLabelText('Option 1') as HTMLInputElement;
60
+ fireEvent.click(radioOption);
60
61
  expect(onChange).not.toHaveBeenCalled();
61
- })
62
-
63
-
64
- })
62
+ });
63
+ });
@@ -1,8 +1,7 @@
1
-
2
1
  import type { StoryObj, Meta } from '@storybook/react';
3
2
  import { within, userEvent } from '@storybook/testing-library';
4
3
  import { expect } from '@storybook/jest';
5
- import { NsRadioGroup } from './'
4
+ import { NsRadioGroup } from './';
6
5
  import { FoundationTheme } from '@nuskin/foundation-theme';
7
6
 
8
7
  type ComponentType = typeof NsRadioGroup;
@@ -11,46 +10,32 @@ type MetaStory = Meta<ComponentType>;
11
10
 
12
11
  export default {
13
12
  component: NsRadioGroup,
14
- title: 'Components/NsRadioGroup',
13
+ title: 'Components/Inputs/NsRadioGroup',
15
14
  argTypes: {
16
15
  disable: {
17
- description:
18
- 'Indicates whether the radio button is enabled/disabled',
19
-
16
+ description: 'Indicates whether the radio button is enabled/disabled',
20
17
  },
21
18
  items: {
22
- description:
23
- 'Value of the component to be emitted when selected.',
19
+ description: 'Value of the component to be emitted when selected.',
24
20
  },
25
21
  name: {
26
- description:
27
- 'Name of the component',
28
-
22
+ description: 'Name of the component',
29
23
  },
30
24
  label: {
31
- description:
32
- 'Label of the radio group',
33
-
25
+ description: 'Label of the radio group',
34
26
  },
35
27
  color: {
36
- description:
37
- 'Color of the radio button',
38
-
28
+ description: 'Color of the radio button',
39
29
  },
40
30
  size: {
41
- description:
42
- 'Margin Left for Additional Slot text',
43
-
31
+ description: 'Margin Left for Additional Slot text',
44
32
  },
45
33
  labelFontSize: {
46
- description:
47
- 'Used to change font-size of the label'
34
+ description: 'Used to change font-size of the label',
48
35
  },
49
36
  additionalSlot: {
50
- description:
51
- 'An additional slot allows for more text',
52
-
53
- }
37
+ description: 'An additional slot allows for more text',
38
+ },
54
39
  },
55
40
  } as MetaStory;
56
41
 
@@ -61,7 +46,7 @@ export const RadioGroup: Story = {
61
46
  {
62
47
  id: 'individual',
63
48
  label: `Vendeur à domicile indépendant mandataire (The VDI mandataire
64
- enters into sales or service agreements
49
+ enters into sales or service agreements
65
50
  with customers in the name and on behalf of the company.
66
51
  His remuneration will be based on commissions made
67
52
  on the sales of products to customers.)`,
@@ -70,7 +55,7 @@ export const RadioGroup: Story = {
70
55
  {
71
56
  id: ' retailer',
72
57
  label: `Vendeur à domicile indépendant acheteur-revendeur
73
- (The VDI acheteur-revendeur sells the company's products in his own name and behalf.
58
+ (The VDI acheteur-revendeur sells the company's products in his own name and behalf.
74
59
  His remuneration will be based on commissions and on the margins made on the sales of
75
60
  products to customers.)`,
76
61
  value: 'retailer',
@@ -91,12 +76,9 @@ export const RadioGroup: Story = {
91
76
  await userEvent.hover(canvas.getByTestId('radio-group'));
92
77
  await expect(
93
78
  canvas.getByText(
79
+ // eslint-disable-next-line max-len
94
80
  'Vendeur à domicile indépendant mandataire (The VDI mandataire enters into sales or service agreements with customers in the name and on behalf of the company. His remuneration will be based on commissions made on the sales of products to customers.)'
95
81
  )
96
82
  ).toBeInTheDocument();
97
83
  },
98
84
  };
99
-
100
-
101
-
102
-
@@ -1,13 +1,13 @@
1
1
  import { Radio, FormControlLabel, FormLabel, RadioGroup } from '@mui/material';
2
2
  import { ColorUtils, FoundationTheme, styled } from '@nuskin/foundation-theme';
3
+ import { skipDarkModeEnabled } from '../util';
3
4
 
4
5
  const { paletteColor, isDarkMode, color } = ColorUtils;
5
6
 
6
7
  export const StyledHelperText = styled('div')`
7
- margin-top :10px;
8
- padding-left: 0.5em;
9
- text-align: left;
10
- justify-self: flex-start;
8
+ margin-top :10px;
9
+ justify-self:flex-start;
10
+ padding-left: 0.5em;
11
11
  )`;
12
12
 
13
13
  export const StyledSpan = styled('span')`
@@ -23,7 +23,7 @@ export const StyledLabel = styled(FormLabel)`
23
23
  `;
24
24
 
25
25
  export const StyledRadio = styled(Radio)`
26
- color: ${(props) => !isDarkMode(props) ? color('primary', 'black')(props) : color('primary', 'white')(props)}
26
+ color: ${(props) => color('primary', !isDarkMode(props) ? 'black' : 'white')(props)};
27
27
  `;
28
28
 
29
29
  export const StyledFormControlLabel = styled(FormControlLabel)<{ darkModeEnabled?: boolean }>((props) => {
@@ -31,20 +31,21 @@ export const StyledFormControlLabel = styled(FormControlLabel)<{ darkModeEnabled
31
31
  color: paletteColor('primary')(props),
32
32
  marginBottom: '10px',
33
33
  '.MuiFormControlLabel-label.Mui-disabled': {
34
- color: `${!isDarkMode(props) ? color('neutral', 60)(props) : color('neutral', 20)(props)}`
34
+ color: `${color('neutral', !isDarkMode(props) ? 60 : 20)(props)}`,
35
+ },
36
+ };
37
+ });
38
+ const options = {
39
+ shouldForwardProp: skipDarkModeEnabled,
40
+ };
41
+ export const StyledRadioGroup = styled(
42
+ RadioGroup,
43
+ options
44
+ )<{ color: FoundationTheme.PaletteColors; darkModeEnabled?: boolean }>(({ theme, color, darkModeEnabled }) => {
45
+ return {
46
+ marginTop: '10px',
47
+ '.MuiRadio-root.custom-radio.Mui-checked': {
48
+ color: paletteColor(color)({ theme, darkModeEnabled }),
35
49
  },
36
50
  };
37
51
  });
38
-
39
- export const StyledRadioGroup = styled(RadioGroup)<
40
- { color: FoundationTheme.PaletteColors; darkModeEnabled?: boolean }
41
- >(
42
- ({ theme, color, darkModeEnabled }) => {
43
- return {
44
- marginTop: '10px',
45
- '.MuiRadio-root.custom-radio.Mui-checked': {
46
- color: paletteColor(color)({ theme, darkModeEnabled })
47
- },
48
- };
49
- }
50
- );
@@ -22,7 +22,7 @@ const NsRadioGroup = (props: NsRadioGroupProps) => {
22
22
  size,
23
23
  additionalProps,
24
24
  labelFontSize,
25
- darkModeEnabled = true
25
+ darkModeEnabled = true,
26
26
  } = props;
27
27
 
28
28
  return (
@@ -50,10 +50,11 @@ const NsRadioGroup = (props: NsRadioGroupProps) => {
50
50
  ))}
51
51
  </StyledRadioGroup>
52
52
  </FormControl>
53
- {additionalSlot ? <StyledHelperText className={`ml-${size}`}>
54
- <StyledSpan className="text-sm">{additionalSlot}</StyledSpan>
55
- </StyledHelperText> : null}
56
-
53
+ {additionalSlot ? (
54
+ <StyledHelperText className={`ml-${size}`}>
55
+ <StyledSpan className="text-sm">{additionalSlot}</StyledSpan>
56
+ </StyledHelperText>
57
+ ) : null}
57
58
  </>
58
59
  );
59
60
  };
@@ -2,8 +2,6 @@ import React from 'react';
2
2
  import InputBase from '@mui/material/InputBase';
3
3
  import { styled } from '@nuskin/foundation-theme';
4
4
 
5
- interface NsSearchBarProps {}
6
-
7
5
  const Search = styled('div')`
8
6
  position: relative;
9
7
  borderRadius: 0;
@@ -31,7 +29,7 @@ const StyledInputBase = styled(InputBase)(() => ({
31
29
  },
32
30
  }));
33
31
 
34
- const NsSearchBar: React.FC<NsSearchBarProps> = () => {
32
+ const NsSearchBar: React.FC = () => {
35
33
  return (
36
34
  <div>
37
35
  <Search>
@@ -11,9 +11,7 @@ describe('NsSelectOption', () => {
11
11
  test('renders NsSelectOption component without errors', () => {
12
12
  const value = 'option1';
13
13
  const label = 'Option 1';
14
- const { getByTestId, getByText } = render(
15
- <NsSelectOption value={value} label={label} />
16
- );
14
+ const { getByTestId, getByText } = render(<NsSelectOption value={value} label={label} />);
17
15
 
18
16
  // Check if the option container element exists
19
17
  const optionContainer = getByTestId(`option-${value}`);
@@ -27,14 +25,11 @@ describe('NsSelectOption', () => {
27
25
  const value = 'option1';
28
26
  const label = 'Option 1';
29
27
  const onSelect = jest.fn();
30
- const { getByTestId } = render(
31
- <NsSelectOption value={value} label={label} onSelect={onSelect} />
32
- );
28
+ const { getByTestId } = render(<NsSelectOption value={value} label={label} onSelect={onSelect} />);
33
29
  const optionElement = getByTestId(`option-${value}`);
34
30
  fireEvent.click(optionElement);
35
31
  expect(onSelect).toHaveBeenCalledWith(value);
36
32
  });
37
-
38
33
  });
39
34
 
40
35
  describe('NsSelect', () => {
@@ -69,8 +64,7 @@ describe('NsSelect', () => {
69
64
  const onSelect = jest.fn();
70
65
  const selectedLabel = 'Option 1';
71
66
  const { getByTestId, queryByTestId } = render(
72
- <NsSelect selectedValue="Option1" selectedLabel={selectedLabel} onSelect={onSelect}>
73
- </NsSelect>
67
+ <NsSelect selectedValue="Option1" selectedLabel={selectedLabel} onSelect={onSelect} />
74
68
  );
75
69
  const selectButton = getByTestId('select-head');
76
70
  fireEvent.mouseDown(selectButton);
@@ -132,12 +126,7 @@ describe('NsSelect', () => {
132
126
 
133
127
  it('select closes on mouse leave when closeOnMouseLeave is set to true', async () => {
134
128
  render(
135
- <NsSelect
136
- closeOnMouseLeave
137
- selectedValue={selectedValue}
138
- selectedLabel={selectedLabel}
139
- onSelect={onSelect}
140
- >
129
+ <NsSelect closeOnMouseLeave selectedValue={selectedValue} selectedLabel={selectedLabel} onSelect={onSelect}>
141
130
  {createSelectOptions(options)}
142
131
  </NsSelect>
143
132
  );
@@ -186,7 +175,12 @@ describe('NsSelect', () => {
186
175
  test('renders SelectContainer with error styles when errorMessage is present', () => {
187
176
  const errorMessage = 'Invalid value';
188
177
  render(
189
- <NsSelect selectedValue={selectedValue} selectedLabel={selectedLabel} onSelect={onSelect} errorMessage={errorMessage}>
178
+ <NsSelect
179
+ selectedValue={selectedValue}
180
+ selectedLabel={selectedLabel}
181
+ onSelect={onSelect}
182
+ errorMessage={errorMessage}
183
+ >
190
184
  {createSelectOptions(options)}
191
185
  </NsSelect>
192
186
  );
@@ -196,5 +190,4 @@ describe('NsSelect', () => {
196
190
  expect(selectContainer).toHaveStyle('borderColor: red');
197
191
  expect(selectContainer).toHaveStyle('color: red');
198
192
  });
199
-
200
193
  });
@@ -1,4 +1,6 @@
1
1
  import { styled, ColorUtils, FoundationTheme } from '@nuskin/foundation-theme';
2
+ import { Themed } from '../common.types';
3
+ import { getDropdownHeadBorder } from '../dropdown/NsDropdown.styled';
2
4
  const { color, paletteColor, isDarkMode } = ColorUtils;
3
5
 
4
6
  export const SelectContainer = styled.div<{ disabled: boolean }>`
@@ -13,8 +15,7 @@ export const SelectHead = styled.div<{ type: string; disabled: boolean }>`
13
15
  display: flex;
14
16
  justify-content: space-between;
15
17
  align-items: center;
16
- border: ${({ type, theme }) =>
17
- type === 'outlined' ? `1px solid ${color('primary', 'black')({ theme })}` : 'none'};
18
+ border: ${getDropdownHeadBorder}
18
19
  color: ${paletteColor('primary')};
19
20
  width: 207px;
20
21
  position: relative;
@@ -36,47 +37,65 @@ export const SelectList = styled.div<{ borderColor: FoundationTheme.PaletteColor
36
37
  background-color: ${paletteColor('primary', 'contrastText')};
37
38
  `;
38
39
 
39
- const getDividerColor = (props: { theme: FoundationTheme.Theme}) => {
40
- const dividerColor = !isDarkMode(props) ? color('neutral', '30')(props) : color('neutral', '20')(props);
41
- return dividerColor;
40
+ const getDividerColor = (props: { theme: FoundationTheme.Theme }) => {
41
+ return !isDarkMode(props) ? color('neutral', '30')(props) : color('neutral', '20')(props);
42
42
  };
43
43
 
44
44
  const getListBgColor = (props: { theme: FoundationTheme.Theme }) => {
45
- const bgColor = !isDarkMode(props) ? color('accentColorB', '10')(props) : color('accentColorB', '50')(props);
46
- return bgColor;
45
+ return !isDarkMode(props) ? color('accentColorB', '10')(props) : color('accentColorB', '50')(props);
47
46
  };
47
+ type ContainerParam = { borderBottom: string; bgColor: string; color: string; hoveredBg: string };
48
+ function createListContainerStyle({ borderBottom, bgColor, color, hoveredBg }: ContainerParam) {
49
+ return `
50
+ cursor: pointer;
51
+ padding: 5px 0;
52
+ border-bottom: 1px solid ${borderBottom};
53
+ background-color: ${bgColor};
54
+ color: ${color};
48
55
 
49
- export const ListItemContainer = styled.div<{ showListDivider: boolean; isSelected: boolean }>`
50
- ${({ showListDivider, isSelected, theme }) => `
51
- cursor: pointer;
52
- padding: 5px 0;
53
- border-bottom: 1px solid ${showListDivider ? getDividerColor({ theme }) : 'none'};
54
- background-color: ${isSelected ? paletteColor('primary')({ theme }) : 'white'};
55
- color: ${isSelected ? 'white' : 'black'};
56
-
57
- &:hover {
58
- background-color: ${getListBgColor({ theme })};
59
- }
56
+ &:hover {
57
+ background-color: ${hoveredBg};
58
+ }
60
59
 
61
- &:last-child {
62
- border-bottom: none;
63
- }
64
- `}
60
+ &:last-child {
61
+ border-bottom: none;
62
+ }
63
+ `;
64
+ }
65
+ export const ListItemContainer = styled.div<{ showListDivider: boolean; isSelected: boolean }>`
66
+ ${({ showListDivider, isSelected, theme }) => {
67
+ const borderBottom = showListDivider ? getDividerColor({ theme }) : 'none';
68
+ const bgColor = isSelected ? paletteColor('primary')({ theme }) : 'white';
69
+ const color = isSelected ? 'white' : 'black';
70
+ const hoveredBg = getListBgColor({ theme });
71
+ return createListContainerStyle({ borderBottom, bgColor, color, hoveredBg });
72
+ }}
65
73
  `;
74
+ const getListItemBgColor = ({ isSelected, theme }: { isSelected: boolean } & Themed) => {
75
+ if (isSelected) {
76
+ return paletteColor('primary')({ theme });
77
+ }
78
+ return getListBgColor({ theme });
79
+ };
66
80
 
67
- export const ListItem = styled.div<{ isSelected: boolean}>`
68
- padding: 5px 10px;
69
- border-left: ${({ isSelected, theme }) =>
70
- isSelected ? `2px solid ${paletteColor('primary')({ theme })}` : 'none'};
71
- background-color: ${({ isSelected, theme }) =>
72
- isSelected ? paletteColor('primary', 'main')({ theme }) : 'white'};
73
- color: ${({ isSelected }) => (isSelected ? 'white' : 'black')};
74
- &:hover {
75
- background-color: ${({ isSelected, theme }) =>
76
- isSelected ? paletteColor('primary')({ theme }) : getListBgColor({ theme })};
77
- font-weight: bold;
81
+ const getListItemBorderLeftColor = ({ isSelected, theme }: { isSelected: boolean } & Themed) => {
82
+ if (isSelected) {
83
+ const color = paletteColor('primary')({ theme });
84
+ return `2px solid ${color}`;
78
85
  }
79
- `;
86
+ return 'none';
87
+ };
88
+
89
+ export const ListItem = styled.div<{ isSelected: boolean }>(({ isSelected, theme }) => ({
90
+ padding: '5px 10px',
91
+ borderLeft: getListItemBorderLeftColor({ isSelected, theme }),
92
+ backgroundColor: isSelected ? paletteColor('primary', 'main')({ theme }) : 'white',
93
+ color: isSelected ? 'white' : 'black',
94
+ '&:hover': {
95
+ backgroundColor: getListItemBgColor({ isSelected, theme }),
96
+ fontWeight: 'bold',
97
+ },
98
+ }));
80
99
 
81
100
  export const SelectLabel = styled.label`
82
101
  display: block;