@nuskin/foundation-ui-components 1.14.0 → 1.16.0-cx130-990.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.
package/README.md CHANGED
@@ -1,39 +1,122 @@
1
+ <div align="right">
2
+ <a href='https://code.tls.nuskin.io/ns-am/content-foundation/foundation-ui-components/badges/master/pipeline.svg'><img src='https://code.tls.nuskin.io/ns-am/content-foundation/foundation-ui-components/badges/master/pipeline.svg' alt='Pipeline Badge' /></a>
3
+ <a href='https://code.tls.nuskin.io/ns-am/content-foundation/foundation-ui-components/-/badges/release.svg'><img src='https://code.tls.nuskin.io/ns-am/content-foundation/foundation-ui-components/-/badges/release.svg' alt='Latest Release Badge' /></a>
4
+ <a href='https://img.shields.io/npm/dt/%40nuskin/foundation-ui-components'><img src='https://img.shields.io/npm/dt/%40nuskin/foundation-ui-components' alt='Downloads Badge' /></a>
5
+ </div>
6
+
1
7
  # @nuskin/foundation-ui-components
2
8
 
3
- This is a library that contains react components used in NuSkin Pages
9
+ This comprehensive library houses a collection of reusable React components specifically designed for NuSkin Pages. These components are meticulously crafted to ensure consistent UI/UX across all NuSkin digital properties, fostering a seamless user experience.
10
+
11
+ ## Releases
12
+
13
+ ### [CHANGELOG](https://code.tls.nuskin.io/ns-am/content-foundation/foundation-ui-components/-/blob/master/CHANGELOG.md)
14
+
15
+ ## Installation Guide
16
+
17
+ To integrate the NuSkin React Components Library into your NuSkin Pages project, follow these steps:
18
+
19
+ ### Clone the repository to your local machine
20
+
21
+ ```shell
22
+ git clone git@code.tls.nuskin.io:ns-am/content-foundation/foundation-ui-components.git
23
+ ```
4
24
 
5
- ## Installing
25
+ ## Running the project
6
26
 
7
- Usng npm:
27
+ ### Run the main application using yarn
8
28
 
9
- ```bash
10
- npm add @nuskin/foundation-ui-components
29
+ ```shell
30
+ yarn dev
11
31
  ```
12
32
 
13
- Usng yarn:
33
+ ### Storybook
34
+
35
+ See how React components look and behave in isolation using Storybook. To get started, follow these steps:
14
36
 
15
- ```bash
16
- yarn add @nuskin/foundation-ui-components
37
+ #### Run storybook using yarn.
38
+
39
+ ```shell
40
+ yarn storybook
17
41
  ```
18
42
 
19
- ## Example usage
43
+ #### To view the Storybook, use the following URLs
44
+
45
+ | Environment | URL |
46
+ | ----------- | ------------------------------------------------------- |
47
+ | Local | http://localhost:6007 |
48
+ | Test | https://test.nuskin.com/static/foundation-ui-components |
20
49
 
21
- ```ts
22
- import { Button } from "@nuskin/foundation-ui-components";
50
+ ## Usage
23
51
 
52
+ The following example illustrates how to use this project
53
+
54
+ ```shell
55
+ import { NsButton } from '@nuskin/foundation-ui-components';
24
56
  const Page = () => {
25
57
  return (
26
- <Button variant="contained" color="primary">
58
+ <NsButton variant="contained" color="primary">
27
59
  Sample
28
- </Button>
60
+ </NsButton>
29
61
  );
30
62
  };
31
63
  ```
32
64
 
33
- ## Resources
65
+ ## Dependencies
66
+
67
+ This project relies on the following dependencies:
68
+
69
+ **Emotion UI Libraries**
70
+
71
+ - `@emotion/react@^11.11.1`
72
+ - `@emotion/styled@^11.11.0`
73
+
74
+ **Material-UI Libraries**
75
+
76
+ - `@mui/material@5.14.16`
77
+ - `@mui/icons-material@^5.14.16`
78
+ - `@mui/utils@^5.14.16`
79
+
80
+ **NuSkin Foundation Theme**
81
+
82
+ - `@nuskin/foundation-theme@1.2.0`
83
+
84
+ **Carousel Libraries**
85
+
86
+ - `react-material-ui-carousel@^3.4.2`
87
+ - `react-slick@^0.29.0`
88
+ - `slick-carousel@^1.8.1`
89
+
90
+ **Other Libraries**
91
+
92
+ - `cliui@^8.0.1`
93
+ - `framer-motion@^10.16.4`
94
+
95
+ ## Testing
96
+
97
+ We use Jest for testing our project. Below are the available test scripts:
98
+
99
+ - Run all tests and generate coverage report:\*\*
100
+ ```bash
101
+ yarn test
102
+ ```
103
+ - Run tests for a specific pattern (e.g., accordion/\*):
104
+ ```bash
105
+ yarn run test:pattern
106
+ ```
107
+ - Run only failed tests from the last test run:
108
+ ```bash
109
+ yarn run test:failed
110
+ ```
111
+ - Generate and view code coverage report:
112
+
113
+ ```bash
114
+ yarn run test:coverage
115
+ ```
34
116
 
35
- - 0.1.0 - Initial commit
117
+ - The yarn test script builds the project using Next.js before running Jest tests.
118
+ - Feel free to customize the test patterns or add additional options as needed.
36
119
 
37
- ## License
120
+ ### Coverage Report:
38
121
 
39
- [MIT](https://opensource.org/licenses/MIT)
122
+ After running tests, open the `index.html` file in the `coverage` directory to view the coverage report.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuskin/foundation-ui-components",
3
- "version": "1.14.0",
3
+ "version": "1.16.0-cx130-990.1",
4
4
  "description": "It is a foundation library written in react, that provides common components to all UI pages",
5
5
  "main": "src/common/index.ts",
6
6
  "repository": {
@@ -46,7 +46,7 @@
46
46
  "@mui/material": "5.14.16",
47
47
  "@mui/utils": "^5.14.16",
48
48
  "@next/font": "13.5.6",
49
- "@nuskin/foundation-theme": "1.2.0",
49
+ "@nuskin/foundation-theme": "1.3.0-cx130-596.3",
50
50
  "@types/react": "^18.2.34",
51
51
  "@types/react-dom": "^18.2.14",
52
52
  "cliui": "^8.0.1",
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable max-len */
2
- import { styled, css, ColorUtils, FoundationTheme } from '@nuskin/foundation-theme';
2
+ import { styled, ColorUtils, FoundationTheme } from '@nuskin/foundation-theme';
3
3
 
4
4
  const { color } = ColorUtils;
5
5
 
@@ -43,12 +43,6 @@ export const AlertContainer = styled.div<AlertContainerParams>`
43
43
  }
44
44
  text-align: left;
45
45
  `;
46
- //[Todo-Arun] - Fonts should be driven through @next/font and according to theme
47
- const fontFamilyStyles = css`
48
- font-family: 'proxima-nova', 'OpenSans', 'Pridi', 'NotoSans', 'NotoSansSC', 'NotoSansHebrew', 'NotoSansJapanese',
49
- 'Hiragino Kaku Gothic Pro', 'Yu Gothic Medium', 'Yu Gothic', Meiryo, 'source-han-sans-japanese',
50
- 'source-han-sans-korean', 'source-han-sans-simplified-c', Helvetica, Arial, sans-serif;
51
- `;
52
46
 
53
47
  export const Alert = styled.div<AlertParams>`
54
48
  position: relative;
@@ -90,12 +84,8 @@ export const AlertHead = styled.div`
90
84
  display: flex;
91
85
  flex-direction: column;
92
86
  justify-content: center;
93
- span {
94
- ${fontFamilyStyles}
87
+ .alert-head-title {
95
88
  color: ${color('primary', 'black')};
96
- font-weight: 600;
97
- font-size: 18px;
98
- line-height: 20px;
99
89
  }
100
90
  `;
101
91
 
@@ -110,14 +100,14 @@ export const AlertFoot = styled.div<{ type: AlertType }>`
110
100
  margin-top: 8px;
111
101
  color: ${color('primary', 'black')};
112
102
  display: ${({ type }) => TypeMap?.[type]?.['footDisplay']};
113
- ${fontFamilyStyles}
103
+ font-family: ${({ theme }) => theme?.fonts?.sectionFonts?.body};
114
104
  font-weight: 300;
115
105
  font-size: 14px;
116
106
  line-height: 18px;
117
107
  `;
118
108
 
119
109
  export const AlertBody = styled.div`
120
- ${fontFamilyStyles}
110
+ font-family: ${({ theme }) => theme?.fonts?.sectionFonts?.body};
121
111
  font-weight: 300;
122
112
  font-size: 16px;
123
113
  line-height: 21px;
@@ -15,6 +15,7 @@ import type { NsAlertProps, ContextType, AlertType } from './types.d';
15
15
  import { NsIcon } from '../icon';
16
16
  import Header, { colorMap, iconMap } from './Header';
17
17
  import useWindowSize from '../hooks/useWindowSize';
18
+ import { NsTypography } from '../typography';
18
19
 
19
20
  export default function NsAlert({
20
21
  context = 'info',
@@ -57,7 +58,11 @@ export default function NsAlert({
57
58
  />
58
59
  </AlertIcon>
59
60
  <AlertHead>
60
- <Header head={<span>{title}</span>}>{head}</Header>
61
+ <Header head={
62
+ <NsTypography variant="body-xl" className='alert-head-title' weight="bold" noSpacing>
63
+ {title}
64
+ </NsTypography>
65
+ }>{head}</Header>
61
66
  </AlertHead>
62
67
  {hasDismissListener && (
63
68
  <AlertCloseButton data-testid="alert-close-button" onClick={onDismiss}>
@@ -1,7 +1,4 @@
1
- import {
2
- NsButton,
3
- NsIcon,
4
- } from '../';
1
+ import { NsButton, NsIcon } from '../';
5
2
  import { NsCardButton } from './types';
6
3
 
7
4
  const CardButton = ({
@@ -12,6 +9,7 @@ const CardButton = ({
12
9
  buttonVariant = 'outlined',
13
10
  buttonColor = 'primary',
14
11
  fullWidth = false,
12
+ showArrowWithText = false,
15
13
  }: NsCardButton) => {
16
14
  if (showButton && url) {
17
15
  return (
@@ -22,7 +20,7 @@ const CardButton = ({
22
20
  variant={buttonVariant}
23
21
  fullWidth={fullWidth}
24
22
  endIcon={
25
- buttonVariant === 'text' ? (
23
+ showArrowWithText && buttonVariant === 'text' ? (
26
24
  <NsIcon name="arrowRight" size="small" color="primary" />
27
25
  ) : endIcon ? (
28
26
  <NsIcon name={endIcon} color={buttonColor} />
@@ -14,6 +14,7 @@ type NsMediumCardProps = {
14
14
  button?: NsCardButton;
15
15
  className?: string;
16
16
  fluid?: boolean;
17
+ showArrowWithButtonText?: boolean;
17
18
  };
18
19
  const textVariantButton = {
19
20
  padding: '0 0 4px',
@@ -76,6 +77,7 @@ export default function NsMediumCard({
76
77
  button,
77
78
  className,
78
79
  fluid,
80
+ showArrowWithButtonText = false,
79
81
  }: NsMediumCardProps) {
80
82
  return (
81
83
  <CardContainer
@@ -92,7 +94,7 @@ export default function NsMediumCard({
92
94
  {title}
93
95
  </NsTypography>
94
96
  <article className="subtitle">{subtitle}</article>
95
- {button ? <CardButton {...button} /> : null}
97
+ {button ? <CardButton {...button} showArrowWithText={showArrowWithButtonText} /> : null}
96
98
  </div>
97
99
  </CardContainer>
98
100
  );
@@ -21,4 +21,5 @@ export type NsCardButton = {
21
21
  buttonText: string;
22
22
  buttonVariant?: 'text' | 'outlined' | 'contained';
23
23
  buttonColor?: 'secondary' | 'primary';
24
+ showArrowWithText?: boolean;
24
25
  };
@@ -4,9 +4,6 @@ const GlobalFontInter = () => (
4
4
  <GlobalStyles
5
5
  styles={css`
6
6
  @import url('https://fonts.googleapis.com/css2?family=Inter');
7
- body {
8
- font-family: 'Inter', sans-serif;
9
- }
10
7
  `}
11
8
  />
12
9
  );
@@ -24,7 +24,7 @@ describe('GlobalFontInter', () => {
24
24
  weight="bold"
25
25
  className="mt-2"
26
26
  decoration="underline"
27
- fontStyle="italic"
27
+
28
28
  color="primary"
29
29
  >
30
30
  {text}
@@ -41,7 +41,6 @@ describe('GlobalFontInter', () => {
41
41
  weight="bold"
42
42
  className="mt-2"
43
43
  decoration="underline"
44
- fontStyle="italic"
45
44
  color="accentColorA"
46
45
  >
47
46
  {text}
@@ -1,125 +1,153 @@
1
- import { styled, ColorUtils } from '@nuskin/foundation-theme';
1
+ import { styled, ColorUtils, FoundationTheme } from '@nuskin/foundation-theme';
2
2
  import { NsTypographyProps } from './types.d';
3
3
 
4
4
  const { paletteColor } = ColorUtils;
5
5
 
6
- const variantStyles = {
6
+ type TypographyConfig = {
7
+ fontFamily: string;
8
+ fontSize?: number;
9
+ lineHeight?: number;
10
+ letterSpacingPercentage?: number;
11
+ paragraphSpacing?: number;
12
+ fontWeight?: number;
13
+ };
14
+
15
+ const defaultFont = 'Roboto';
16
+ const defaultTypographyStyles = {
7
17
  h1: {
8
- 'font-size': '42px',
9
- 'line-height': '48px',
10
- 'letter-spacing': '0px',
11
- margin: '0px',
18
+ fontFamily: defaultFont,
19
+ fontSize: 42,
20
+ lineHeight: 48,
21
+ letterSpacingPercentage: 0,
22
+ paragraphSpacing: 0,
12
23
  },
13
24
  h2: {
14
- 'font-size': '36px',
15
- 'line-height': '42px',
16
- 'letter-spacing': '0px',
17
- margin: '0px',
25
+ fontFamily: defaultFont,
26
+ fontSize: 36,
27
+ lineHeight: 42,
28
+ letterSpacingPercentage: 0,
29
+ paragraphSpacing: 0,
18
30
  },
19
31
  h3: {
20
- 'font-size': '32px',
21
- 'line-height': '38px',
22
- 'letter-spacing': '0px',
23
- margin: '0px',
32
+ fontFamily: defaultFont,
33
+ fontSize: 32,
34
+ lineHeight: 38,
35
+ letterSpacingPercentage: 0,
36
+ paragraphSpacing: 0,
24
37
  },
25
38
  h4: {
26
- 'font-size': '26px',
27
- 'line-height': '34px',
28
- 'letter-spacing': '0px',
29
- margin: '0px',
39
+ fontFamily: defaultFont,
40
+ fontSize: 26,
41
+ lineHeight: 34,
42
+ letterSpacingPercentage: 0,
43
+ paragraphSpacing: 0,
30
44
  },
31
45
  h5: {
32
- 'font-size': '22px',
33
- 'line-height': '28px',
34
- 'letter-spacing': '0px',
35
- 'font-weight': '700',
36
- margin: '0px',
46
+ fontFamily: defaultFont,
47
+ fontSize: 22,
48
+ lineHeight: 28,
49
+ letterSpacingPercentage: 0,
50
+ fontWeight: 700,
51
+ paragraphSpacing: 0,
37
52
  },
38
53
  h6: {
39
- 'font-size': '18px',
40
- 'line-height': '24px',
41
- 'letter-spacing': '0px',
42
- 'font-weight': '600',
43
- margin: '0px',
54
+ fontFamily: defaultFont,
55
+ fontSize: 18,
56
+ lineHeight: 24,
57
+ letterSpacingPercentage: 0,
58
+ fontWeight: 600,
59
+ paragraphSpacing: 0,
44
60
  },
45
61
  'title-l': {
46
- 'font-size': '22px',
47
- 'line-height': '28px',
48
- 'letter-spacing': '2px',
49
- 'font-weight': '700',
50
- margin: '0px',
62
+ fontFamily: defaultFont,
63
+ fontSize: 22,
64
+ lineHeight: 28,
65
+ letterSpacingPercentage: 2,
66
+ fontWeight: 700,
67
+ paragraphSpacing: 0,
51
68
  },
52
69
  'title-m': {
53
- 'font-size': '16px',
54
- 'line-height': '20px',
55
- 'letter-spacing': '4px',
56
- 'font-weight': '700',
57
- margin: '0px',
70
+ fontFamily: defaultFont,
71
+ fontSize: 16,
72
+ lineHeight: 20,
73
+ letterSpacingPercentage: 4,
74
+ fontWeight: 700,
75
+ paragraphSpacing: 0,
58
76
  },
59
77
  'title-s': {
60
- 'font-size': '16px',
61
- 'line-height': '16px',
62
- 'letter-spacing': '4px',
63
- 'font-weight': '700',
64
- margin: '0px',
78
+ fontFamily: defaultFont,
79
+ fontSize: 16,
80
+ lineHeight: 16,
81
+ letterSpacingPercentage: 4,
82
+ fontWeight: 700,
83
+ paragraphSpacing: 0,
65
84
  },
66
85
  'label-l': {
67
- 'font-size': '20px',
68
- 'line-height': '26px',
69
- 'letter-spacing': '0px',
70
- 'font-weight': '600',
71
- margin: '8px',
86
+ fontFamily: defaultFont,
87
+ fontSize: 20,
88
+ lineHeight: 26,
89
+ letterSpacingPercentage: 0,
90
+ fontWeight: 600,
91
+ paragraphSpacing: 8,
72
92
  },
73
93
  'label-m': {
74
- 'font-size': '16px',
75
- 'line-height': '22px',
76
- 'letter-spacing': '0px',
77
- 'font-weight': '600',
78
- margin: '8px',
94
+ fontFamily: defaultFont,
95
+ fontSize: 16,
96
+ lineHeight: 22,
97
+ letterSpacingPercentage: 0,
98
+ fontWeight: 600,
99
+ paragraphSpacing: 8,
79
100
  },
80
101
  'label-s': {
81
- 'font-size': '14px',
82
- 'line-height': '20px',
83
- 'letter-spacing': '0px',
84
- 'font-weight': '700',
85
- margin: '6px',
102
+ fontFamily: defaultFont,
103
+ fontSize: 14,
104
+ lineHeight: 20,
105
+ letterSpacingPercentage: 0,
106
+ fontWeight: 700,
107
+ paragraphSpacing: 6,
86
108
  },
87
109
  'body-xl': {
88
- 'font-size': '18px',
89
- 'line-height': '22px',
90
- 'letter-spacing': '0px',
91
- margin: '22px',
110
+ fontFamily: defaultFont,
111
+ fontSize: 18,
112
+ lineHeight: 22,
113
+ letterSpacingPercentage: 0,
114
+ paragraphSpacing: 22,
92
115
  },
93
116
  'body-l': {
94
- 'font-size': '16px',
95
- 'line-height': '22px',
96
- 'letter-spacing': '0px',
97
- margin: '20px',
117
+ fontFamily: defaultFont,
118
+ fontSize: 16,
119
+ lineHeight: 22,
120
+ letterSpacingPercentage: 0,
121
+ paragraphSpacing: 20,
98
122
  },
99
123
  'body-m': {
100
- 'font-size': '14px',
101
- 'line-height': '20px',
102
- 'letter-spacing': '0px',
103
- margin: '18px',
124
+ fontFamily: defaultFont,
125
+ fontSize: 14,
126
+ lineHeight: 20,
127
+ letterSpacingPercentage: 0,
128
+ paragraphSpacing: 18,
104
129
  },
105
130
  'body-s': {
106
- 'font-size': '12px',
107
- 'line-height': '16px',
108
- 'letter-spacing': '1px',
109
- margin: '16px',
131
+ fontFamily: defaultFont,
132
+ fontSize: 12,
133
+ lineHeight: 16,
134
+ letterSpacingPercentage: 1,
135
+ paragraphSpacing: 16,
110
136
  },
111
137
  'body-xs': {
112
- 'font-size': '10px',
113
- 'line-height': '14px',
114
- 'letter-spacing': '2px',
115
- margin: '14px',
138
+ fontFamily: defaultFont,
139
+ fontSize: 10,
140
+ lineHeight: 14,
141
+ letterSpacingPercentage: 2,
142
+ paragraphSpacing: 14,
116
143
  },
117
144
  CTA: {
118
- 'font-size': '14px',
119
- 'line-height': '20px',
120
- 'letter-spacing': '0.14px',
121
- 'font-weight': '600',
122
- margin: '0px',
145
+ fontFamily: defaultFont,
146
+ fontSize: 14,
147
+ lineHeight: 20,
148
+ letterSpacingPercentage: 0.14,
149
+ fontWeight: 600,
150
+ paragraphSpacing: 0,
123
151
  },
124
152
  };
125
153
 
@@ -129,17 +157,37 @@ const fontWeightMap = {
129
157
  bold: 600,
130
158
  };
131
159
 
160
+ const getVariantStyle = (
161
+ themeTypographyVariants: Record<FoundationTheme.TypographyVariants, TypographyConfig>,
162
+ variant: FoundationTheme.TypographyVariants
163
+ ) => {
164
+ const variantStyles = themeTypographyVariants[variant as FoundationTheme.TypographyVariants];
165
+ if (variantStyles) {
166
+ return variantStyles;
167
+ }
168
+ return defaultTypographyStyles[variant as FoundationTheme.TypographyVariants];
169
+ };
170
+
132
171
  export const StyledTypography = styled('div')<NsTypographyProps>(
133
- ({ theme, weight = 'normal', variant = 'h1', noSpacing, decoration, color, colorOverride }) => {
134
- const fontStyles = variantStyles[variant];
172
+ ({ theme, weight, variant, noSpacing, decoration, color, colorOverride }) => {
173
+ const fontStyles: TypographyConfig = getVariantStyle(theme.fonts.typographyVariants, variant) || {};
135
174
  if (noSpacing) {
136
- fontStyles.margin = '0px';
175
+ fontStyles.paragraphSpacing = 0;
176
+ }
177
+ if (weight) {
178
+ fontStyles.fontWeight = fontWeightMap[weight] || fontWeightMap.normal;
137
179
  }
180
+ const updatedFontStyle = {
181
+ fontFamily: fontStyles?.fontFamily || defaultFont,
182
+ fontSize: `${fontStyles?.fontSize || 16}px`,
183
+ lineHeight: `${fontStyles?.lineHeight || 16}px`,
184
+ margin: fontStyles?.paragraphSpacing || 0,
185
+ fontWeight: fontStyles?.fontWeight || 400,
186
+ letterSpacing: fontStyles?.letterSpacingPercentage || 0,
187
+ };
138
188
  return {
139
- ...fontStyles,
140
- fontFamily: 'Inter',
189
+ ...updatedFontStyle,
141
190
  textDecorationLine: decoration,
142
- fontWeight: fontWeightMap[weight],
143
191
  color: colorOverride?.startsWith('#') ? colorOverride : paletteColor(color)({ theme }),
144
192
  };
145
193
  }