@nuskin/foundation-ui-components 1.0.0-develop.7 → 1.0.0-develop.9

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 (42) hide show
  1. package/package.json +1 -1
  2. package/src/common/accordion/NsAccordion.tsx +3 -1
  3. package/src/common/accordion/NsAccordionHeader.tsx +25 -19
  4. package/src/common/accordion/NsAccordionItem.tsx +8 -0
  5. package/src/common/accordion/NsCollapse.tsx +26 -10
  6. package/src/common/accordion/NsToggleSection.tsx +2 -0
  7. package/src/common/accordion/ToggleSection.styled.tsx +5 -2
  8. package/src/common/accordion/enums.ts +0 -7
  9. package/src/common/accordion/specs/NsAccordion.spec.tsx +1 -0
  10. package/src/common/accordion/specs/NsAccordionItem.spec.tsx +4 -0
  11. package/src/common/accordion/specs/NsCollapse.spec.tsx +23 -20
  12. package/src/common/accordion/specs/NsToggleSection.spec.tsx +4 -0
  13. package/src/common/accordion/stories/NsAccordion.stories.tsx +5 -0
  14. package/src/common/accordion/stories/NsAccordionHeader.stories.tsx +2 -1
  15. package/src/common/accordion/stories/NsAccordionItem.stories.tsx +6 -1
  16. package/src/common/accordion/stories/NsCollapse.stories.tsx +17 -2
  17. package/src/common/accordion/stories/NsToggleSection.stories.tsx +5 -1
  18. package/src/common/accordion/stories/data.tsx +66 -83
  19. package/src/common/accordion/types.d.ts +13 -12
  20. package/src/common/card/NsFfgCard.tsx +13 -7
  21. package/src/common/card/specs/NsFfgCard.spec.tsx +18 -8
  22. package/src/common/card/stories/NsFfgCard.stories.tsx +47 -17
  23. package/src/common/card/styled/NsFfgStyled.tsx +9 -7
  24. package/src/common/card/types.d.ts +7 -4
  25. package/src/common/common.types.d.ts +3 -4
  26. package/src/common/index.ts +5 -3
  27. package/src/common/modal/NsModal.spec.tsx +46 -0
  28. package/src/common/modal/NsModal.styled.tsx +28 -0
  29. package/src/common/modal/NsModal.tsx +37 -0
  30. package/src/common/modal/helper-component/NsModalContentBox.tsx +32 -0
  31. package/src/common/modal/helper-component/NsModalDefault.tsx +25 -0
  32. package/src/common/modal/helper-component/NsModalStatus.tsx +15 -0
  33. package/src/common/modal/helper-component/NsModalStatusIcon.tsx +14 -0
  34. package/src/common/modal/helper-component/NsModalTitle.tsx +26 -0
  35. package/src/common/modal/index.ts +2 -0
  36. package/src/common/modal/model/NsModalVariantMap.tsx +24 -0
  37. package/src/common/modal/stories/NsModal.stories.tsx +86 -0
  38. package/src/common/modal/stories/mock.tsx +46 -0
  39. package/src/common/modal/types.ts +56 -0
  40. package/src/common/nav-tab/types.d.ts +2 -2
  41. package/src/common/utility/Show.tsx +13 -0
  42. package/src/common/utility/index.ts +1 -0
@@ -1,5 +1,5 @@
1
1
  import { NsIconProps } from '../..';
2
- import { AccordionItem, ItemContent } from '../types';
2
+ import { AccordionItem } from '../types';
3
3
 
4
4
  const getItem = () => {
5
5
  return {
@@ -14,8 +14,8 @@ const getIcon = (name = '', color = '') => {
14
14
  };
15
15
  export const getTextContent = (text = '') => {
16
16
  return {
17
- type: 'text' as ItemContent['type'],
18
- data: text || dummyText,
17
+ type: 'text' as AccordionItem['type'],
18
+ content: text || dummyText,
19
19
  };
20
20
  };
21
21
  const getJsxContent = (text = '') => {
@@ -33,6 +33,7 @@ function createAccordionItem1(): AccordionItem {
33
33
  icon: getIcon(),
34
34
  title: 'Example - 1 JSX',
35
35
  content: getJsxContent(),
36
+ type: 'jsx',
36
37
  isDefaultOpen: true,
37
38
  };
38
39
  }
@@ -42,18 +43,17 @@ function createAccordionItem2(): AccordionItem {
42
43
  isDefaultOpen: true,
43
44
  icon: getIcon(),
44
45
  title: 'Example - 2',
45
- content: {
46
- type: 'accordion',
47
- data: [
48
- { ...getItem(), title: 'Example - 2.1', content: getTextContent() },
49
- {
50
- ...getItem(),
51
- icon: getIcon('hamburgerIcon', 'success'),
52
- title: 'Example - 2.2',
53
- content: <div className="p-2">Example 2.2 Content</div>,
54
- },
55
- ],
56
- },
46
+ type: 'accordion',
47
+ content: [
48
+ { ...getItem(), title: 'Example - 2.1', ...getTextContent() },
49
+ {
50
+ ...getItem(),
51
+ icon: getIcon('hamburgerIcon', 'success'),
52
+ title: 'Example - 2.2',
53
+ type: 'jsx',
54
+ content: <div className="p-2">Example 2.2 Content</div>,
55
+ },
56
+ ],
57
57
  };
58
58
  }
59
59
  function createAccordionItem3(): AccordionItem {
@@ -61,21 +61,17 @@ function createAccordionItem3(): AccordionItem {
61
61
  ...getItem(),
62
62
  icon: getIcon('hamburgerIcon', 'success'),
63
63
  title: 'Example - 3',
64
- content: {
65
- type: 'accordion',
66
- data: [
67
- createAccordionItem3_1(),
68
- {
69
- ...getItem(),
64
+ type: 'accordion',
65
+ content: [
66
+ createAccordionItem3_1(),
67
+ {
68
+ ...getItem(),
70
69
 
71
- title: 'Example - 3.2',
72
- content: {
73
- type: 'text',
74
- data: dummyText,
75
- },
76
- },
77
- ],
78
- },
70
+ title: 'Example - 3.2',
71
+ type: 'text',
72
+ content: dummyText,
73
+ },
74
+ ],
79
75
  };
80
76
  }
81
77
 
@@ -83,28 +79,22 @@ export function createAccordionItem3_1(): AccordionItem {
83
79
  return {
84
80
  ...getItem(),
85
81
  title: 'Example - 3.1',
86
- content: {
87
- type: 'accordion',
88
- allowMultipleExpanded: true,
89
- data: [
90
- {
91
- ...getItem(),
92
- title: 'Example - 3.1.1',
93
- content: {
94
- type: 'text',
95
- data: dummyText,
96
- },
97
- },
98
- {
99
- ...getItem(),
100
- title: 'Example - 3.1.2',
101
- content: {
102
- type: 'text',
103
- data: dummyText,
104
- },
105
- },
106
- ],
107
- },
82
+ allowMultipleExpanded: true,
83
+ type: 'accordion',
84
+ content: [
85
+ {
86
+ ...getItem(),
87
+ title: 'Example - 3.1.1',
88
+ type: 'text',
89
+ content: dummyText,
90
+ },
91
+ {
92
+ ...getItem(),
93
+ title: 'Example - 3.1.2',
94
+ type: 'text',
95
+ content: dummyText,
96
+ },
97
+ ],
108
98
  };
109
99
  }
110
100
 
@@ -113,20 +103,16 @@ function createAccordionItem4(): AccordionItem {
113
103
  ...getItem(),
114
104
  icon: getIcon(),
115
105
  title: 'Example - 4',
116
- content: {
117
- type: 'accordion',
118
- data: [
119
- createAccordionItem4_1(),
120
- {
121
- ...getItem(),
122
- title: 'Example - 4.2',
123
- content: {
124
- type: 'html',
125
- data: '<h2>Lorem ipsum dolor sit amet.</h2>',
126
- },
127
- },
128
- ],
129
- },
106
+ type: 'accordion',
107
+ content: [
108
+ createAccordionItem4_1(),
109
+ {
110
+ ...getItem(),
111
+ title: 'Example - 4.2',
112
+ type: 'html',
113
+ content: '<h2>Lorem ipsum dolor sit amet.</h2>',
114
+ },
115
+ ],
130
116
  };
131
117
  }
132
118
 
@@ -134,25 +120,22 @@ function createAccordionItem4_1(): AccordionItem {
134
120
  return {
135
121
  ...getItem(),
136
122
  title: 'Example - 4.1',
137
- content: {
138
- type: 'accordion',
139
- data: [
140
- {
141
- ...getItem(),
123
+ type: 'accordion',
124
+ content: [
125
+ {
126
+ ...getItem(),
142
127
 
143
- title: 'Example - 4.1.1',
144
- content: {
145
- type: 'text',
146
- data: dummyText,
147
- },
148
- },
149
- {
150
- ...getItem(),
151
- content: <div className="p-3">Example 4.1.2. content</div>,
152
- title: 'Example - 4.1.2',
153
- },
154
- ],
155
- },
128
+ title: 'Example - 4.1.1',
129
+ type: 'text',
130
+ content: dummyText,
131
+ },
132
+ {
133
+ ...getItem(),
134
+ type: 'jsx',
135
+ content: <div className="p-3">Example 4.1.2. content</div>,
136
+ title: 'Example - 4.1.2',
137
+ },
138
+ ],
156
139
  };
157
140
  }
158
141
  export function getAccordionData(): AccordionItem[] {
@@ -1,18 +1,14 @@
1
- import {ReactElement, ReactNode} from 'react';
2
- import {AdditionalProps} from '../common.types';
3
- import {NsIconNameType, NsIconProps} from '../icon';
4
- import {Variants} from '../typography';
5
- import {AccordionVariantType} from './enums';
6
-
7
- export interface ItemContent {
8
- type: 'text' | 'html' | 'accordion' | 'jsx';
9
- allowMultipleExpanded?: boolean;
10
- data: string | AccordionItem[];
11
- }
1
+ import { ReactElement, ReactNode } from 'react';
2
+ import { AdditionalProps } from '../common.types';
3
+ import { NsIconNameType, NsIconProps } from '../icon';
4
+ import { Variants } from '../typography';
5
+ import { AccordionVariantType } from './enums';
12
6
 
13
7
  export type AccordionItem = {
8
+ allowMultipleExpanded?: boolean;
9
+ type: 'text' | 'html' | 'accordion' | 'jsx';
14
10
  id: string;
15
- content: ItemContent | ReactElement;
11
+ content: string | AccordionItem[] | ReactElement;
16
12
  icon?: NsIconProps;
17
13
  title: string;
18
14
  isDefaultOpen?: boolean;
@@ -56,6 +52,8 @@ export type NsAccordionHeaderProps = AdditionalProps & {
56
52
  export type NsCollapseProps = AdditionalProps & {
57
53
  isOpen: boolean;
58
54
  isChild: boolean;
55
+ allowMultipleExpanded?: boolean;
56
+ type: 'text' | 'html' | 'accordion' | 'jsx';
59
57
  } & CommonAccordionType;
60
58
 
61
59
  export type NsToggleSectionProps = AdditionalProps & {
@@ -63,6 +61,7 @@ export type NsToggleSectionProps = AdditionalProps & {
63
61
  /** if true, NsToggle is rendered in open state, that collapsible section is visible */
64
62
  defaultOpen?: boolean;
65
63
  isChild: boolean;
64
+ type: 'text' | 'html' | 'accordion' | 'jsx';
66
65
  } & Pick<CommonAccordionType, 'invert' | 'variant' | 'content'>;
67
66
 
68
67
  export type NsAccordionItemProps = AdditionalProps & {
@@ -77,4 +76,6 @@ export type NsAccordionItemProps = AdditionalProps & {
77
76
  closedIconName?: NsIconNameType;
78
77
  startIcon?: NsIconProps;
79
78
  isChild: boolean;
79
+ type: 'text' | 'html' | 'accordion' | 'jsx';
80
+ allowMultipleExpanded?: boolean;
80
81
  } & CommonAccordionType;
@@ -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,33 +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
- // eslint-disable-next-line max-len
23
- 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.',
24
- topImageUrl:
25
- // eslint-disable-next-line max-len
26
- '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`,
27
58
  topImageAlt: 'Force for Good Foundation',
28
59
  additionalProps: {
29
60
  testid: 'ffg-card',
30
61
  },
62
+ onClick: () => {
63
+ d.count = 1;
64
+ console.log('on click called');
65
+ },
31
66
  },
32
- play: async ({ canvasElement }) => {
67
+ play: async ({ canvasElement }: any) => {
68
+ d.count = 0;
33
69
  const canvas = within(canvasElement);
34
- await userEvent.hover(canvas.getByTestId('ffg-card'));
35
- await userEvent.hover(canvas.getByRole('link'));
36
- expect(
37
- canvas.getByText(
38
- // eslint-disable-next-line max-len
39
- '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.'
40
- )
41
- ).toBeInTheDocument();
70
+ userEvent.click(canvas.getByTestId('ffg-card'));
71
+ expect(d.count).toEqual(1);
42
72
  },
43
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
  };
@@ -1,8 +1,6 @@
1
1
  import { FoundationTheme } from '@nuskin/foundation-theme';
2
2
 
3
- export type ContentStackLiveTags = {
4
- 'data-cslp'?: string;
5
- };
3
+ export type CslpTag = { 'data-cslp': string };
6
4
 
7
5
  export type AdditionalProps = {
8
6
  additionalProps?: {
@@ -10,7 +8,8 @@ export type AdditionalProps = {
10
8
  testid?: string;
11
9
  className?: string;
12
10
  'data-testid'?: string;
13
- } & ContentStackLiveTags;
11
+ } & Partial<CslpTag>;
12
+ cslp?: Record<string, CslpTag>;
14
13
  } & DarkModeEnabledOption;
15
14
 
16
15
  export type Themed = {
@@ -13,6 +13,7 @@ export * from './column-control';
13
13
  export * from './checkbox';
14
14
  export * from './common.types.d';
15
15
  export * from './dropdown';
16
+ export * from './email-simple';
16
17
  export * from './flag';
17
18
  export * from './hooks';
18
19
  export * from './icon';
@@ -20,11 +21,12 @@ export * from './image';
20
21
  export * from './input';
21
22
  export * from './label';
22
23
  export * from './link';
24
+ export * from './modal';
23
25
  export * from './nav-tab';
24
26
  export * from './nav-product-card';
27
+ export * from './radiogroup';
28
+ export * from './spinner';
25
29
  export * from './text-strip';
26
30
  export * from './table';
27
31
  export * from './typography';
28
- export * from './email-simple';
29
- export * from './radiogroup';
30
- export * from './spinner';
32
+ export * from './utility';
@@ -0,0 +1,46 @@
1
+ import React from 'react';
2
+ import { render } from '@/test-utils/index';
3
+ import NsModal from './NsModal';
4
+ import { NsModalData } from './stories/mock';
5
+ import { NsModalProps } from './types';
6
+
7
+ describe('NsModal', () => {
8
+ const onHandleClose = jest.fn();
9
+
10
+ const NsModalProp = NsModalData as NsModalProps;
11
+
12
+ test('1. check NsModal component open', () => {
13
+ const { getByTestId } = render(<NsModal {...NsModalProp} handleClose={onHandleClose} />);
14
+ expect(getByTestId('nsmodal-dialog')).toBeInTheDocument();
15
+ });
16
+
17
+ test('2. should render NsModal default component', () => {
18
+ const { getByTestId } = render(<NsModal {...NsModalProp} handleClose={onHandleClose} />);
19
+ expect(getByTestId('modal-default')).toBeInTheDocument();
20
+ });
21
+
22
+ test('3. should render NsModal status component', () => {
23
+ const VariantProps: NsModalProps = {
24
+ ...NsModalProp,
25
+ variant: 'info',
26
+ };
27
+ const { getByTestId } = render(<NsModal {...VariantProps} handleClose={onHandleClose} />);
28
+ expect(getByTestId('modal-status')).toBeInTheDocument();
29
+ });
30
+
31
+ test('4. should render NsModal title with close button', () => {
32
+ const { getByTestId } = render(<NsModal {...NsModalProp} handleClose={onHandleClose} />);
33
+ expect(getByTestId('modal-title')).toBeInTheDocument();
34
+ expect(getByTestId('modal-close-button')).toBeInTheDocument();
35
+ });
36
+
37
+ test('5. should render NsModal body content', () => {
38
+ const { getByTestId } = render(<NsModal {...NsModalProp} handleClose={onHandleClose} />);
39
+ expect(getByTestId('modal-body-content')).toBeInTheDocument();
40
+ });
41
+
42
+ test('6. should render NsModal footer', () => {
43
+ const { getByTestId } = render(<NsModal {...NsModalProp} handleClose={onHandleClose} />);
44
+ expect(getByTestId('modal-footer')).toBeInTheDocument();
45
+ });
46
+ });
@@ -0,0 +1,28 @@
1
+ import { styled } from '@nuskin/foundation-theme';
2
+ import { NsButton } from '../button';
3
+ import { DialogActions } from '@mui/material';
4
+
5
+ export const NsInfoWrapper = styled.div`
6
+ display: flex;
7
+ .status-icon {
8
+ padding: 16px 0px 0px 24px;
9
+ }
10
+ .title-icon {
11
+ padding-right: 10px;
12
+ }
13
+ `;
14
+
15
+ export const CloseButton = styled(NsButton)`
16
+ position: absolute;
17
+ right: 8px;
18
+ top: 8px;
19
+ `;
20
+
21
+ export const ModalFooter = styled(DialogActions)`
22
+ display: flex;
23
+ justify-content: space-around;
24
+ padding: 20px 0px 10px 0px;
25
+ button {
26
+ width: 100%;
27
+ }
28
+ `;
@@ -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;