@nuskin/foundation-ui-components 1.0.0-develop.6 → 1.0.0-develop.8

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 (127) hide show
  1. package/package.json +17 -12
  2. package/src/common/accordion/NsAccordion.tsx +30 -40
  3. package/src/common/accordion/NsAccordionHeader.tsx +27 -7
  4. package/src/common/accordion/NsAccordionItem.tsx +16 -4
  5. package/src/common/accordion/NsCollapse.tsx +71 -35
  6. package/src/common/accordion/NsToggleSection.tsx +14 -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 +8 -0
  10. package/src/common/accordion/index.ts +1 -0
  11. package/src/common/accordion/specs/NsAccordion.spec.tsx +100 -31
  12. package/src/common/accordion/specs/NsAccordionHeader.spec.tsx +77 -10
  13. package/src/common/accordion/specs/NsAccordionItem.spec.tsx +23 -10
  14. package/src/common/accordion/specs/NsCollapse.spec.tsx +106 -17
  15. package/src/common/accordion/specs/NsToggleSection.spec.tsx +46 -14
  16. package/src/common/accordion/stories/NsAccordion.stories.tsx +32 -14
  17. package/src/common/accordion/stories/NsAccordionHeader.stories.tsx +4 -1
  18. package/src/common/accordion/stories/NsAccordionItem.stories.tsx +3 -3
  19. package/src/common/accordion/stories/NsCollapse.stories.tsx +3 -3
  20. package/src/common/accordion/stories/NsToggleSection.stories.tsx +2 -3
  21. package/src/common/accordion/stories/data.tsx +157 -19
  22. package/src/common/accordion/types.d.ts +56 -49
  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 +29 -6
  34. package/src/common/autocomplete/NsAutocomplete.stories.tsx +1 -1
  35. package/src/common/autocomplete/NsAutocomplete.tsx +18 -8
  36. package/src/common/autocomplete/mock/MockUI.tsx +1 -0
  37. package/src/common/banner/NsBanner.spec.tsx +12 -3
  38. package/src/common/banner/NsBanner.stories.tsx +1 -1
  39. package/src/common/brand-components/NsBrand.stories.tsx +1 -1
  40. package/src/common/brand-components/NsBrandComponent.tsx +2 -2
  41. package/src/common/breadcrumb/NsBreadcrumb.spec.tsx +8 -3
  42. package/src/common/breadcrumb/NsBreadcrumb.stories.tsx +1 -1
  43. package/src/common/breadcrumb/data.ts +8 -5
  44. package/src/common/button/NsButton.spec.tsx +65 -49
  45. package/src/common/button/NsButton.stories.tsx +59 -2
  46. package/src/common/button/NsButton.styled.tsx +49 -66
  47. package/src/common/button/NsButton.tsx +1 -2
  48. package/src/common/button/helper.ts +82 -0
  49. package/src/common/button/types.d.ts +2 -0
  50. package/src/common/card/stories/NsBgCard.stories.tsx +1 -1
  51. package/src/common/card/stories/NsBrandProductCard.stories.tsx +1 -1
  52. package/src/common/card/stories/NsFfgCard.stories.tsx +5 -2
  53. package/src/common/card/styled/NsFfgStyled.tsx +1 -1
  54. package/src/common/carousal/stories/NSCarousal.stories.tsx +1 -1
  55. package/src/common/carousal/stories/NsScrollingCarousal.stories.tsx +1 -1
  56. package/src/common/cart-icon/NsCartIcon.stories.tsx +1 -1
  57. package/src/common/checkbox/NsCheckbox.stories.tsx +1 -1
  58. package/src/common/checkbox/NsCheckbox.styled.tsx +15 -16
  59. package/src/common/checkbox/NsCheckbox.tsx +1 -1
  60. package/src/common/column-control/stories/DivArray.stories.tsx +1 -1
  61. package/src/common/column-control/stories/NsColumnControl.stories.tsx +1 -1
  62. package/src/common/column-control/stories/NsFlexColumns.stories.tsx +1 -1
  63. package/src/common/column-control/stories/NsGridColumns.stories.tsx +1 -1
  64. package/src/common/column-control/styled/common.ts +1 -1
  65. package/src/common/column-control/utils.ts +4 -4
  66. package/src/common/common.types.d.ts +11 -1
  67. package/src/common/dropdown/NsDropdown.styled.tsx +23 -18
  68. package/src/common/dropdown/stories/NsDropdown.stories.tsx +1 -1
  69. package/src/common/dropdown/stories/NsDropdownCountry.stories.tsx +1 -1
  70. package/src/common/flag/NsFlag.stories.tsx +1 -1
  71. package/src/common/hooks/index.ts +2 -0
  72. package/src/common/hooks/specs/useWindowSize.spec.tsx +19 -0
  73. package/src/common/hooks/useAccordionMap.tsx +39 -0
  74. package/src/common/hooks/useWindowSize.tsx +30 -0
  75. package/src/common/icon/NsIcon.stories.tsx +1 -1
  76. package/src/common/icon/NsIconVariants.ts +1 -0
  77. package/src/common/image/NsImage.spec.tsx +56 -6
  78. package/src/common/image/NsImage.stories.tsx +1 -1
  79. package/src/common/image/NsImage.tsx +23 -11
  80. package/src/common/image/NsNextImage.stories.tsx +1 -1
  81. package/src/common/index.ts +6 -2
  82. package/src/common/input/InputWrapper.tsx +12 -7
  83. package/src/common/input/NsInputField.tsx +1 -1
  84. package/src/common/label/NsLabel.stories.tsx +1 -1
  85. package/src/common/link/NsLink.stories.tsx +1 -1
  86. package/src/common/modal/NsModal.spec.tsx +46 -0
  87. package/src/common/modal/NsModal.styled.tsx +28 -0
  88. package/src/common/modal/NsModal.tsx +37 -0
  89. package/src/common/modal/helper-component/NsModalContentBox.tsx +32 -0
  90. package/src/common/modal/helper-component/NsModalDefault.tsx +25 -0
  91. package/src/common/modal/helper-component/NsModalStatus.tsx +15 -0
  92. package/src/common/modal/helper-component/NsModalStatusIcon.tsx +14 -0
  93. package/src/common/modal/helper-component/NsModalTitle.tsx +26 -0
  94. package/src/common/modal/index.ts +2 -0
  95. package/src/common/modal/model/NsModalVariantMap.tsx +24 -0
  96. package/src/common/modal/stories/NsModal.stories.tsx +86 -0
  97. package/src/common/modal/stories/mock.tsx +46 -0
  98. package/src/common/modal/types.ts +56 -0
  99. package/src/common/nav-product-card/NsNavProductCard.stories.tsx +1 -1
  100. package/src/common/nav-tab/NsNavTab.stories.tsx +1 -1
  101. package/src/common/radiogroup/NsRadioGroup.spec.tsx +24 -25
  102. package/src/common/radiogroup/NsRadioGroup.stories.tsx +14 -32
  103. package/src/common/radiogroup/NsRadioGroup.styled.tsx +17 -15
  104. package/src/common/radiogroup/NsRadioGroup.tsx +6 -5
  105. package/src/common/search-bar/NsSearchBar.tsx +1 -3
  106. package/src/common/select/NsSelect.spec.tsx +10 -17
  107. package/src/common/select/NsSelect.styled.tsx +53 -34
  108. package/src/common/select/stories/NsSelect.stories.tsx +11 -11
  109. package/src/common/select/types.d.ts +3 -3
  110. package/src/common/spinner/NsSpinner.spec.tsx +21 -0
  111. package/src/common/spinner/NsSpinner.stories.tsx +26 -0
  112. package/src/common/spinner/NsSpinner.styled.tsx +344 -0
  113. package/src/common/spinner/NsSpinner.tsx +14 -0
  114. package/src/common/spinner/icons/Spinner.tsx +161 -0
  115. package/src/common/spinner/index.ts +2 -0
  116. package/src/common/spinner/types.ts +5 -0
  117. package/src/common/table/NsTable.stories.tsx +1 -1
  118. package/src/common/table/NsTable.tsx +32 -49
  119. package/src/common/table/NsTableHeader.tsx +30 -51
  120. package/src/common/text-strip/NsTextStrip.stories.tsx +1 -1
  121. package/src/common/typography/NsTypography.stories.tsx +1 -1
  122. package/src/common/util.ts +1 -0
  123. package/src/common/utility/Show.tsx +13 -0
  124. package/src/common/utility/index.ts +1 -0
  125. package/src/common/videos/NsVideo.stories.tsx +1 -1
  126. package/src/common/videos/types.d.ts +1 -1
  127. /package/src/common/brand-components/{NsBrandContanier.styled.tsx → NsBrandContainer.styled.tsx} +0 -0
@@ -0,0 +1,37 @@
1
+ import React from 'react';
2
+ import Dialog from '@mui/material/Dialog';
3
+ import { useMediaQuery } from '@mui/material';
4
+ import { useTheme } from '@mui/material/styles';
5
+ import { ModalVariantMap } from './model/NsModalVariantMap';
6
+ import { NsModalProps } from './types';
7
+
8
+ const NsModal = (props: NsModalProps) => {
9
+ const { open, handleClose, header, body, additionalProps, footer, statusInfo, variant = 'default' } = props;
10
+
11
+ const { className, scrollType = 'paper', ariaLabel } = additionalProps || {};
12
+
13
+ const { ariaLabelledby = 'alert-dialog-title', ariaDescribedby = 'alert-dialog-description' } = ariaLabel || {};
14
+
15
+ const theme = useTheme();
16
+
17
+ const fullScreen: boolean = useMediaQuery(theme.breakpoints.down('md'));
18
+
19
+ const Component = ModalVariantMap[variant];
20
+
21
+ return (
22
+ <Dialog
23
+ data-testid="nsmodal-dialog"
24
+ fullScreen={fullScreen}
25
+ open={open}
26
+ scroll={scrollType}
27
+ onClose={handleClose}
28
+ aria-labelledby={ariaLabelledby}
29
+ aria-describedby={ariaDescribedby}
30
+ className={className}
31
+ >
32
+ <Component {...{ header, handleClose, body, footer, additionalProps, statusInfo, variant, open }} />
33
+ </Dialog>
34
+ );
35
+ };
36
+
37
+ export default NsModal;
@@ -0,0 +1,32 @@
1
+ import { useMemo } from 'react';
2
+ import { DialogContent } from '@mui/material';
3
+ import { NsModalComponentProps } from '../types';
4
+ import NsModalTitle from './NsModalTitle';
5
+ import { NsTypography } from '../..';
6
+
7
+ const NsModalContentBox = ({ handleClose, statusInfo }: NsModalComponentProps) => {
8
+ const { title, description } = statusInfo || {};
9
+
10
+ const header = useMemo(() => {
11
+ return {
12
+ show: true,
13
+ children: (
14
+ <NsTypography variant="h5" weight="bold">
15
+ {title}
16
+ </NsTypography>
17
+ ),
18
+ isCloseIcon: true,
19
+ };
20
+ }, [title]);
21
+
22
+ return (
23
+ <div>
24
+ <NsModalTitle header={header} handleClose={handleClose} />
25
+ <DialogContent>
26
+ <NsTypography variant="p-xs">{description}</NsTypography>
27
+ </DialogContent>
28
+ </div>
29
+ );
30
+ };
31
+
32
+ export default NsModalContentBox;
@@ -0,0 +1,25 @@
1
+ import { DialogContent } from '@mui/material';
2
+ import NsModalTitle from './NsModalTitle';
3
+ import { NsModalComponentProps } from '../types';
4
+ import { ModalFooter } from '../NsModal.styled';
5
+ import { Show } from '../../utility';
6
+
7
+ const NsDefaultModal = ({ header, handleClose, body, footer, additionalProps }: NsModalComponentProps) => {
8
+ const { dividers } = additionalProps || {};
9
+
10
+ return (
11
+ <div data-testid="modal-default">
12
+ <NsModalTitle header={header} handleClose={handleClose} />
13
+ <DialogContent dividers={dividers}>
14
+ <Show when={body?.show ?? false}>
15
+ <div data-testid="modal-body-content">{body?.children}</div>
16
+ </Show>
17
+ <Show when={footer?.show ?? false}>
18
+ <ModalFooter data-testid="modal-footer">{footer?.children}</ModalFooter>
19
+ </Show>
20
+ </DialogContent>
21
+ </div>
22
+ );
23
+ };
24
+
25
+ export default NsDefaultModal;
@@ -0,0 +1,15 @@
1
+ import { NsInfoWrapper } from '../NsModal.styled';
2
+ import { NsModalComponentProps } from '../types';
3
+ import NsModalContentBox from './NsModalContentBox';
4
+ import NsModalStatusIcon from './NsModalStatusIcon';
5
+
6
+ const NsStatusModal = ({ handleClose, statusInfo, variant }: NsModalComponentProps) => {
7
+ return (
8
+ <NsInfoWrapper data-testid="modal-status">
9
+ <NsModalStatusIcon {...{ variant }} />
10
+ <NsModalContentBox {...{ handleClose, statusInfo }} />
11
+ </NsInfoWrapper>
12
+ );
13
+ };
14
+
15
+ export default NsStatusModal;
@@ -0,0 +1,14 @@
1
+ import { NsIcon, NsIconNameType } from '../../';
2
+ import { StatusIconMap } from '../model/NsModalVariantMap';
3
+ import { NsModalComponentProps, NsModalVariant } from '../types';
4
+
5
+ const NsModalStatusIcon = ({ variant }: NsModalComponentProps) => {
6
+ const iconName = variant ? StatusIconMap[variant] : null;
7
+ return (
8
+ <div className="status-icon">
9
+ <NsIcon name={iconName as NsIconNameType} size="medium" color={variant as NsModalVariant} />
10
+ </div>
11
+ );
12
+ };
13
+
14
+ export default NsModalStatusIcon;
@@ -0,0 +1,26 @@
1
+ import { NsIcon } from '../..';
2
+ import { DialogTitle } from '@mui/material';
3
+ import { CloseButton, NsInfoWrapper } from '../NsModal.styled';
4
+ import { NsModalComponentProps } from '../types';
5
+ import { Show } from '../../utility';
6
+
7
+ const NsModalTitle = ({ header, handleClose }: NsModalComponentProps) => {
8
+ const { show, children, isCloseIcon, iconName } = header || {};
9
+ return (
10
+ <Show when={show}>
11
+ <DialogTitle data-testid="modal-title">
12
+ <NsInfoWrapper>
13
+ {iconName ? <NsIcon name={iconName} className="title-icon" /> : null}
14
+ {children}
15
+ </NsInfoWrapper>
16
+ <Show when={isCloseIcon}>
17
+ <CloseButton aria-label="close" onClick={handleClose} data-testid="modal-close-button">
18
+ <NsIcon name="close" size="small" />
19
+ </CloseButton>
20
+ </Show>
21
+ </DialogTitle>
22
+ </Show>
23
+ );
24
+ };
25
+
26
+ export default NsModalTitle;
@@ -0,0 +1,2 @@
1
+ export { default as NsModal } from './NsModal';
2
+ export type { NsModalProps } from './types';
@@ -0,0 +1,24 @@
1
+ import { ElementType } from 'react';
2
+ import NsDefaultModal from '../helper-component/NsModalDefault';
3
+ import NsStatusModal from '../helper-component/NsModalStatus';
4
+ import { StatusIconMapProps } from '../types';
5
+
6
+ type ModalMapType = {
7
+ [key: string]: ElementType;
8
+ };
9
+
10
+ export const ModalVariantMap: ModalMapType = {
11
+ default: NsDefaultModal,
12
+ confirmation: NsDefaultModal,
13
+ success: NsStatusModal,
14
+ warning: NsStatusModal,
15
+ error: NsStatusModal,
16
+ info: NsStatusModal,
17
+ };
18
+
19
+ export const StatusIconMap: StatusIconMapProps = {
20
+ success: 'success',
21
+ warning: 'warning',
22
+ error: 'error',
23
+ info: 'infoFilled',
24
+ };
@@ -0,0 +1,86 @@
1
+ import type { StoryObj, Meta } from '@storybook/react';
2
+ import { withCenterDecorator } from '@/stories/decorators/withCenterDecorator';
3
+ import NsModal from '../NsModal';
4
+ import { NsButton } from '../../button';
5
+ import { Grid, Typography } from '@mui/material';
6
+ import { useState } from 'react';
7
+ import { NsModalProps } from '../types';
8
+ import { NsModalData } from './mock';
9
+
10
+ type ComponentType = typeof NsModal;
11
+ type Story = StoryObj<ComponentType>;
12
+ type MetaStory = Meta<ComponentType>;
13
+
14
+ export default {
15
+ title: 'Components/NsModal',
16
+ component: NsModal,
17
+ decorators: [withCenterDecorator],
18
+ argTypes: {},
19
+ args: {
20
+ ...NsModalData,
21
+ },
22
+ } as MetaStory;
23
+
24
+ const RenderNsModal = (args: NsModalProps) => {
25
+ const [isOpen, setOpen] = useState(false);
26
+
27
+ const onModalHandler = () => {
28
+ setOpen(!isOpen);
29
+ };
30
+
31
+ return (
32
+ <>
33
+ <NsButton onClick={onModalHandler}>Open Modal</NsButton>
34
+ <NsModal {...args} open={isOpen} handleClose={onModalHandler} />
35
+ </>
36
+ );
37
+ };
38
+
39
+ export const Modal: Story = {
40
+ args: {
41
+ header: {
42
+ ...NsModalData?.header,
43
+ isCloseIcon: false,
44
+ },
45
+ } as NsModalProps,
46
+ render: RenderNsModal,
47
+ };
48
+
49
+ export const WithCloseIcon: Story = {
50
+ render: RenderNsModal,
51
+ };
52
+
53
+ export const ImageWidthText: Story = {
54
+ args: {
55
+ header: {
56
+ show: true,
57
+ isCloseIcon: true,
58
+ },
59
+ body: {
60
+ show: true,
61
+ children: (
62
+ <Grid container spacing={2}>
63
+ <Grid xs={6}>
64
+ <img
65
+ src="https://www.nuskin.com/content/products/01/55/00/01550014/_jcr_content/fullImage.img.160.160.png.64.64.png"
66
+ alt={'NsImage'}
67
+ />
68
+ </Grid>
69
+ <Grid xs={6} className="p-5">
70
+ <Typography gutterBottom variant="h5" component="div">
71
+ Lizard
72
+ </Typography>
73
+ <Typography variant="body2" color="text.secondary">
74
+ Lizards are a widespread group of squamate reptiles, with over 6,000 species, ranging across
75
+ all continents except Antarctica
76
+ </Typography>
77
+ </Grid>
78
+ </Grid>
79
+ ),
80
+ },
81
+ footer: {
82
+ show: false,
83
+ },
84
+ },
85
+ render: RenderNsModal,
86
+ };
@@ -0,0 +1,46 @@
1
+ import { NsButton } from '../../button';
2
+ import { NsTypography } from '../../typography';
3
+
4
+ export const NsModalData = {
5
+ open: true,
6
+ handleClose: () => {},
7
+ variant: 'default',
8
+ header: {
9
+ show: true,
10
+ children: (
11
+ <NsTypography variant="h4" weight="bold">
12
+ Dialog with hero icon
13
+ </NsTypography>
14
+ ),
15
+ isCloseIcon: true,
16
+ iconName: 'infoOutlined',
17
+ },
18
+ body: {
19
+ show: true,
20
+ children: (
21
+ <NsTypography variant="p-s">
22
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquet sed odio donec tellus nibh dictum quis.
23
+ Dis tempus aliquam tristique auctor justo, lacus in pellentesque. Quam semper facilisi posuere hendrerit
24
+ scelerisque sed.
25
+ </NsTypography>
26
+ ),
27
+ },
28
+ statusInfo: {
29
+ title: 'Are you sure you want to delete your account?',
30
+ description: `Lorem ipsum dolor sit amet, consectetur adipiscing elit,
31
+ sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.`,
32
+ },
33
+ footer: {
34
+ show: true,
35
+ children: (
36
+ <>
37
+ <NsButton onClick={() => {}} variant="outlined">
38
+ Cancel
39
+ </NsButton>
40
+ <NsButton onClick={() => {}} variant="contained">
41
+ Confirm
42
+ </NsButton>
43
+ </>
44
+ ),
45
+ },
46
+ };
@@ -0,0 +1,56 @@
1
+ import { ReactNode } from 'react';
2
+ import { NsIconNameType } from '../icon';
3
+
4
+ export interface DialogTitleProps {
5
+ id: string;
6
+ children?: ReactNode;
7
+ onClose: () => void;
8
+ }
9
+
10
+ export interface NsModalProps extends NsModalComponentProps {
11
+ open: boolean;
12
+ }
13
+
14
+ export interface NsModalComponentProps {
15
+ handleClose?: () => void;
16
+ additionalProps?: NsModalAdditionalProps;
17
+ variant?: NsModalVariant | 'default';
18
+ header?: NsModalContentProps;
19
+ body?: NsModalContentProps;
20
+ footer?: NsModalContentProps;
21
+ statusInfo?: NsModalStatusProps;
22
+ }
23
+
24
+ export interface NsModalContentProps {
25
+ show?: boolean;
26
+ children?: string | ReactNode;
27
+ isCloseIcon?: boolean;
28
+ iconName?: NsIconNameType;
29
+ }
30
+
31
+ export interface NsModalStatusProps {
32
+ title: string;
33
+ description: string;
34
+ }
35
+
36
+ export interface NsModalAdditionalProps {
37
+ className?: string;
38
+ scrollType?: 'paper' | 'body';
39
+ ariaLabel?: NsModalAriaLabelProps;
40
+ dividers?: boolean;
41
+ }
42
+
43
+ export interface NsModalAriaLabelProps {
44
+ ariaLabelledby?: string;
45
+ ariaDescribedby?: string;
46
+ }
47
+
48
+ export type NsModalVariant = 'success' | 'warning' | 'error' | 'info';
49
+
50
+ export interface StatusIconMapProps {
51
+ success: string;
52
+ warning: string;
53
+ error: string;
54
+ info: string;
55
+ default?: string;
56
+ }
@@ -7,7 +7,7 @@ type Story = StoryObj<ComponentType>;
7
7
  type MetaStory = Meta<ComponentType>;
8
8
 
9
9
  export default {
10
- title: 'Components/NsNavProductCard',
10
+ title: 'Components/Navigation/NsNavProductCard',
11
11
  component: NsNavProductCard,
12
12
  decorators: [withCenterDecorator],
13
13
  args: {
@@ -7,7 +7,7 @@ type Story = StoryObj<ComponentType>;
7
7
  type MetaStory = Meta<ComponentType>;
8
8
 
9
9
  export default {
10
- title: 'Components/NsNavTab',
10
+ title: 'Components/Navigation/NsNavTab',
11
11
  component: NsNavTab,
12
12
  decorators: [withCenterDecorator],
13
13
  argTypes: {
@@ -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,5 +1,6 @@
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
 
@@ -23,7 +24,7 @@ export const StyledLabel = styled(FormLabel)`
23
24
  `;
24
25
 
25
26
  export const StyledRadio = styled(Radio)`
26
- color: ${(props) => !isDarkMode(props) ? color('primary', 'black')(props) : color('primary', 'white')(props)}
27
+ color: ${(props) => color('primary', !isDarkMode(props) ? 'black' : 'white')(props)};
27
28
  `;
28
29
 
29
30
  export const StyledFormControlLabel = styled(FormControlLabel)<{ darkModeEnabled?: boolean }>((props) => {
@@ -31,20 +32,21 @@ export const StyledFormControlLabel = styled(FormControlLabel)<{ darkModeEnabled
31
32
  color: paletteColor('primary')(props),
32
33
  marginBottom: '10px',
33
34
  '.MuiFormControlLabel-label.Mui-disabled': {
34
- color: `${!isDarkMode(props) ? color('neutral', 60)(props) : color('neutral', 20)(props)}`
35
+ color: `${color('neutral', !isDarkMode(props) ? 60 : 20)(props)}`,
36
+ },
37
+ };
38
+ });
39
+ const options = {
40
+ shouldForwardProp: skipDarkModeEnabled,
41
+ };
42
+ export const StyledRadioGroup = styled(
43
+ RadioGroup,
44
+ options
45
+ )<{ color: FoundationTheme.PaletteColors; darkModeEnabled?: boolean }>(({ theme, color, darkModeEnabled }) => {
46
+ return {
47
+ marginTop: '10px',
48
+ '.MuiRadio-root.custom-radio.Mui-checked': {
49
+ color: paletteColor(color)({ theme, darkModeEnabled }),
35
50
  },
36
51
  };
37
52
  });
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>