@nuskin/foundation-ui-components 1.8.1 → 1.9.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/package.json +1 -1
- package/src/common/accordion/NsAccordionHeader.tsx +2 -7
- package/src/common/accordion/NsCollapse.tsx +35 -42
- package/src/common/alert/NsAlert.tsx +7 -5
- package/src/common/auth-dropdown/NsAuthDropdown.styled.ts +1 -5
- package/src/common/autocomplete/helper/AutoCompleteButton.tsx +1 -1
- package/src/common/autocomplete/helper/renderGroupName.tsx +1 -1
- package/src/common/autocomplete/mock/MockUI.tsx +1 -1
- package/src/common/banner/NsBanner.stories.tsx +1 -1
- package/src/common/button/NsButton.styled.tsx +40 -45
- package/src/common/card/NsAwardCard.tsx +71 -0
- package/src/common/card/NsBgCard.tsx +2 -1
- package/src/common/card/NsLargeCard.tsx +14 -9
- package/src/common/card/NsMediumCard.tsx +21 -6
- package/src/common/card/NsPost.tsx +4 -7
- package/src/common/card/index.ts +1 -0
- package/src/common/card/stories/NsAwardCard.stories.tsx +26 -0
- package/src/common/card/stories/NsLargeCard.stories.tsx +5 -4
- package/src/common/card/stories/NsMediumCard.stories.tsx +7 -3
- package/src/common/card/stories/NsPost.stories.tsx +2 -2
- package/src/common/carousal/NsCarousal.tsx +6 -5
- package/src/common/carousal/NsScrollingCarousal.tsx +4 -8
- package/src/common/checkbox/NsCheckbox.tsx +1 -1
- package/src/common/column-control/NsColumnControl.tsx +6 -3
- package/src/common/column-control/styled/StyledFlex.tsx +5 -4
- package/src/common/column-control/styled/StyledGrid.tsx +2 -1
- package/src/common/icon/NsIcon.stories.tsx +42 -0
- package/src/common/icon/NsIcon.styled.tsx +5 -3
- package/src/common/icon/NsIcon.tsx +9 -1
- package/src/common/icon/types.d.ts +37 -0
- package/src/common/input/InputWrapper.tsx +3 -10
- package/src/common/link/NsLink.stories.tsx +2 -2
- package/src/common/link/NsLink.styled.tsx +2 -12
- package/src/common/link/NsLink.tsx +4 -7
- package/src/common/modal/helper-component/NsModalContentBox.tsx +1 -1
- package/src/common/modal/stories/mock.tsx +1 -1
- package/src/common/nav-product-card/NsNavProductCard.tsx +1 -1
- package/src/common/progress/NsProgress.tsx +1 -1
- package/src/common/radiogroup/NsRadioGroup.styled.tsx +6 -7
- package/src/common/text-strip/NsTextStrip.tsx +1 -1
- package/src/common/typography/HtmlTagVariantMap.tsx +24 -0
- package/src/common/typography/NsTypography.stories.tsx +1 -0
- package/src/common/typography/NsTypography.tsx +7 -2
- package/src/common/typography/Typography.styled.tsx +12 -10
- package/src/common/typography/types.d.ts +15 -8
- package/src/common/util.ts +3 -1
package/package.json
CHANGED
|
@@ -2,15 +2,10 @@ import { NsTypography, NsIcon, NsAccordionHeaderProps, AccordionVariant, NsIconP
|
|
|
2
2
|
import { styled } from '@nuskin/foundation-theme';
|
|
3
3
|
import { isValidIconName } from '../icon/NsIconVariants';
|
|
4
4
|
import { getAccordionColor } from './colorMap';
|
|
5
|
-
|
|
6
|
-
shouldForwardProp: (propKey: string) => !['variant', 'invert'].includes(propKey),
|
|
7
|
-
};
|
|
5
|
+
|
|
8
6
|
type StyledType = { variant: AccordionVariantType; invert: boolean };
|
|
9
7
|
|
|
10
|
-
const StyledHeader = styled(
|
|
11
|
-
'header',
|
|
12
|
-
options
|
|
13
|
-
)<StyledType>(({ theme, variant, invert }) => {
|
|
8
|
+
const StyledHeader = styled('header')<StyledType>(({ theme, variant, invert }) => {
|
|
14
9
|
const { headBg, headText } = getAccordionColor({ theme, variant, invert, keys: ['headBg', 'headText'] });
|
|
15
10
|
let borderBottom = 'none';
|
|
16
11
|
if (variant === AccordionVariant.Compact) {
|
|
@@ -1,59 +1,52 @@
|
|
|
1
1
|
import { styled } from '@nuskin/foundation-theme';
|
|
2
|
+
import { isValidElement, ReactElement, useMemo } from 'react';
|
|
3
|
+
|
|
2
4
|
import {
|
|
5
|
+
AccordionContentTypeObject,
|
|
6
|
+
AccordionItem,
|
|
3
7
|
AccordionVariant,
|
|
4
8
|
AccordionVariantType,
|
|
5
|
-
NsCollapseProps,
|
|
6
|
-
AccordionItem,
|
|
7
9
|
NsAccordion,
|
|
8
|
-
|
|
10
|
+
NsCollapseProps,
|
|
9
11
|
} from '../';
|
|
10
12
|
import { getAccordionColor } from './colorMap';
|
|
11
|
-
import { ReactElement, isValidElement, useMemo } from 'react';
|
|
12
13
|
|
|
13
14
|
const getLevelOffset = (level: number) => {
|
|
14
15
|
return level > 1 ? (level - 1) * 16 : 0;
|
|
15
16
|
};
|
|
17
|
+
type CollapsePropsType = { variant: AccordionVariantType; level: number; invert: boolean; isChild: boolean };
|
|
16
18
|
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
export const StyledCollapse = styled('section')<CollapsePropsType>(({ theme, variant, level, invert, isChild }) => {
|
|
20
|
+
const { contentBg, contentText } = getAccordionColor({
|
|
21
|
+
theme,
|
|
22
|
+
invert,
|
|
23
|
+
variant,
|
|
24
|
+
keys: ['contentBg', 'contentText'],
|
|
25
|
+
});
|
|
20
26
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
)<{ variant: AccordionVariantType; level: number; invert: boolean; isChild: boolean }>(
|
|
25
|
-
({ theme, variant, level, invert, isChild }) => {
|
|
26
|
-
const { contentBg, contentText } = getAccordionColor({
|
|
27
|
-
theme,
|
|
28
|
-
invert,
|
|
29
|
-
variant,
|
|
30
|
-
keys: ['contentBg', 'contentText'],
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
let borderBottom = 'none';
|
|
34
|
-
if (variant === AccordionVariant.Compact) {
|
|
35
|
-
borderBottom = isChild ? 'none' : '1px solid rgb(0,0,0,0.125)';
|
|
36
|
-
}
|
|
37
|
-
return {
|
|
38
|
-
backgroundColor: contentBg,
|
|
39
|
-
color: contentText,
|
|
40
|
-
opacity: 0,
|
|
41
|
-
padding: '0 16px',
|
|
42
|
-
height: 0,
|
|
43
|
-
overflow: 'hidden',
|
|
44
|
-
transition: '0.3s',
|
|
45
|
-
'&.expanded': {
|
|
46
|
-
padding: `9px 0 9px ${getLevelOffset(level)}px`,
|
|
47
|
-
height: 'auto',
|
|
48
|
-
opacity: 1,
|
|
49
|
-
borderBottom,
|
|
50
|
-
},
|
|
51
|
-
'.nsa-content-padded': {
|
|
52
|
-
padding: '0 16px 16px',
|
|
53
|
-
},
|
|
54
|
-
};
|
|
27
|
+
let borderBottom = 'none';
|
|
28
|
+
if (variant === AccordionVariant.Compact) {
|
|
29
|
+
borderBottom = isChild ? 'none' : '1px solid rgb(0,0,0,0.125)';
|
|
55
30
|
}
|
|
56
|
-
|
|
31
|
+
return {
|
|
32
|
+
backgroundColor: contentBg,
|
|
33
|
+
color: contentText,
|
|
34
|
+
opacity: 0,
|
|
35
|
+
padding: '0 16px',
|
|
36
|
+
height: 0,
|
|
37
|
+
overflow: 'hidden',
|
|
38
|
+
transition: '0.3s',
|
|
39
|
+
'&.expanded': {
|
|
40
|
+
padding: `9px 0 9px ${getLevelOffset(level)}px`,
|
|
41
|
+
height: 'auto',
|
|
42
|
+
opacity: 1,
|
|
43
|
+
borderBottom,
|
|
44
|
+
},
|
|
45
|
+
'.nsa-content-padded': {
|
|
46
|
+
padding: '0 16px 16px',
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
});
|
|
57
50
|
|
|
58
51
|
/**
|
|
59
52
|
* NsCollapse component adds css animation while showing children items if prop `isOpen` is true,
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import React, { useEffect, useState } from 'react';
|
|
2
|
+
|
|
2
3
|
import {
|
|
3
|
-
AlertContainer,
|
|
4
4
|
Alert,
|
|
5
|
-
|
|
6
|
-
AlertHead,
|
|
5
|
+
AlertBody,
|
|
7
6
|
AlertCloseButton,
|
|
7
|
+
AlertContainer,
|
|
8
8
|
AlertContent,
|
|
9
9
|
AlertFoot,
|
|
10
|
-
|
|
10
|
+
AlertHead,
|
|
11
|
+
AlertIcon,
|
|
11
12
|
} from './NsAlert.styled';
|
|
13
|
+
|
|
12
14
|
import type { NsAlertProps, ContextType, AlertType } from './types.d';
|
|
13
15
|
import { NsIcon } from '../icon';
|
|
14
16
|
import Header, { colorMap, iconMap } from './Header';
|
|
@@ -59,7 +61,7 @@ export default function NsAlert({
|
|
|
59
61
|
</AlertHead>
|
|
60
62
|
{hasDismissListener && (
|
|
61
63
|
<AlertCloseButton data-testid="alert-close-button" onClick={onDismiss}>
|
|
62
|
-
<NsIcon name="close" size="small" />
|
|
64
|
+
<NsIcon name="close" size="small" cursor="pointer" />
|
|
63
65
|
</AlertCloseButton>
|
|
64
66
|
)}
|
|
65
67
|
<AlertContent type={alertType as AlertType}>
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { styled, ColorUtils } from '@nuskin/foundation-theme';
|
|
2
2
|
import { DarkModeEnabledOption } from '../common.types';
|
|
3
|
-
import { skipDarkModeEnabled } from '../util';
|
|
4
3
|
|
|
5
4
|
//[TODO-Arun] - Use from custom color variables
|
|
6
5
|
// const MAGENTA_COLOR = '#bb29bb';
|
|
@@ -49,10 +48,7 @@ export const Triangle = styled.div`
|
|
|
49
48
|
box-shadow: 0 0 5px 0 ${color('neutral', '20')};
|
|
50
49
|
}
|
|
51
50
|
`;
|
|
52
|
-
const
|
|
53
|
-
shouldForwardProp: skipDarkModeEnabled,
|
|
54
|
-
};
|
|
55
|
-
export const AuthHead = styled('div', options)<DarkModeEnabledOption>`
|
|
51
|
+
export const AuthHead = styled('div')<DarkModeEnabledOption>`
|
|
56
52
|
cursor: pointer;
|
|
57
53
|
padding: 5px 10px;
|
|
58
54
|
display: flex;
|
|
@@ -15,7 +15,7 @@ export const AutoCompleteButton = (props: AutoCompleteButtonProps) => {
|
|
|
15
15
|
return (
|
|
16
16
|
<li className="text-right p-3">
|
|
17
17
|
<NsButton onClick={onClick} data-testid={testId}>
|
|
18
|
-
<NsTypography variant="
|
|
18
|
+
<NsTypography variant="body-xs" weight="bold">
|
|
19
19
|
{text}
|
|
20
20
|
</NsTypography>
|
|
21
21
|
</NsButton>
|
|
@@ -5,7 +5,7 @@ import { NsTypography, OptionsProps } from '../..';
|
|
|
5
5
|
export const renderGroupName = ({ key, group, children }: AutocompleteRenderGroupParams) => (
|
|
6
6
|
<li key={key}>
|
|
7
7
|
{group ? (
|
|
8
|
-
<NsTypography variant="
|
|
8
|
+
<NsTypography variant="body-m" weight="bold" className="p-3">
|
|
9
9
|
{group}
|
|
10
10
|
</NsTypography>
|
|
11
11
|
) : null}
|
|
@@ -8,7 +8,7 @@ const OptionUiComponent = ({ option }: ListUiProps) => {
|
|
|
8
8
|
return (
|
|
9
9
|
<ListStyled>
|
|
10
10
|
<div className="item-description" role="link" tabIndex={0}>
|
|
11
|
-
<NsTypography aria-label="Nu Skin Tumbler" variant="
|
|
11
|
+
<NsTypography aria-label="Nu Skin Tumbler" variant="body-m" colorOverride="#63666A">
|
|
12
12
|
<img src={option.image} alt="No-image" />
|
|
13
13
|
{option?.value}
|
|
14
14
|
</NsTypography>
|
|
@@ -32,7 +32,7 @@ export default {
|
|
|
32
32
|
<NsTypography className="w-80" variant="h1" colorOverride="#000000">
|
|
33
33
|
Limited time offers on LumiSpa iO cleansers and bundles!
|
|
34
34
|
</NsTypography>
|
|
35
|
-
<NsTypography variant="
|
|
35
|
+
<NsTypography variant="body-m" className="my-5" colorOverride="#000000">
|
|
36
36
|
Learn more about what I do and how I can help you
|
|
37
37
|
</NsTypography>
|
|
38
38
|
<NsButton variant="contained">Contact me</NsButton>
|
|
@@ -5,7 +5,6 @@ import { ButtonConfig } from '@nuskin/foundation-theme/src/common/themes/types/b
|
|
|
5
5
|
|
|
6
6
|
import { NsButtonProps } from './types.d';
|
|
7
7
|
import { generateContainedStyle, generateIconOnlyStyles, generateOutlinedStyle, generateTextStyles } from './helper';
|
|
8
|
-
import { skipDarkModeEnabled } from '../util';
|
|
9
8
|
|
|
10
9
|
const { buttonColor, paletteColor } = ColorUtils;
|
|
11
10
|
|
|
@@ -13,49 +12,45 @@ const getButtonConfig = (theme: FoundationTheme.Theme, attribute: keyof ButtonCo
|
|
|
13
12
|
const { config } = theme || {};
|
|
14
13
|
return config?.components?.button?.[attribute] || '';
|
|
15
14
|
};
|
|
16
|
-
const options = {
|
|
17
|
-
shouldForwardProp: skipDarkModeEnabled,
|
|
18
|
-
};
|
|
19
15
|
|
|
20
|
-
export const StyledButton = styled(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
16
|
+
export const StyledButton = styled(MUIButton)<NsButtonProps>(
|
|
17
|
+
({ theme, color, size, darkModeEnabled, variant, iconOnly }) => {
|
|
18
|
+
const borderRadius = getButtonConfig(theme, 'borderRadius') || 0;
|
|
19
|
+
const focusBorderColor = getButtonConfig(theme, 'focusColor');
|
|
20
|
+
// TODO: remove as any from the theme and color
|
|
21
|
+
const sizeStyle = (theme as any)?.components?.button?.['size']?.[size ?? '']?.padding ?? {};
|
|
22
|
+
const btnColor = color as any;
|
|
23
|
+
|
|
24
|
+
let buttonStyles = {};
|
|
25
|
+
const hovered = buttonColor(btnColor, 'hovered')({ theme });
|
|
26
|
+
const pressed = buttonColor(btnColor, 'pressed')({ theme });
|
|
27
|
+
const focused = buttonColor(btnColor, 'focused')({ theme });
|
|
28
|
+
const textColor = paletteColor(btnColor, 'contrastText')({ theme, darkModeEnabled });
|
|
29
|
+
const backgroundColor = paletteColor(btnColor)({ theme, darkModeEnabled });
|
|
30
|
+
|
|
31
|
+
if (variant === 'contained') {
|
|
32
|
+
buttonStyles = generateContainedStyle({ backgroundColor, textColor, hovered, pressed, focused });
|
|
33
|
+
} else if (variant === 'outlined') {
|
|
34
|
+
const activeColor = paletteColor(btnColor)({ theme });
|
|
35
|
+
buttonStyles = generateOutlinedStyle({ borderColor: backgroundColor, hovered, pressed, activeColor });
|
|
36
|
+
} else if (variant === 'text') {
|
|
37
|
+
buttonStyles = generateTextStyles({ underlineColor: backgroundColor, hovered, pressed });
|
|
38
|
+
} else if (iconOnly) {
|
|
39
|
+
buttonStyles = generateIconOnlyStyles();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
gap: '10px',
|
|
44
|
+
borderRadius,
|
|
45
|
+
'&:focus': {
|
|
46
|
+
border: `1px solid ${focusBorderColor} !important`,
|
|
47
|
+
},
|
|
48
|
+
'&:disabled': {
|
|
49
|
+
backgroundColor: buttonColor(btnColor, 'disabled'),
|
|
50
|
+
color: buttonColor(btnColor, 'disabledText'),
|
|
51
|
+
},
|
|
52
|
+
...buttonStyles,
|
|
53
|
+
...sizeStyle,
|
|
54
|
+
};
|
|
46
55
|
}
|
|
47
|
-
|
|
48
|
-
return {
|
|
49
|
-
gap: '10px',
|
|
50
|
-
borderRadius,
|
|
51
|
-
'&:focus': {
|
|
52
|
-
border: `1px solid ${focusBorderColor} !important`,
|
|
53
|
-
},
|
|
54
|
-
'&:disabled': {
|
|
55
|
-
backgroundColor: buttonColor(btnColor, 'disabled'),
|
|
56
|
-
color: buttonColor(btnColor, 'disabledText'),
|
|
57
|
-
},
|
|
58
|
-
...buttonStyles,
|
|
59
|
-
...sizeStyle,
|
|
60
|
-
};
|
|
61
|
-
});
|
|
56
|
+
);
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import Box from '@mui/material/Box';
|
|
2
|
+
import { styled } from '@nuskin/foundation-theme';
|
|
3
|
+
import { NsImage } from '..';
|
|
4
|
+
|
|
5
|
+
type NsAwardCardProps = {
|
|
6
|
+
title: string;
|
|
7
|
+
awardName: string;
|
|
8
|
+
mediaOutlet: string;
|
|
9
|
+
backgroundImageUrl: string;
|
|
10
|
+
backgroundImageAlt: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const CardContainer = styled(Box)(() => {
|
|
14
|
+
return {
|
|
15
|
+
display: 'flex',
|
|
16
|
+
flexDirection: 'column',
|
|
17
|
+
position: 'relative',
|
|
18
|
+
backgroundColor: '#fff',
|
|
19
|
+
alignItems: 'center',
|
|
20
|
+
'.image': {
|
|
21
|
+
width: '150px',
|
|
22
|
+
height: 'auto',
|
|
23
|
+
objectFit: 'cover',
|
|
24
|
+
backgroundColor: 'red',
|
|
25
|
+
},
|
|
26
|
+
'.content': {
|
|
27
|
+
display: 'flex',
|
|
28
|
+
flexDirection: 'column',
|
|
29
|
+
alignItems: 'center',
|
|
30
|
+
},
|
|
31
|
+
'.title': {
|
|
32
|
+
fontSize: '16px',
|
|
33
|
+
fontWeight: 'bold',
|
|
34
|
+
marginTop: '30px',
|
|
35
|
+
},
|
|
36
|
+
'.awardName': {
|
|
37
|
+
fontSize: '16px',
|
|
38
|
+
fontWeight: '400',
|
|
39
|
+
marginTop: '20px',
|
|
40
|
+
},
|
|
41
|
+
'.mediaOutlet': {
|
|
42
|
+
fontSize: '11px',
|
|
43
|
+
fontWeight: '400',
|
|
44
|
+
marginTop: '20px',
|
|
45
|
+
},
|
|
46
|
+
'.action-link': {
|
|
47
|
+
marginTop: '10px',
|
|
48
|
+
fontSize: '14px',
|
|
49
|
+
alignSelf: 'start',
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
export default function NsAwardCard({
|
|
55
|
+
title,
|
|
56
|
+
awardName,
|
|
57
|
+
mediaOutlet,
|
|
58
|
+
backgroundImageUrl,
|
|
59
|
+
backgroundImageAlt,
|
|
60
|
+
}: NsAwardCardProps) {
|
|
61
|
+
return (
|
|
62
|
+
<CardContainer role="award-card" component="div" data-testid="award-card">
|
|
63
|
+
<NsImage alt={backgroundImageAlt} src={backgroundImageUrl} className="image" />
|
|
64
|
+
<div className="content">
|
|
65
|
+
<article className="title">{title}</article>
|
|
66
|
+
<article className="awardName">{awardName}</article>
|
|
67
|
+
<article className="mediaOutlet">{mediaOutlet}</article>
|
|
68
|
+
</div>
|
|
69
|
+
</CardContainer>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import Card from '@mui/material/Card';
|
|
2
2
|
import { styled } from '@nuskin/foundation-theme';
|
|
3
|
+
import { shouldNotForwardPropsWithKeys } from '../util';
|
|
3
4
|
|
|
4
5
|
type NsBgCardProps = {
|
|
5
6
|
backgroundImageUrl: string;
|
|
6
7
|
};
|
|
7
8
|
const options = {
|
|
8
|
-
shouldForwardProp: (
|
|
9
|
+
shouldForwardProp: shouldNotForwardPropsWithKeys<NsBgCardProps>(['backgroundImageUrl']),
|
|
9
10
|
};
|
|
10
11
|
const Component = ({ backgroundImageUrl }: NsBgCardProps) => {
|
|
11
12
|
const width = 256;
|
|
@@ -4,9 +4,10 @@ import { NsButton, NsIcon, NsImage, NsLink, NsIconNameType } from '..';
|
|
|
4
4
|
|
|
5
5
|
type NsLargeCardProps = {
|
|
6
6
|
title: string;
|
|
7
|
-
subtitle
|
|
7
|
+
subtitle?: string;
|
|
8
8
|
intro: string;
|
|
9
|
-
icon
|
|
9
|
+
icon?: NsIconNameType;
|
|
10
|
+
buttonVariant: 'text' | 'outlined' | 'contained';
|
|
10
11
|
backgroundImageUrl: string;
|
|
11
12
|
backgroundImageAlt: string;
|
|
12
13
|
cardLink: { href: string; title: string };
|
|
@@ -14,16 +15,16 @@ type NsLargeCardProps = {
|
|
|
14
15
|
};
|
|
15
16
|
|
|
16
17
|
const CardContainer = styled((props: any) => <Box {...props} />)(({ isHorizontal }) => {
|
|
17
|
-
let width = '
|
|
18
|
+
let width = '375px',
|
|
18
19
|
paddingLeft = '0px',
|
|
19
20
|
justifyContent,
|
|
20
|
-
fontSizeSub = '
|
|
21
|
+
fontSizeSub = '16px',
|
|
21
22
|
fontSizeTitle = '26px';
|
|
22
23
|
|
|
23
24
|
if (isHorizontal) {
|
|
24
|
-
width = '
|
|
25
|
+
width = 'unset';
|
|
25
26
|
paddingLeft = '30px';
|
|
26
|
-
justifyContent = '
|
|
27
|
+
justifyContent = 'center';
|
|
27
28
|
fontSizeSub = '16px';
|
|
28
29
|
fontSizeTitle = '36px';
|
|
29
30
|
}
|
|
@@ -33,15 +34,15 @@ const CardContainer = styled((props: any) => <Box {...props} />)(({ isHorizontal
|
|
|
33
34
|
display: 'flex',
|
|
34
35
|
flexDirection: direction,
|
|
35
36
|
position: 'relative',
|
|
37
|
+
width,
|
|
36
38
|
'.image': {
|
|
37
39
|
width: '375px',
|
|
38
|
-
height: '
|
|
40
|
+
height: 'auto',
|
|
39
41
|
objectFit: 'cover',
|
|
40
42
|
},
|
|
41
43
|
'.content': {
|
|
42
44
|
display: 'flex',
|
|
43
45
|
flexDirection: 'column',
|
|
44
|
-
width,
|
|
45
46
|
paddingLeft,
|
|
46
47
|
justifyContent,
|
|
47
48
|
},
|
|
@@ -59,6 +60,7 @@ const CardContainer = styled((props: any) => <Box {...props} />)(({ isHorizontal
|
|
|
59
60
|
display: 'flex',
|
|
60
61
|
flexDirection: 'column' as 'column',
|
|
61
62
|
width: 'fit-content',
|
|
63
|
+
|
|
62
64
|
borderBottom: '1px solid black',
|
|
63
65
|
':hover': {
|
|
64
66
|
opacity: '0.8',
|
|
@@ -68,6 +70,7 @@ const CardContainer = styled((props: any) => <Box {...props} />)(({ isHorizontal
|
|
|
68
70
|
marginTop: '10px',
|
|
69
71
|
display: 'flex',
|
|
70
72
|
fontWeight: 600,
|
|
73
|
+
width: 'fit-content',
|
|
71
74
|
':hover': {
|
|
72
75
|
textDecoration: 'none',
|
|
73
76
|
},
|
|
@@ -84,6 +87,7 @@ export default function NsLargeCard({
|
|
|
84
87
|
backgroundImageUrl,
|
|
85
88
|
backgroundImageAlt,
|
|
86
89
|
cardLink,
|
|
90
|
+
buttonVariant,
|
|
87
91
|
intro,
|
|
88
92
|
icon,
|
|
89
93
|
isHorizontal,
|
|
@@ -105,11 +109,12 @@ export default function NsLargeCard({
|
|
|
105
109
|
) : (
|
|
106
110
|
<NsButton
|
|
107
111
|
className="action-link"
|
|
108
|
-
variant=
|
|
112
|
+
variant={buttonVariant}
|
|
109
113
|
color="primary"
|
|
110
114
|
href={cardLink.href}
|
|
111
115
|
fullWidth={false}
|
|
112
116
|
darkModeEnabled={false}
|
|
117
|
+
endIcon={buttonVariant !== 'contained' ? <NsIcon className="icon" name={icon} /> : null}
|
|
113
118
|
>
|
|
114
119
|
{cardLink.title}
|
|
115
120
|
</NsButton>
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import Box from '@mui/material/Box';
|
|
2
2
|
import { styled } from '@nuskin/foundation-theme';
|
|
3
|
-
import { NsButton, NsImage } from '..';
|
|
3
|
+
import { NsButton, NsIcon, NsIconNameType, NsImage, NsTypography } from '..';
|
|
4
4
|
|
|
5
5
|
type NsMediumCardProps = {
|
|
6
6
|
title: string;
|
|
7
|
+
titleFontWeight?: 'bold' | 'normal' | 'light';
|
|
7
8
|
subtitle: string;
|
|
9
|
+
icon?: NsIconNameType;
|
|
8
10
|
backgroundImageUrl: string;
|
|
9
11
|
backgroundImageAlt: string;
|
|
12
|
+
buttonVariant: 'text' | 'outlined' | 'contained';
|
|
10
13
|
cardLink: { href: string; title: string };
|
|
11
14
|
};
|
|
12
15
|
|
|
@@ -22,16 +25,16 @@ const CardContainer = styled(Box)(() => {
|
|
|
22
25
|
},
|
|
23
26
|
'.content': {
|
|
24
27
|
display: 'flex',
|
|
28
|
+
width: '300px',
|
|
25
29
|
flexDirection: 'column',
|
|
26
30
|
},
|
|
27
31
|
'.subtitle': {
|
|
28
|
-
fontSize: '
|
|
32
|
+
fontSize: '16px',
|
|
29
33
|
fontWeight: '400',
|
|
30
34
|
marginTop: '10px',
|
|
31
35
|
},
|
|
32
36
|
'.title': {
|
|
33
|
-
fontSize: '
|
|
34
|
-
fontWeight: '400',
|
|
37
|
+
fontSize: '20px',
|
|
35
38
|
marginTop: '10px',
|
|
36
39
|
},
|
|
37
40
|
'.action-link': {
|
|
@@ -44,18 +47,30 @@ const CardContainer = styled(Box)(() => {
|
|
|
44
47
|
|
|
45
48
|
export default function NsMediumCard({
|
|
46
49
|
title,
|
|
50
|
+
titleFontWeight,
|
|
47
51
|
subtitle,
|
|
48
52
|
backgroundImageUrl,
|
|
49
53
|
backgroundImageAlt,
|
|
50
54
|
cardLink,
|
|
55
|
+
icon,
|
|
56
|
+
buttonVariant,
|
|
51
57
|
}: NsMediumCardProps) {
|
|
52
58
|
return (
|
|
53
59
|
<CardContainer role="medium-card" component="div" data-testid="medium-card">
|
|
54
60
|
<NsImage alt={backgroundImageAlt} src={backgroundImageUrl} className="image" />
|
|
55
61
|
<div className="content">
|
|
56
|
-
<
|
|
62
|
+
<NsTypography variant="h5" color="primary" className="title" weight={titleFontWeight}>
|
|
63
|
+
{title}
|
|
64
|
+
</NsTypography>
|
|
57
65
|
<article className="subtitle">{subtitle}</article>
|
|
58
|
-
<NsButton
|
|
66
|
+
<NsButton
|
|
67
|
+
className="action-link"
|
|
68
|
+
variant={buttonVariant}
|
|
69
|
+
color="primary"
|
|
70
|
+
href={cardLink.href}
|
|
71
|
+
fullWidth={false}
|
|
72
|
+
endIcon={buttonVariant !== 'contained' ? <NsIcon className="icon" name={icon} /> : null}
|
|
73
|
+
>
|
|
59
74
|
{cardLink.title}
|
|
60
75
|
</NsButton>
|
|
61
76
|
</div>
|
|
@@ -19,17 +19,14 @@ const CardContainer = styled(Box)(() => {
|
|
|
19
19
|
position: 'relative',
|
|
20
20
|
overflow: 'hidden',
|
|
21
21
|
height: 'auto',
|
|
22
|
-
width: '
|
|
22
|
+
width: '200px',
|
|
23
23
|
backgroundColor: '#fff',
|
|
24
|
-
'.image': {
|
|
25
|
-
width: '100%',
|
|
26
|
-
height: '180px',
|
|
27
|
-
display: 'block',
|
|
28
|
-
},
|
|
29
24
|
'.content': {
|
|
30
|
-
padding: '
|
|
25
|
+
padding: '10px',
|
|
31
26
|
display: 'flex',
|
|
32
27
|
flexDirection: 'column',
|
|
28
|
+
minHeight: '150px',
|
|
29
|
+
justifyContent: 'space-between',
|
|
33
30
|
},
|
|
34
31
|
'.body-title': {
|
|
35
32
|
fontSize: '18px',
|
package/src/common/card/index.ts
CHANGED
|
@@ -11,3 +11,4 @@ export { default as NsSmallFullCard } from './NsSmallFullCard';
|
|
|
11
11
|
export { default as NsXLargeCard } from './NsXLargeCard';
|
|
12
12
|
export { default as NsLargeCard } from './NsLargeCard';
|
|
13
13
|
export { default as NsMediumCard } from './NsMediumCard';
|
|
14
|
+
export { default as NsAwardCard } from './NsAwardCard';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { StoryObj, Meta } from '@storybook/react';
|
|
2
|
+
import { withCenterDecorator } from '@/stories/decorators/withCenterDecorator';
|
|
3
|
+
import { NsAwardCard } from '../';
|
|
4
|
+
|
|
5
|
+
type ComponentType = typeof NsAwardCard;
|
|
6
|
+
type Story = StoryObj<ComponentType>;
|
|
7
|
+
type MetaStory = Meta<ComponentType>;
|
|
8
|
+
|
|
9
|
+
export default {
|
|
10
|
+
component: NsAwardCard,
|
|
11
|
+
title: 'Components/Containers/Card/NsAwardCard',
|
|
12
|
+
argTypes: {},
|
|
13
|
+
decorators: [withCenterDecorator],
|
|
14
|
+
} as MetaStory;
|
|
15
|
+
|
|
16
|
+
const host = 'https://media.nuskin.com';
|
|
17
|
+
|
|
18
|
+
export const Default: Story = {
|
|
19
|
+
args: {
|
|
20
|
+
title: 'AgeLoc LumiSpa iO',
|
|
21
|
+
awardName: '2023 Bronze Winner',
|
|
22
|
+
mediaOutlet: 'Edison Awards',
|
|
23
|
+
backgroundImageUrl: `${host}/m/2ec571a87dc9680c/Small-Edison-Bronze-Logo-Homepage.jpg`,
|
|
24
|
+
backgroundImageAlt: 'Edison Bronze Logo',
|
|
25
|
+
},
|
|
26
|
+
};
|
|
@@ -18,15 +18,16 @@ const host = 'https://media.nuskin.com';
|
|
|
18
18
|
export const Default: Story = {
|
|
19
19
|
args: {
|
|
20
20
|
isHorizontal: false,
|
|
21
|
-
title: '
|
|
21
|
+
title: 'Personal Care',
|
|
22
22
|
subtitle: 'Subtitle',
|
|
23
|
-
intro: '
|
|
23
|
+
intro: 'Nu Skin® product lines combine nature and science for skincare benefits you can see and feel.',
|
|
24
24
|
icon: 'cart',
|
|
25
25
|
cardLink: {
|
|
26
26
|
href: 'https://www.forceforgood.org/',
|
|
27
|
-
title: '
|
|
27
|
+
title: 'REVEAL YOUR BEST SKIN',
|
|
28
28
|
},
|
|
29
|
-
|
|
29
|
+
buttonVariant: 'outlined',
|
|
30
|
+
backgroundImageUrl: `${host}/m/95f9cf4143e3882/Small-About_Us-Personal-Care-Products-Image.jpg`,
|
|
30
31
|
backgroundImageAlt: 'Facial Moisturizers',
|
|
31
32
|
},
|
|
32
33
|
};
|
|
@@ -17,12 +17,16 @@ const host = 'https://media.nuskin.com';
|
|
|
17
17
|
|
|
18
18
|
export const Default: Story = {
|
|
19
19
|
args: {
|
|
20
|
-
title: '
|
|
21
|
-
|
|
20
|
+
title: 'Sustainability',
|
|
21
|
+
titleFontWeight: 'bold',
|
|
22
|
+
subtitle:
|
|
23
|
+
'We’re committed to keeping our global communities clean, safe, and protected for the future. We’re proud to embrace sustainable practices today for a resource-rich tomorrow.',
|
|
22
24
|
cardLink: {
|
|
23
25
|
href: 'https://www.forceforgood.org/',
|
|
24
|
-
title: '
|
|
26
|
+
title: 'SEE WHAT WE’RE DOING',
|
|
25
27
|
},
|
|
28
|
+
icon: 'arrowRight',
|
|
29
|
+
buttonVariant: 'outlined',
|
|
26
30
|
backgroundImageUrl: `${host}/m/3353b9c05cb83860/Small-category-facial_moisturizers.jpg`,
|
|
27
31
|
backgroundImageAlt: 'Lumi Spa',
|
|
28
32
|
},
|