@nuskin/foundation-ui-components 1.9.3 → 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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuskin/foundation-ui-components",
3
- "version": "1.9.3",
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;
@@ -7,7 +7,7 @@ const CardButton = ({
7
7
  buttonText,
8
8
  showButton = true,
9
9
  buttonVariant = 'outlined',
10
- buttonColor = 'secondary',
10
+ buttonColor = 'primary',
11
11
  fullWidth = false,
12
12
  }: NsCardButton) => {
13
13
  if (showButton && url) {
@@ -16,17 +16,18 @@ const CardContainer = styled(Box)(() => {
16
16
  display: 'flex',
17
17
  flexDirection: 'column',
18
18
  position: 'relative',
19
- backgroundColor: '#fff',
20
19
  alignItems: 'center',
20
+ width: '160px',
21
+ height: 'auto',
21
22
  '.image': {
22
- width: '150px',
23
+ width: '160px',
23
24
  height: 'auto',
24
25
  objectFit: 'cover',
25
- backgroundColor: 'red',
26
26
  },
27
27
  '.content': {
28
28
  display: 'flex',
29
29
  flexDirection: 'column',
30
+ textAlign: 'center',
30
31
  alignItems: 'center',
31
32
  },
32
33
  '.title': {
@@ -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,
@@ -11,20 +11,25 @@ type NsHeroCardLevel1Props = {
11
11
  backgroundImageAlt: string;
12
12
  button?: NsCardButton;
13
13
  className?: string;
14
+ imagePosition?: 'top' | 'bottom';
14
15
  };
15
16
 
16
- const CardContainer = styled(Box)(() => {
17
+ const CardContainer = styled((props: any) => <Box {...props} />)(({ imagePosition }) => {
18
+ const imageDirection = imagePosition === 'top' ? 'column' : 'column-reverse';
19
+
17
20
  return {
18
21
  backgroundClip: 'border-box',
19
22
  display: 'flex',
20
- flexDirection: 'row' as 'row',
21
23
  wordWrap: 'break-word' as 'break-word',
22
24
  position: 'relative',
23
25
  overflow: 'hidden',
24
- height: 'auto',
26
+ width: '100%',
27
+ height: '500px',
28
+ flexDirection: 'row',
25
29
  '.content': {
26
30
  width: '50%',
27
- height: '100%',
31
+ minWidth: '300px',
32
+ height: '500px',
28
33
  padding: '50px',
29
34
  paddingLeft: '100px',
30
35
  display: 'flex',
@@ -34,10 +39,8 @@ const CardContainer = styled(Box)(() => {
34
39
  left: 0,
35
40
  boxSizing: 'border-box',
36
41
  },
37
- '.image': {
38
- width: 'auto',
39
- height: '100%',
40
- display: 'block',
42
+ '.bg-image': {
43
+ objectFit: 'cover',
41
44
  },
42
45
  '.body-title': {
43
46
  fontSize: '36px',
@@ -52,10 +55,16 @@ const CardContainer = styled(Box)(() => {
52
55
  marginTop: '10px',
53
56
  },
54
57
  '@media (max-width: 768px)': {
55
- display: 'block',
58
+ '.content': {
59
+ paddingLeft: '20px',
60
+ },
61
+ },
62
+ '@media (max-width: 430px)': {
56
63
  height: 'auto',
57
64
  backgroundColor: '#edece9',
65
+ flexDirection: imageDirection,
58
66
  '.content': {
67
+ height: 'auto',
59
68
  position: 'static',
60
69
  width: '100%',
61
70
  padding: '20px',
@@ -64,19 +73,18 @@ const CardContainer = styled(Box)(() => {
64
73
  };
65
74
  });
66
75
 
67
- const NsHeroCardLevel1 = ({
76
+ export default function NsHeroCardLevel1({
68
77
  cardTitle,
69
78
  cardDescription,
70
79
  backgroundImageUrl,
71
80
  backgroundImageAlt,
72
81
  button,
73
82
  className,
74
- }: NsHeroCardLevel1Props) => {
83
+ imagePosition = 'top',
84
+ }: NsHeroCardLevel1Props) {
75
85
  return (
76
- <CardContainer className={className} data-testid="hero-card-level-1">
77
- <div className="image">
78
- <NsImage height={'auto'} width={'100%'} alt={backgroundImageAlt} src={backgroundImageUrl} />
79
- </div>
86
+ <CardContainer className={className} data-testid="hero-card-level-1" imagePosition={imagePosition}>
87
+ <NsImage variant="fill" alt={backgroundImageAlt} src={backgroundImageUrl} className="bg-image" />
80
88
  <div className="content">
81
89
  <article className="body-title">{cardTitle}</article>
82
90
  <article className="body-text">{cardDescription}</article>
@@ -84,5 +92,4 @@ const NsHeroCardLevel1 = ({
84
92
  </div>
85
93
  </CardContainer>
86
94
  );
87
- };
88
- export default NsHeroCardLevel1;
95
+ }
@@ -22,7 +22,8 @@ const CardContainer = styled(Box)(() => {
22
22
  wordWrap: 'break-word' as 'break-word',
23
23
  position: 'relative',
24
24
  overflow: 'hidden',
25
- height: 'auto',
25
+ height: '250px',
26
+ width: '100%',
26
27
  '.content': {
27
28
  height: '100%',
28
29
  padding: '50px',
@@ -33,10 +34,8 @@ const CardContainer = styled(Box)(() => {
33
34
  left: 0,
34
35
  boxSizing: 'border-box',
35
36
  },
36
- '.image': {
37
- width: 'auto',
38
- height: '100%',
39
- display: 'block',
37
+ '.bg-image': {
38
+ objectFit: 'cover',
40
39
  },
41
40
  '.brand-container': {
42
41
  backgroundColor: '#fff',
@@ -45,29 +44,19 @@ const CardContainer = styled(Box)(() => {
45
44
  paddingRight: '10px',
46
45
  },
47
46
  '.body-title': {
48
- fontSize: '36px',
47
+ fontSize: '26px',
49
48
  lineHeight: '44px',
50
49
  marginBottom: '5px',
51
50
  },
52
51
  '.body-text': {
53
- fontSize: '18px',
52
+ fontSize: '12px',
54
53
  fontWeight: 700,
55
54
  marginBottom: '5px',
56
55
  },
57
- '@media (max-width: 768px)': {
56
+ '@media (max-width:768px)': {
58
57
  '.content': {
59
58
  padding: '5%',
60
59
  },
61
- '.body-title': {
62
- fontSize: '18px',
63
- lineHeight: '44px',
64
- marginBottom: '5px',
65
- },
66
- '.body-text': {
67
- fontSize: '12px',
68
- fontWeight: 700,
69
- marginBottom: '5px',
70
- },
71
60
  },
72
61
  };
73
62
  });
@@ -83,9 +72,7 @@ const NsHeroCardLevel2 = ({
83
72
  }: NsHeroCardLevel2Props) => {
84
73
  return (
85
74
  <CardContainer className={className} data-testid="hero-card-level-2">
86
- <div className="image">
87
- <NsImage height={'auto'} width={'100%'} alt={backgroundImageAlt} src={backgroundImageUrl} />
88
- </div>
75
+ <NsImage variant="fill" alt={backgroundImageAlt} src={backgroundImageUrl} className="bg-image" />
89
76
  <div className="content">
90
77
  <div className="brand-container">
91
78
  <article>{brandName}</article>
@@ -15,19 +15,21 @@ type NsLargeCardProps = {
15
15
  className?: string;
16
16
  };
17
17
 
18
- const CardContainer = styled((props: any) => <Box {...props} />)(({ isHorizontal }) => {
19
- let width = '375px',
18
+ const CardContainer = styled((props: any) => <Box {...props} />)(({ isHorizontal, matches }) => {
19
+ let width = '450px',
20
20
  paddingLeft = '0px',
21
21
  justifyContent,
22
22
  fontSizeSub = '16px',
23
- fontSizeTitle = '26px';
23
+ fontSizeTitle = '26px',
24
+ imageWidth = '100%';
24
25
 
25
26
  if (isHorizontal) {
26
- width = 'unset';
27
+ width = '600px';
27
28
  paddingLeft = '30px';
28
29
  justifyContent = 'center';
29
30
  fontSizeSub = '16px';
30
- fontSizeTitle = '36px';
31
+ fontSizeTitle = '26px';
32
+ imageWidth = '50%';
31
33
  }
32
34
  let direction = isHorizontal ? ('row' as 'row') : ('column' as 'column');
33
35
 
@@ -36,10 +38,10 @@ const CardContainer = styled((props: any) => <Box {...props} />)(({ isHorizontal
36
38
  flexDirection: direction,
37
39
  position: 'relative',
38
40
  width,
39
- '.image': {
40
- width: '375px',
41
- height: 'auto',
41
+ '.bg-image': {
42
42
  objectFit: 'cover',
43
+ height: '220px',
44
+ width: imageWidth,
43
45
  },
44
46
  '.content': {
45
47
  display: 'flex',
@@ -60,6 +62,9 @@ const CardContainer = styled((props: any) => <Box {...props} />)(({ isHorizontal
60
62
  '.cta': {
61
63
  marginTop: '10px',
62
64
  },
65
+ '@media (max-width: 768px)': {
66
+ width: '100%',
67
+ },
63
68
  };
64
69
  });
65
70
 
@@ -81,7 +86,7 @@ export default function NsLargeCard({
81
86
  data-testid="large-card"
82
87
  isHorizontal={isHorizontal}
83
88
  >
84
- <NsImage alt={backgroundImageAlt} src={backgroundImageUrl} className="image" />
89
+ <NsImage alt={backgroundImageAlt} src={backgroundImageUrl} className="bg-image" />
85
90
  <div className="content">
86
91
  <article className="subtitle">{subtitle}</article>
87
92
  <article className="title">{title}</article>
@@ -18,20 +18,25 @@ const CardContainer = styled(Box)(() => {
18
18
  wordWrap: 'break-word' as 'break-word',
19
19
  position: 'relative',
20
20
  overflow: 'hidden',
21
- height: 'auto',
22
- width: '200px',
21
+ height: '350px',
22
+ width: '210px',
23
23
  backgroundColor: '#fff',
24
24
  '.content': {
25
25
  padding: '10px',
26
26
  display: 'flex',
27
27
  flexDirection: 'column',
28
- minHeight: '150px',
28
+ minHeight: '80px',
29
29
  justifyContent: 'space-between',
30
30
  },
31
31
  '.body-title': {
32
32
  fontSize: '18px',
33
33
  marginBottom: '5px',
34
34
  fontWeight: 600,
35
+ display: '-webkit-box',
36
+ '-webkit-box-orient': 'vertical',
37
+ '-webkit-line-clamp': '3',
38
+ overflow: 'hidden',
39
+ textOverflow: 'ellipsis',
35
40
  },
36
41
  '.body-text': {
37
42
  fontSize: '12px',
@@ -17,8 +17,8 @@ const CardContainer = styled(Box)(() => {
17
17
  return {
18
18
  backgroundColor: '#fff',
19
19
  display: 'flex',
20
- height: '320px',
21
- width: '375px',
20
+ height: '275px',
21
+ width: '250px',
22
22
  position: 'relative',
23
23
  '.image': {
24
24
  width: '100%',
@@ -49,7 +49,7 @@ const CardContainer = styled(Box)(() => {
49
49
  },
50
50
  '.title': {
51
51
  color: '#fff',
52
- fontSize: '26px',
52
+ fontSize: '22px',
53
53
  fontWeight: '400',
54
54
  marginTop: '20px',
55
55
  },
@@ -17,8 +17,8 @@ const CardContainer = styled(Box)(() => {
17
17
  return {
18
18
  backgroundColor: '#fff',
19
19
  display: 'flex',
20
- height: '545px',
21
- width: '375px',
20
+ height: '620px',
21
+ width: '450px',
22
22
  position: 'relative',
23
23
  '.image': {
24
24
  width: '100%',
@@ -1,11 +1,11 @@
1
1
  const cardSizes = {
2
2
  small: {
3
- width: '165px',
4
- height: '180px',
3
+ width: '180px',
4
+ height: '200px',
5
5
  },
6
6
  large: {
7
- width: '190px',
8
- height: '220px',
7
+ width: '220px',
8
+ height: '250px',
9
9
  },
10
10
  };
11
11
 
@@ -58,11 +58,11 @@ describe('NsBrandCard component', () => {
58
58
  const cardContainer = container.firstChild;
59
59
  const nsBgCardElement = cardContainer?.firstChild;
60
60
  expect(cardContainer).toHaveStyle(`
61
- width: 165px;
61
+ width: 180px;
62
62
  `);
63
63
  expect(nsBgCardElement).toHaveStyle(`
64
- width: 165px;
65
- height: 180px;
64
+ width: 180px;
65
+ height: 200px;
66
66
  `);
67
67
  });
68
68
 
@@ -71,7 +71,7 @@ describe('NsBrandCard component', () => {
71
71
  const cardContainer = screen.getByTestId('brand-card') as HTMLElement;
72
72
  const computedStyles = window.getComputedStyle(cardContainer);
73
73
 
74
- expect(computedStyles.width).toBe('190px');
74
+ expect(computedStyles.width).toBe('220px');
75
75
  });
76
76
 
77
77
  it('7. renders with default styles when size is not provided', () => {
@@ -79,6 +79,6 @@ describe('NsBrandCard component', () => {
79
79
  const cardContainer = screen.getByTestId('brand-card') as HTMLElement;
80
80
  const computedStyles = window.getComputedStyle(cardContainer);
81
81
 
82
- expect(computedStyles.width).toBe('190px');
82
+ expect(computedStyles.width).toBe('220px');
83
83
  });
84
84
  });
@@ -26,6 +26,7 @@ export const Default: Story = {
26
26
  buttonColor: 'primary',
27
27
  endIcon: 'cart',
28
28
  url: '#',
29
+ fullWidth: true,
29
30
  },
30
31
  },
31
32
  };
@@ -27,5 +27,6 @@ export const Default: Story = {
27
27
  buttonColor: 'primary',
28
28
  url: '#',
29
29
  },
30
+ imagePosition: 'bottom',
30
31
  },
31
32
  };
@@ -1,24 +0,0 @@
1
- import { NsButton, NsTypography } from '../..';
2
-
3
- type AutoCompleteButtonProps = {
4
- text: string;
5
- show: boolean;
6
- onClick(): void;
7
- testId?: string;
8
- };
9
-
10
- export const AutoCompleteButton = (props: AutoCompleteButtonProps) => {
11
- const { show, onClick, text, testId } = props;
12
- if (!show) {
13
- return null;
14
- }
15
- return (
16
- <li className="text-right p-3">
17
- <NsButton onClick={onClick} data-testid={testId}>
18
- <NsTypography variant="body-xs" weight="bold">
19
- {text}
20
- </NsTypography>
21
- </NsButton>
22
- </li>
23
- );
24
- };