@nuskin/foundation-ui-components 1.9.2 → 1.9.4

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 (50) hide show
  1. package/package.json +6 -6
  2. package/src/common/autocomplete/NsAutocomplete.spec.tsx +22 -28
  3. package/src/common/autocomplete/NsAutocomplete.styled.tsx +6 -8
  4. package/src/common/autocomplete/NsAutocomplete.tsx +14 -8
  5. package/src/common/autocomplete/helper/LineLoader.tsx +37 -0
  6. package/src/common/autocomplete/helper/RecentClearAll.tsx +36 -0
  7. package/src/common/autocomplete/helper/SeeMoreButton.tsx +31 -4
  8. package/src/common/autocomplete/helper/index.ts +4 -0
  9. package/src/common/autocomplete/helper/renderGroupName.tsx +0 -1
  10. package/src/common/autocomplete/mock/MockData.ts +13 -14
  11. package/src/common/autocomplete/mock/MockUI.tsx +4 -5
  12. package/src/common/autocomplete/types.d.ts +1 -0
  13. package/src/common/card/CardButton.tsx +31 -0
  14. package/src/common/card/NsAwardCard.tsx +8 -5
  15. package/src/common/card/NsBrandCard.tsx +8 -17
  16. package/src/common/card/NsCheckoutCard.tsx +8 -7
  17. package/src/common/card/NsHeroCardLevel1.tsx +39 -50
  18. package/src/common/card/NsHeroCardLevel2.tsx +28 -67
  19. package/src/common/card/NsIconText.tsx +4 -4
  20. package/src/common/card/NsLargeCard.tsx +28 -55
  21. package/src/common/card/NsMediumCard.tsx +10 -21
  22. package/src/common/card/NsPost.tsx +13 -8
  23. package/src/common/card/NsSmallFullCard.tsx +13 -22
  24. package/src/common/card/NsXLargeCard.tsx +12 -11
  25. package/src/common/card/cardSizes.ts +4 -4
  26. package/src/common/card/specs/NsAwardCard.spec.tsx +29 -0
  27. package/src/common/card/specs/NsBrandCard.spec.tsx +18 -31
  28. package/src/common/card/specs/NsCheckoutCard.spec.tsx +4 -15
  29. package/src/common/card/specs/NsHeroCardLevel1.spec.tsx +16 -24
  30. package/src/common/card/specs/NsHeroCardLevel2.spec.tsx +18 -20
  31. package/src/common/card/specs/NsIconText.spec.tsx +0 -3
  32. package/src/common/card/specs/NsLargeCard.spec.tsx +26 -19
  33. package/src/common/card/specs/NsMediumCard.spec.tsx +28 -12
  34. package/src/common/card/specs/NsPost.spec.tsx +8 -11
  35. package/src/common/card/specs/NsSmallFullCard.spec.tsx +23 -12
  36. package/src/common/card/specs/NsXLargeCard.spec.tsx +23 -11
  37. package/src/common/card/stories/NsAwardCard.stories.tsx +0 -3
  38. package/src/common/card/stories/NsBrandCard.stories.tsx +8 -3
  39. package/src/common/card/stories/NsCheckoutCard.stories.tsx +3 -4
  40. package/src/common/card/stories/NsHeroCardLevel1.stories.tsx +11 -24
  41. package/src/common/card/stories/NsHeroCardLevel2.stories.tsx +10 -29
  42. package/src/common/card/stories/NsIconText.stories.tsx +2 -20
  43. package/src/common/card/stories/NsLargeCard.stories.tsx +8 -7
  44. package/src/common/card/stories/NsMediumCard.stories.tsx +7 -6
  45. package/src/common/card/stories/NsPost.stories.tsx +2 -19
  46. package/src/common/card/stories/NsSmallFullCard.stories.tsx +7 -4
  47. package/src/common/card/stories/NsXLargeCard.stories.tsx +8 -4
  48. package/src/common/card/types.d.ts +12 -0
  49. package/src/common/carousal/RenderBrand.tsx +0 -1
  50. package/src/common/autocomplete/helper/AutoCompleteButton.tsx +0 -24
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuskin/foundation-ui-components",
3
- "version": "1.9.2",
3
+ "version": "1.9.4",
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": {
@@ -42,12 +42,12 @@
42
42
  "dependencies": {
43
43
  "@emotion/react": "^11.11.1",
44
44
  "@emotion/styled": "^11.11.0",
45
- "@mui/icons-material": "^5.14.14",
46
- "@mui/material": "5.14.14",
47
- "@mui/utils": "^5.14.14",
45
+ "@mui/icons-material": "^5.14.16",
46
+ "@mui/material": "5.14.16",
47
+ "@mui/utils": "^5.14.16",
48
48
  "@next/font": "13.5.6",
49
49
  "@nuskin/foundation-theme": "1.2.0",
50
- "@types/react": "^18.2.30",
50
+ "@types/react": "^18.2.34",
51
51
  "@types/react-dom": "^18.2.14",
52
52
  "cliui": "^8.0.1",
53
53
  "framer-motion": "^10.16.4",
@@ -79,7 +79,7 @@
79
79
  "@testing-library/jest-dom": "^6.1.4",
80
80
  "@testing-library/react": "^14.0.0",
81
81
  "@testing-library/react-hooks": "^8.0.1",
82
- "@types/jest": "^29.5.6",
82
+ "@types/jest": "^29.5.7",
83
83
  "@types/lodash": "^4.14.200",
84
84
  "@types/node": "^20.8.7",
85
85
  "@types/ramda": "^0.29.7",
@@ -2,9 +2,9 @@ import { render, screen, waitFor } from '@/test-utils/index';
2
2
  import userEvent from '@testing-library/user-event';
3
3
  import React from 'react';
4
4
 
5
- import { AutocompleteMockList } from './mock/MockData';
6
- import { OptionUiComponent } from './mock/MockUI';
7
- import NsAutocomplete from './NsAutocomplete';
5
+ import { AutocompleteMockList } from '../autocomplete/mock/MockData';
6
+ import { OptionUiComponent } from '../autocomplete/mock/MockUI';
7
+ import NsAutocomplete from '../autocomplete/NsAutocomplete';
8
8
 
9
9
  const commonProps = {
10
10
  value: '',
@@ -14,6 +14,7 @@ const commonProps = {
14
14
  options: AutocompleteMockList,
15
15
  placeholder: 'autocomplete-input',
16
16
  OptionsUI: OptionUiComponent,
17
+ // renderOption: (props: any) => <li {...props}>{props.value}</li>,
17
18
  };
18
19
  describe('CustomAutocomplete', () => {
19
20
  it('1. should render autocomplete component', () => {
@@ -47,7 +48,7 @@ describe('CustomAutocomplete', () => {
47
48
  it('4. selects an option when clicking on it', async () => {
48
49
  const onChangeMock = jest.fn();
49
50
  render(<NsAutocomplete {...commonProps} onChange={onChangeMock} />);
50
- const autocompleteInput = screen.getByPlaceholderText('autocomplete-input');
51
+ const autocompleteInput = screen.getByPlaceholderText(commonProps.placeholder);
51
52
  await userEvent.type(autocompleteInput, 'GS Facial');
52
53
  await waitFor(async () => {
53
54
  const optionLi = screen.getByText('GS Facial Spa');
@@ -57,39 +58,32 @@ describe('CustomAutocomplete', () => {
57
58
  }, 40000);
58
59
 
59
60
  it('5. should load more options when clicking load more button', async () => {
60
- render(
61
- <NsAutocomplete
62
- seeMore={{
63
- text: '',
64
- show: true,
65
- onSeeMore: () => ({}),
66
- }}
67
- {...commonProps}
68
- />
69
- );
70
- const autocompleteInput = screen.getByPlaceholderText('autocomplete-input');
61
+ const seeMore = {
62
+ text: 'See More',
63
+ show: true,
64
+ onSeeMore: jest.fn(),
65
+ };
66
+ render(<NsAutocomplete seeMore={seeMore} {...commonProps} />);
67
+ const autocompleteInput = screen.getByPlaceholderText(commonProps.placeholder);
71
68
  await userEvent.type(autocompleteInput, 'GS Facial');
72
69
  await waitFor(async () => {
73
- const loadMoreButton = screen.getByTestId('autocomplete-loadmore-id');
70
+ const loadMoreButton = screen.getByText(seeMore.text);
74
71
  await userEvent.click(loadMoreButton);
75
72
  });
73
+ expect(seeMore.onSeeMore).toHaveBeenCalled();
76
74
  }, 40000);
77
75
 
78
76
  it('6. should clear options when clicking clear button', async () => {
79
- render(
80
- <NsAutocomplete
81
- clear={{
82
- text: '',
83
- show: true,
84
- onClear: () => ({}),
85
- }}
86
- {...commonProps}
87
- />
88
- );
89
- const autocompleteInput = screen.getByPlaceholderText('autocomplete-input');
77
+ const clear = {
78
+ text: 'Clear All',
79
+ show: true,
80
+ onClear: jest.fn(),
81
+ };
82
+ render(<NsAutocomplete clear={clear} {...commonProps} />);
83
+ const autocompleteInput = screen.getByPlaceholderText(commonProps.placeholder);
90
84
  await userEvent.type(autocompleteInput, 'GS Facial');
91
85
  await waitFor(async () => {
92
- const clearButton = screen.getByTestId('autocomplete-clear-id');
86
+ const clearButton = screen.getByText(clear.text);
93
87
  await userEvent.click(clearButton);
94
88
  });
95
89
  }, 40000);
@@ -1,18 +1,16 @@
1
- import { styled } from '@nuskin/foundation-theme';
2
-
1
+ import { styled, ColorUtils } from '@nuskin/foundation-theme';
3
2
  import { NsInputField } from '../input';
3
+ const { getGenomeColor } = ColorUtils;
4
4
 
5
- // TODO: why is .muiautocomplete-popupindicator added?
6
- // TODO: ${({ theme }) => getGenomeColor(theme, 'N100')}; use forceMode light
7
5
  export const StyledTextField = styled(NsInputField)`
8
6
  .MuiAutocomplete-inputRoot {
9
7
  padding-right: 10px !important;
10
8
  }
11
- .muiautocomplete-popupindicator {
12
- display: none;
13
- }
14
9
  .styled-text-field.MuiOutlinedInput-root input#custom_autocomplete_dropdown::placeholder {
15
10
  opacity: 1;
16
- color: #252525;
11
+ color: ${({ theme }) => getGenomeColor(theme, 'N100', 'light')};
17
12
  }
18
13
  `;
14
+ // .muiautocomplete-popupindicator {
15
+ // display: none;
16
+ // }
@@ -1,7 +1,8 @@
1
1
  import { Autocomplete, AutocompleteRenderInputParams } from '@mui/material';
2
2
  import React, { PropsWithChildren, useEffect, useRef, useState } from 'react';
3
3
 
4
- import { AutoCompleteButton } from './helper/AutoCompleteButton';
4
+ import { LineLoader } from './helper/LineLoader';
5
+ import { RecentClearAll } from './helper/RecentClearAll';
5
6
  import { renderGroupBy, renderGroupName, renderOptionLabel } from './helper/renderGroupName';
6
7
  import { SeeMoreButton } from './helper/SeeMoreButton';
7
8
  import { StyledTextField } from './NsAutocomplete.styled';
@@ -48,11 +49,14 @@ const NsAutocomplete = ({
48
49
  />
49
50
  );
50
51
 
51
- const renderOption = (props: ComponentBoxProps, option: OptionsProps) => (
52
- <li {...props} key={props.id}>
53
- {OptionsUI ? <OptionsUI {...props} option={option} /> : null}
54
- </li>
55
- );
52
+ const renderOption = (props: ComponentBoxProps, option: OptionsProps) =>
53
+ OptionsUI ? (
54
+ <OptionsUI {...props} option={option} key={props.id} />
55
+ ) : (
56
+ <li {...props} key={props.id}>
57
+ {option.value}
58
+ </li>
59
+ );
56
60
 
57
61
  const renderListBoxComponent = ({ children, ...rest }: ComponentBoxProps) => {
58
62
  return (
@@ -64,11 +68,12 @@ const NsAutocomplete = ({
64
68
  className={rest.className}
65
69
  ref={listboxRef}
66
70
  >
67
- <AutoCompleteButton
71
+ <RecentClearAll
68
72
  show={clear?.show ?? false}
69
73
  text={clear?.text ?? 'Clear All'}
70
74
  onClick={clear?.onClear ?? noop}
71
75
  testId="autocomplete-clear-id"
76
+ recentSearchText={clear?.recentSearchText ?? 'Your Recent Searches'}
72
77
  />
73
78
  {children}
74
79
  <SeeMoreButton
@@ -82,10 +87,11 @@ const NsAutocomplete = ({
82
87
  </ul>
83
88
  );
84
89
  };
85
-
86
90
  return (
87
91
  <>
92
+ <LineLoader show={loading ?? false} />
88
93
  <Autocomplete
94
+ openOnFocus
89
95
  id={id}
90
96
  disablePortal
91
97
  className={className}
@@ -0,0 +1,37 @@
1
+ import { styled } from '@nuskin/foundation-theme';
2
+
3
+ const StyledLine = styled.div`
4
+ position: fixed;
5
+ top: 0px;
6
+ left: 0;
7
+ width: 100%;
8
+ height: 2px;
9
+ background: #fff;
10
+ z-index: 99999;
11
+ overflow: hidden;
12
+ .dot {
13
+ position: absolute;
14
+ height: 100%;
15
+ width: 150px;
16
+ background: #f00;
17
+ animation: dotleft 1s cubic-bezier(0.72, 0.03, 0.75, 0.54) infinite;
18
+ }
19
+ @keyframes dotleft {
20
+ 0% {
21
+ left: 0%;
22
+ width: 150px;
23
+ }
24
+ 100% {
25
+ left: 100%;
26
+ width: 900px;
27
+ }
28
+ }
29
+ `;
30
+
31
+ export const LineLoader = ({ show }: { show: boolean }) => {
32
+ return (
33
+ <StyledLine className={`${show ? '' : 'hidden '} line`}>
34
+ <div className="dot">{show}</div>
35
+ </StyledLine>
36
+ );
37
+ };
@@ -0,0 +1,36 @@
1
+ import { styled } from '@nuskin/foundation-theme';
2
+ import { NsTypography } from '../../typography';
3
+
4
+ type AutoCompleteButtonProps = {
5
+ text: string;
6
+ show: boolean;
7
+ onClick(): void;
8
+ testId?: string;
9
+ recentSearchText: string;
10
+ };
11
+ export const StyledClear = styled(NsTypography)`
12
+ :hover {
13
+ opacity: 0.5;
14
+ }
15
+ `;
16
+ export const RecentClearAll = (props: AutoCompleteButtonProps) => {
17
+ const { show, onClick, text, testId, recentSearchText } = props;
18
+ if (!show) {
19
+ return null;
20
+ }
21
+ return (
22
+ <li className="justify-between flex p-3" onClick={onClick}>
23
+ <NsTypography data-testid={testId} variant="body-m" weight="bold">
24
+ {recentSearchText}
25
+ </NsTypography>
26
+ <StyledClear
27
+ data-testid={testId}
28
+ variant="body-m"
29
+ weight="bold"
30
+ className="cursor-pointer hover:opacity-40"
31
+ >
32
+ {text}
33
+ </StyledClear>
34
+ </li>
35
+ );
36
+ };
@@ -1,7 +1,20 @@
1
1
  import { Dispatch, MutableRefObject, SetStateAction, useCallback } from 'react';
2
+ import { styled, ColorUtils } from '@nuskin/foundation-theme';
2
3
 
3
- import { OptionsProps } from '../..';
4
- import { AutoCompleteButton } from './AutoCompleteButton';
4
+ import { NsTypography, OptionsProps } from '../..';
5
+ const { getGenomeColor } = ColorUtils;
6
+ export const ListStyled = styled.div`
7
+ display: flex;
8
+ width: 100%;
9
+ flex-direction: row;
10
+ align-items: center;
11
+ gap: 10px;
12
+ padding: 4px 12px;
13
+ cursor: pointer;
14
+ &:hover {
15
+ background: ${({ theme }) => getGenomeColor(theme, 'A10')};
16
+ }
17
+ `;
5
18
 
6
19
  type SeeMoreButtonProps = {
7
20
  text?: string;
@@ -30,9 +43,23 @@ export const SeeMoreButton = (props: SeeMoreButtonProps) => {
30
43
  setScrollTopPosition(lastScrollPosition);
31
44
  }
32
45
  }
33
- if (onSeeMore && typeof onSeeMore === 'function') {
46
+ if (typeof onSeeMore === 'function') {
34
47
  onSeeMore();
35
48
  }
36
49
  }, [listboxRef, onSeeMore, options?.length, setScrollTopPosition]);
37
- return <AutoCompleteButton show={show} text={text} onClick={handleSeeMore} testId="autocomplete-loadmore-id" />;
50
+ if (!show) {
51
+ return null;
52
+ }
53
+ return (
54
+ <ListStyled className="text-left p-3" onClick={handleSeeMore}>
55
+ <NsTypography
56
+ data-testid="autocomplete-loadmore-id"
57
+ variant="body-m"
58
+ decoration="underline"
59
+ className="cursor-pointer"
60
+ >
61
+ {text}
62
+ </NsTypography>
63
+ </ListStyled>
64
+ );
38
65
  };
@@ -0,0 +1,4 @@
1
+ export { LineLoader } from './LineLoader';
2
+ export { RecentClearAll } from './RecentClearAll';
3
+ export * from './renderGroupName';
4
+ export {} from './SeeMoreButton';
@@ -1,5 +1,4 @@
1
1
  import { AutocompleteRenderGroupParams } from '@mui/material';
2
-
3
2
  import { NsTypography, OptionsProps } from '../..';
4
3
 
5
4
  export const renderGroupName = ({ key, group, children }: AutocompleteRenderGroupParams) => (
@@ -1,4 +1,3 @@
1
- /* eslint-disable max-len */
2
1
  import { OptionsProps } from '../types';
3
2
 
4
3
  export const AutocompleteMockList: OptionsProps[] = [
@@ -6,19 +5,19 @@ export const AutocompleteMockList: OptionsProps[] = [
6
5
  id: '1',
7
6
  value: 'GS Facial Gels 2pk Subscription',
8
7
  group: 'Popular Searches',
9
- image: 'https://www.nuskin.com/content/products/86/99/01/86990168/_jcr_content/fullImage.img.160.160.png.64.64.png',
8
+ image: 'https://www.nuskin.com/content/products/86/99/01/86990168/_jcr_content/fullImage.img.160.160.png.64.64.png'
10
9
  },
11
10
  {
12
11
  id: '2',
13
12
  value: 'GS Facial',
14
13
  group: 'Popular Searches',
15
- image: 'https://www.nuskin.com/content/products/01/55/00/01550014/_jcr_content/fullImage.img.160.160.png.64.64.png',
14
+ image: 'https://www.nuskin.com/content/products/01/55/00/01550014/_jcr_content/fullImage.img.160.160.png.64.64.png'
16
15
  },
17
16
  {
18
17
  id: '3',
19
18
  value: 'GS Facial Spa',
20
19
  group: 'Popular Searches',
21
- image: 'https://www.nuskin.com/content/products/01/10/12/01101251/_jcr_content/fullImage.img.160.160.png.64.64.png',
20
+ image: 'https://www.nuskin.com/content/products/01/10/12/01101251/_jcr_content/fullImage.img.160.160.png.64.64.png'
22
21
  },
23
22
  {
24
23
  id: '4',
@@ -26,7 +25,7 @@ export const AutocompleteMockList: OptionsProps[] = [
26
25
  group: 'Popular Searches',
27
26
  image: 'https://www.nuskin.com/content/products/01/55/00/01550013/_jcr_content/fullImage.img.160.160.png.64.64.png',
28
27
  icon: 'cart',
29
- groupBgColor: '#000',
28
+ groupBgColor: '#000'
30
29
  },
31
30
  {
32
31
  id: '5',
@@ -34,7 +33,7 @@ export const AutocompleteMockList: OptionsProps[] = [
34
33
  group: 'Popular Searches',
35
34
  image: 'https://www.nuskin.com/content/products/86/99/01/86990100/_jcr_content/fullImage.img.160.160.png.64.64.png',
36
35
  icon: 'cart',
37
- groupBgColor: '#000',
36
+ groupBgColor: '#000'
38
37
  },
39
38
  {
40
39
  id: '6',
@@ -42,26 +41,26 @@ export const AutocompleteMockList: OptionsProps[] = [
42
41
  group: 'Popular Searches',
43
42
  image: 'https://www.nuskin.com/content/products/01/00/16/01001647/jcr:content/fullImage.img.160.160.png/1611763135883-cache.png.64.64.png',
44
43
  icon: 'cart',
45
- groupBgColor: '#000',
44
+ groupBgColor: '#000'
46
45
  },
47
46
 
48
47
  {
49
48
  id: '7',
50
49
  value: 'Rejuvenating Cream',
51
50
  group: 'Popular Searches',
52
- image: 'https://www.nuskin.com/content/products/86/99/01/86990168/_jcr_content/fullImage.img.160.160.png.64.64.png',
51
+ image: 'https://www.nuskin.com/content/products/86/99/01/86990168/_jcr_content/fullImage.img.160.160.png.64.64.png'
53
52
  },
54
53
  {
55
54
  id: '8',
56
55
  value: 'Epoch® Firewalker® Foot Cream',
57
56
  group: 'Popular Searches',
58
- image: 'https://www.nuskin.com/content/products/01/55/00/01550014/_jcr_content/fullImage.img.160.160.png.64.64.png',
57
+ image: 'https://www.nuskin.com/content/products/01/55/00/01550014/_jcr_content/fullImage.img.160.160.png.64.64.png'
59
58
  },
60
59
  {
61
60
  id: '9',
62
61
  value: 'Tri-Phasic White® Night Cream',
63
62
  group: 'Popular Searches',
64
- image: 'https://www.nuskin.com/content/products/01/10/12/01101251/_jcr_content/fullImage.img.160.160.png.64.64.png',
63
+ image: 'https://www.nuskin.com/content/products/01/10/12/01101251/_jcr_content/fullImage.img.160.160.png.64.64.png'
65
64
  },
66
65
  {
67
66
  id: '10',
@@ -69,7 +68,7 @@ export const AutocompleteMockList: OptionsProps[] = [
69
68
  group: 'Popular Searches',
70
69
  image: 'https://www.nuskin.com/content/products/01/55/00/01550013/_jcr_content/fullImage.img.160.160.png.64.64.png',
71
70
  icon: 'cart',
72
- groupBgColor: '#000',
71
+ groupBgColor: '#000'
73
72
  },
74
73
  {
75
74
  id: '11',
@@ -77,7 +76,7 @@ export const AutocompleteMockList: OptionsProps[] = [
77
76
  group: 'Popular Searches',
78
77
  image: 'https://www.nuskin.com/content/products/86/99/01/86990100/_jcr_content/fullImage.img.160.160.png.64.64.png',
79
78
  icon: 'cart',
80
- groupBgColor: '#000',
79
+ groupBgColor: '#000'
81
80
  },
82
81
  {
83
82
  id: '12',
@@ -85,6 +84,6 @@ export const AutocompleteMockList: OptionsProps[] = [
85
84
  group: 'Popular Searches',
86
85
  image: 'https://www.nuskin.com/content/products/01/00/16/01001647/jcr:content/fullImage.img.160.160.png/1611763135883-cache.png.64.64.png',
87
86
  icon: 'cart',
88
- groupBgColor: '#000',
89
- },
87
+ groupBgColor: '#000'
88
+ }
90
89
  ];
@@ -1,12 +1,11 @@
1
1
  /* eslint-disable @next/next/no-img-element */
2
+ import { ListUiProps, NsIcon, NsTypography } from '../..';
2
3
  import { ListStyled } from './Mock.styled';
3
- import { NsTypography } from '../../typography';
4
- import { NsIcon } from '../../icon';
5
- import { ListUiProps } from '../types';
6
4
 
7
- const OptionUiComponent = ({ option }: ListUiProps) => {
5
+ const OptionUiComponent = (props: ListUiProps) => {
6
+ const { option } = props;
8
7
  return (
9
- <ListStyled>
8
+ <ListStyled {...props}>
10
9
  <div className="item-description" role="link" tabIndex={0}>
11
10
  <NsTypography aria-label="Nu Skin Tumbler" variant="body-m" colorOverride="#63666A">
12
11
  <img src={option.image} alt="No-image" />
@@ -32,6 +32,7 @@ export type NsAutocompleteProps = {
32
32
  text?: string;
33
33
  show?: boolean; //default to false
34
34
  onClear: () => void;
35
+ recentSearchText?: string;
35
36
  };
36
37
  seeMore?: {
37
38
  text?: string;
@@ -0,0 +1,31 @@
1
+ import { NsButton, NsIcon } from '..';
2
+ import { NsCardButton } from './types';
3
+
4
+ const CardButton = ({
5
+ url,
6
+ endIcon,
7
+ buttonText,
8
+ showButton = true,
9
+ buttonVariant = 'outlined',
10
+ buttonColor = 'primary',
11
+ fullWidth = false,
12
+ }: NsCardButton) => {
13
+ if (showButton && url) {
14
+ return (
15
+ <div className="cta">
16
+ <NsButton
17
+ href={url}
18
+ color={buttonColor}
19
+ variant={buttonVariant}
20
+ fullWidth={fullWidth}
21
+ endIcon={endIcon ? <NsIcon name={endIcon} color={buttonColor} /> : null}
22
+ >
23
+ {buttonText}
24
+ </NsButton>
25
+ </div>
26
+ );
27
+ }
28
+ return null;
29
+ };
30
+
31
+ export default CardButton;
@@ -1,6 +1,6 @@
1
1
  import Box from '@mui/material/Box';
2
2
  import { styled } from '@nuskin/foundation-theme';
3
- import { NsImage } from '..';
3
+ import { NsImage } from '../';
4
4
 
5
5
  type NsAwardCardProps = {
6
6
  title: string;
@@ -8,6 +8,7 @@ type NsAwardCardProps = {
8
8
  mediaOutlet: string;
9
9
  backgroundImageUrl: string;
10
10
  backgroundImageAlt: string;
11
+ className?: string;
11
12
  };
12
13
 
13
14
  const CardContainer = styled(Box)(() => {
@@ -15,17 +16,18 @@ const CardContainer = styled(Box)(() => {
15
16
  display: 'flex',
16
17
  flexDirection: 'column',
17
18
  position: 'relative',
18
- backgroundColor: '#fff',
19
19
  alignItems: 'center',
20
+ width: '160px',
21
+ height: 'auto',
20
22
  '.image': {
21
- width: '150px',
23
+ width: '160px',
22
24
  height: 'auto',
23
25
  objectFit: 'cover',
24
- backgroundColor: 'red',
25
26
  },
26
27
  '.content': {
27
28
  display: 'flex',
28
29
  flexDirection: 'column',
30
+ textAlign: 'center',
29
31
  alignItems: 'center',
30
32
  },
31
33
  '.title': {
@@ -57,9 +59,10 @@ export default function NsAwardCard({
57
59
  mediaOutlet,
58
60
  backgroundImageUrl,
59
61
  backgroundImageAlt,
62
+ className,
60
63
  }: NsAwardCardProps) {
61
64
  return (
62
- <CardContainer role="award-card" component="div" data-testid="award-card">
65
+ <CardContainer className={className} role="award-card" component="div" data-testid="award-card">
63
66
  <NsImage alt={backgroundImageAlt} src={backgroundImageUrl} className="image" />
64
67
  <div className="content">
65
68
  <article className="title">{title}</article>
@@ -1,20 +1,20 @@
1
- import { ShoppingCart } from '@mui/icons-material';
2
1
  import Box from '@mui/material/Box';
3
2
  import { styled } from '@nuskin/foundation-theme';
4
3
  import { NsTypography } from '../';
5
4
  import NsBrandWrapper from './NsBrandWrapper';
6
5
  import NsBrandLogo from './NsBrandLogo';
7
6
  import NsBgCard from './NsBgCard';
8
- import NsButton from '../button/NsButton';
9
7
  import cardSizes from './cardSizes';
8
+ import CardButton from './CardButton';
9
+ import { NsCardButton } from './types';
10
10
 
11
11
  type NsBrandCardProps = {
12
12
  title?: string;
13
13
  brandImageUrl: string;
14
14
  backgroundImageUrl: string;
15
15
  size?: 'small' | 'large';
16
- button?: boolean;
17
- onClick?: () => void;
16
+ button?: NsCardButton;
17
+ className?: string;
18
18
  };
19
19
 
20
20
  const CardContainer = styled((props: any) => <Box {...props} />)(({ size }) => {
@@ -49,6 +49,7 @@ const CardContainer = styled((props: any) => <Box {...props} />)(({ size }) => {
49
49
  },
50
50
  '.cta': {
51
51
  marginTop: '15px',
52
+ width: '100%',
52
53
  },
53
54
  '.image': {
54
55
  width,
@@ -64,10 +65,10 @@ export default function NsBrandCard({
64
65
  backgroundImageUrl,
65
66
  button,
66
67
  size,
67
- onClick,
68
+ className,
68
69
  }: NsBrandCardProps) {
69
70
  return (
70
- <CardContainer role="brand-card" component="div" data-testid="brand-card" size={size} onClick={onClick}>
71
+ <CardContainer className={className} role="brand-card" component="div" data-testid="brand-card" size={size}>
71
72
  <NsBgCard backgroundImageUrl={backgroundImageUrl} className="image">
72
73
  <NsBrandWrapper>
73
74
  <NsBrandLogo component="img" image={brandImageUrl} />
@@ -78,17 +79,7 @@ export default function NsBrandCard({
78
79
  {title}
79
80
  </NsTypography>
80
81
  ) : null}
81
- {button ? (
82
- <NsButton
83
- className="cta"
84
- darkModeEnabled={false}
85
- variant="outlined"
86
- fullWidth={true}
87
- endIcon={<ShoppingCart />}
88
- >
89
- Add to Cart
90
- </NsButton>
91
- ) : null}
82
+ {button ? <CardButton {...button} /> : null}
92
83
  </CardContainer>
93
84
  );
94
85
  }
@@ -6,8 +6,9 @@ import { useState } from 'react';
6
6
  type NsCheckoutCardProps = {
7
7
  icon: NsIconNameType;
8
8
  title: string;
9
- address: string;
10
- onClick: () => void;
9
+ linkText: string;
10
+ url: string;
11
+ className?: string;
11
12
  };
12
13
 
13
14
  const CardContainer = styled(Box)(() => {
@@ -58,14 +59,14 @@ const CardContainer = styled(Box)(() => {
58
59
  };
59
60
  });
60
61
 
61
- export default function NsCheckoutCard({ title, address, icon, onClick }: NsCheckoutCardProps) {
62
+ export default function NsCheckoutCard({ title, icon, linkText, url, className }: NsCheckoutCardProps) {
62
63
  const [dropdownIcon, setDropdownIcon] = useState(false);
63
64
  const handleClick = () => {
64
65
  setDropdownIcon(!dropdownIcon);
65
66
  };
66
67
 
67
68
  return (
68
- <CardContainer role="checkout-card" component="div" data-testid="checkout-card" onClick={onClick}>
69
+ <CardContainer className={className} role="checkout-card" component="div" data-testid="checkout-card">
69
70
  <div className="left-bar"></div>
70
71
  <div className="content">
71
72
  <span>
@@ -73,9 +74,9 @@ export default function NsCheckoutCard({ title, address, icon, onClick }: NsChec
73
74
  </span>
74
75
  <div className="text-content">
75
76
  <article className="title">{title}</article>
76
- <article className="address">{address}</article>
77
- <NsLink className="action-link" href={''}>
78
- CHANGE
77
+ <article className="address">Address</article>
78
+ <NsLink className="action-link" href={url}>
79
+ {linkText}
79
80
  </NsLink>
80
81
  </div>
81
82
  <span className="icon-right">