@nuskin/foundation-ui-components 1.1.0 → 1.1.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 +15 -11
- package/src/common/accordion/NsAccordion.tsx +32 -40
- package/src/common/accordion/NsAccordionHeader.tsx +29 -8
- package/src/common/accordion/NsAccordionItem.tsx +24 -4
- package/src/common/accordion/NsCollapse.tsx +96 -35
- package/src/common/accordion/NsToggleSection.tsx +16 -3
- package/src/common/accordion/ToggleSection.styled.tsx +11 -7
- package/src/common/accordion/colorMap.ts +117 -0
- package/src/common/accordion/enums.ts +18 -0
- package/src/common/accordion/index.ts +1 -0
- package/src/common/accordion/specs/NsAccordion.spec.tsx +101 -31
- package/src/common/accordion/specs/NsAccordionHeader.spec.tsx +77 -10
- package/src/common/accordion/specs/NsAccordionItem.spec.tsx +27 -10
- package/src/common/accordion/specs/NsCollapse.spec.tsx +109 -17
- package/src/common/accordion/specs/NsToggleSection.spec.tsx +50 -14
- package/src/common/accordion/stories/NsAccordion.stories.tsx +31 -13
- package/src/common/accordion/stories/NsAccordionHeader.stories.tsx +5 -1
- package/src/common/accordion/stories/NsAccordionItem.stories.tsx +8 -3
- package/src/common/accordion/stories/NsCollapse.stories.tsx +19 -4
- package/src/common/accordion/stories/NsToggleSection.stories.tsx +6 -3
- package/src/common/accordion/stories/data.tsx +140 -19
- package/src/common/accordion/types.d.ts +55 -47
- package/src/common/alert/Header.tsx +29 -0
- package/src/common/alert/NsAlert.spec.tsx +46 -13
- package/src/common/alert/NsAlert.stories.tsx +1 -1
- package/src/common/alert/{NsAlert.styled.ts → NsAlert.styled.tsx} +22 -22
- package/src/common/alert/NsAlert.tsx +22 -87
- package/src/common/alert/types.d.ts +7 -7
- package/src/common/auth-dropdown/NsAuthDropdown.spec.tsx +23 -5
- package/src/common/auth-dropdown/NsAuthDropdown.styled.ts +9 -2
- package/src/common/auth-dropdown/NsAuthDropdown.tsx +4 -4
- package/src/common/autocomplete/NsAutocomplete.spec.tsx +34 -11
- package/src/common/autocomplete/NsAutocomplete.stories.tsx +18 -2
- package/src/common/autocomplete/NsAutocomplete.tsx +63 -24
- package/src/common/autocomplete/mock/MockData.ts +50 -7
- package/src/common/autocomplete/mock/MockUI.tsx +2 -1
- package/src/common/autocomplete/types.d.ts +7 -4
- package/src/common/banner/NsBanner.spec.tsx +12 -3
- package/src/common/brand-components/NsBrandComponent.tsx +2 -2
- package/src/common/breadcrumb/NsBreadcrumb.spec.tsx +8 -3
- package/src/common/breadcrumb/data.ts +8 -5
- package/src/common/button/NsButton.spec.tsx +65 -49
- package/src/common/button/NsButton.stories.tsx +40 -4
- package/src/common/button/NsButton.styled.tsx +49 -66
- package/src/common/button/NsButton.tsx +1 -2
- package/src/common/button/helper.ts +82 -0
- package/src/common/card/NsFfgCard.tsx +13 -7
- package/src/common/card/specs/NsFfgCard.spec.tsx +18 -8
- package/src/common/card/stories/NsFfgCard.stories.tsx +47 -14
- package/src/common/card/styled/NsFfgStyled.tsx +10 -7
- package/src/common/card/types.d.ts +7 -4
- package/src/common/carousal/NsCarousal.tsx +3 -9
- package/src/common/cart-icon/NsCartIcon.spec.tsx +5 -16
- package/src/common/cart-icon/NsCartIcon.stories.tsx +1 -1
- package/src/common/cart-icon/NsCartIcon.styled.ts +7 -33
- package/src/common/cart-icon/NsCartIcon.tsx +5 -14
- package/src/common/cart-icon/types.d.ts +1 -0
- package/src/common/checkbox/NsCheckbox.styled.tsx +15 -16
- package/src/common/checkbox/NsCheckbox.tsx +1 -1
- package/src/common/column-control/styled/common.ts +1 -1
- package/src/common/column-control/utils.ts +4 -4
- package/src/common/common.types.d.ts +14 -5
- package/src/common/dropdown/NsDropdown.styled.tsx +23 -18
- package/src/common/hooks/index.ts +2 -0
- package/src/common/hooks/specs/useWindowSize.spec.tsx +19 -0
- package/src/common/hooks/useAccordionMap.tsx +39 -0
- package/src/common/hooks/useWindowSize.tsx +30 -0
- package/src/common/icon/NsIcon.spec.tsx +1 -1
- package/src/common/icon/NsIcon.stories.tsx +3 -0
- package/src/common/icon/NsIcon.tsx +6 -2
- package/src/common/icon/NsIconVariants.ts +4 -1
- package/src/common/icon/icons/AlertErrorIcon.tsx +2 -2
- package/src/common/icon/icons/ArrowLeft.tsx +3 -6
- package/src/common/icon/icons/ArrowRight.tsx +6 -8
- package/src/common/icon/icons/Cart.tsx +7 -32
- package/src/common/icon/icons/CartBadge.tsx +2 -2
- package/src/common/icon/icons/CloseIcon.tsx +1 -1
- package/src/common/icon/icons/ErrorIcon.tsx +2 -2
- package/src/common/icon/icons/HamburgerIcon.tsx +5 -2
- package/src/common/icon/icons/SearchIcon.tsx +1 -1
- package/src/common/icon/icons/SuccessIcon.tsx +2 -7
- package/src/common/icon/icons/TrashIcon.tsx +1 -1
- package/src/common/icon/icons/UserIcon.tsx +3 -6
- package/src/common/icon/icons/UserOutline.tsx +24 -0
- package/src/common/icon/icons/WarningIcon.tsx +1 -1
- package/src/common/icon/icons/home.tsx +1 -1
- package/src/common/image/NsImage.spec.tsx +56 -6
- package/src/common/image/NsImage.tsx +23 -11
- package/src/common/index.ts +6 -2
- package/src/common/input/InputWrapper.tsx +12 -7
- package/src/common/input/NsInputField.tsx +1 -1
- package/src/common/modal/NsModal.spec.tsx +46 -0
- package/src/common/modal/NsModal.styled.tsx +28 -0
- package/src/common/modal/NsModal.tsx +37 -0
- package/src/common/modal/helper-component/NsModalContentBox.tsx +32 -0
- package/src/common/modal/helper-component/NsModalDefault.tsx +25 -0
- package/src/common/modal/helper-component/NsModalStatus.tsx +15 -0
- package/src/common/modal/helper-component/NsModalStatusIcon.tsx +14 -0
- package/src/common/modal/helper-component/NsModalTitle.tsx +26 -0
- package/src/common/modal/index.ts +2 -0
- package/src/common/modal/model/NsModalVariantMap.tsx +24 -0
- package/src/common/modal/stories/NsModal.stories.tsx +85 -0
- package/src/common/modal/stories/mock.tsx +46 -0
- package/src/common/modal/types.ts +56 -0
- package/src/common/nav-tab/NavDrawer.tsx +34 -0
- package/src/common/nav-tab/NavTitles.tsx +52 -0
- package/src/common/nav-tab/NsNavTab.spec.tsx +4 -5
- package/src/common/nav-tab/NsNavTab.stories.tsx +3 -3
- package/src/common/nav-tab/NsNavTab.styled.tsx +13 -7
- package/src/common/nav-tab/NsNavTab.tsx +21 -75
- package/src/common/nav-tab/index.ts +1 -1
- package/src/common/nav-tab/types.d.ts +3 -3
- package/src/common/radiogroup/NsRadioGroup.spec.tsx +24 -25
- package/src/common/radiogroup/NsRadioGroup.stories.tsx +13 -31
- package/src/common/radiogroup/NsRadioGroup.styled.tsx +20 -19
- package/src/common/radiogroup/NsRadioGroup.tsx +6 -5
- package/src/common/search-bar/NsSearchBar.tsx +1 -3
- package/src/common/select/NsSelect.spec.tsx +10 -17
- package/src/common/select/NsSelect.styled.tsx +53 -34
- package/src/common/select/stories/NsSelect.stories.tsx +10 -10
- package/src/common/select/types.d.ts +3 -3
- package/src/common/spinner/NsSpinner.spec.tsx +21 -0
- package/src/common/spinner/NsSpinner.stories.tsx +26 -0
- package/src/common/spinner/NsSpinner.styled.tsx +344 -0
- package/src/common/spinner/NsSpinner.tsx +14 -0
- package/src/common/spinner/icons/Spinner.tsx +161 -0
- package/src/common/spinner/index.ts +2 -0
- package/src/common/spinner/types.ts +5 -0
- package/src/common/table/NsTable.tsx +32 -49
- package/src/common/table/NsTableHeader.tsx +30 -51
- package/src/common/util.ts +1 -0
- package/src/common/utility/Show.tsx +13 -0
- package/src/common/utility/index.ts +1 -0
- package/src/common/videos/types.d.ts +1 -1
- /package/src/common/brand-components/{NsBrandContanier.styled.tsx → NsBrandContainer.styled.tsx} +0 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { Show } from '../utility';
|
|
3
|
+
import { NavDrawerContainer, NavDrawerStyled } from './NsNavTab.styled';
|
|
4
|
+
|
|
5
|
+
type NavDrawerProps = {
|
|
6
|
+
active: string | null;
|
|
7
|
+
showDrawer: boolean;
|
|
8
|
+
content: ReactNode;
|
|
9
|
+
};
|
|
10
|
+
export const NavDrawer = ({ active, showDrawer, content }: NavDrawerProps) => {
|
|
11
|
+
return (
|
|
12
|
+
<NavDrawerStyled data-testid="nav-drawer-container" className="nav-drawer">
|
|
13
|
+
<Show when={Boolean(active) && showDrawer}>
|
|
14
|
+
<NavDrawerContainer
|
|
15
|
+
data-testid="nav-drawer"
|
|
16
|
+
initial={{
|
|
17
|
+
height: 0,
|
|
18
|
+
}}
|
|
19
|
+
animate={{
|
|
20
|
+
height: 'auto',
|
|
21
|
+
}}
|
|
22
|
+
exit={{
|
|
23
|
+
height: 0,
|
|
24
|
+
}}
|
|
25
|
+
transition={{
|
|
26
|
+
duration: 0.3,
|
|
27
|
+
}}
|
|
28
|
+
>
|
|
29
|
+
<div className="drawer-container">{content}</div>
|
|
30
|
+
</NavDrawerContainer>
|
|
31
|
+
</Show>
|
|
32
|
+
</NavDrawerStyled>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { NsTypography } from '../';
|
|
2
|
+
import { NavTabBox, NavTabUnderLine, NavTitlesBox } from './NsNavTab.styled';
|
|
3
|
+
import { Show } from '../utility';
|
|
4
|
+
|
|
5
|
+
type NavTitlesProps = {
|
|
6
|
+
tabs: any[];
|
|
7
|
+
// eslint-disable-next-line no-unused-vars
|
|
8
|
+
setActive(_x: string): void;
|
|
9
|
+
active: string | null;
|
|
10
|
+
tabTitleClassName?: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const NavTitles = ({ tabs, setActive, active, tabTitleClassName }: NavTitlesProps) => {
|
|
14
|
+
return (
|
|
15
|
+
<NavTitlesBox className="desktop-nav-titles">
|
|
16
|
+
{tabs?.map((tab) => {
|
|
17
|
+
const handleMouseEnter = () => {
|
|
18
|
+
setActive(tab.tabName);
|
|
19
|
+
};
|
|
20
|
+
return (
|
|
21
|
+
<div
|
|
22
|
+
key={tab?.tabName}
|
|
23
|
+
data-testid={tab?.tabName}
|
|
24
|
+
className="relative cursor-pointer"
|
|
25
|
+
onMouseEnter={handleMouseEnter}
|
|
26
|
+
>
|
|
27
|
+
<NavTabBox
|
|
28
|
+
className="nav-tab-box"
|
|
29
|
+
data-testid={tab.tabName + '-list'}
|
|
30
|
+
transition={{
|
|
31
|
+
duration: 0.3,
|
|
32
|
+
}}
|
|
33
|
+
animate
|
|
34
|
+
>
|
|
35
|
+
<NsTypography
|
|
36
|
+
variant={tab.textVariant}
|
|
37
|
+
additionalProps={{ ...tab?.liveTag }}
|
|
38
|
+
className={`${tabTitleClassName} ${!active ? 'opacity-8' : ''}`}
|
|
39
|
+
color={tab.tabName === active ? tab.activeColor : tab.color}
|
|
40
|
+
>
|
|
41
|
+
{tab.tabName}
|
|
42
|
+
</NsTypography>
|
|
43
|
+
</NavTabBox>
|
|
44
|
+
<Show when={active === tab.tabName}>
|
|
45
|
+
<NavTabUnderLine data-testid="underline" layoutId="underline" color={tab.activeColor} />
|
|
46
|
+
</Show>
|
|
47
|
+
</div>
|
|
48
|
+
);
|
|
49
|
+
})}
|
|
50
|
+
</NavTitlesBox>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { fireEvent } from '@testing-library/react';
|
|
2
2
|
import { NsNavTabComponent } from './NsNavTab';
|
|
3
|
-
import { NavTabs } from './types
|
|
3
|
+
import { NavTabs } from './types';
|
|
4
4
|
import { render } from '@/test-utils/index';
|
|
5
5
|
|
|
6
6
|
const tabs: NavTabs[] = [
|
|
7
7
|
{
|
|
8
8
|
tabName: 'Skin & Beauty',
|
|
9
9
|
tabContent: <>Skin & Beauty</>,
|
|
10
|
-
color: 'primary',
|
|
11
10
|
activeColor: 'success',
|
|
12
11
|
textVariant: 'h5',
|
|
13
12
|
},
|
|
@@ -37,7 +36,7 @@ const tabs: NavTabs[] = [
|
|
|
37
36
|
describe('Nav Bar Component', () => {
|
|
38
37
|
it('1. should render Nav Bar Component with variant', () => {
|
|
39
38
|
const { container } = render(
|
|
40
|
-
<NsNavTabComponent tabTitleClassName="text-center"
|
|
39
|
+
<NsNavTabComponent tabTitleClassName="text-center" className="mb-2" tabs={tabs} />
|
|
41
40
|
);
|
|
42
41
|
const li = container.querySelectorAll('li');
|
|
43
42
|
expect(li.length).toBe(4);
|
|
@@ -45,7 +44,7 @@ describe('Nav Bar Component', () => {
|
|
|
45
44
|
expect(container).toBeInTheDocument();
|
|
46
45
|
});
|
|
47
46
|
|
|
48
|
-
it('should
|
|
47
|
+
it('2. should open and close the drawer', () => {
|
|
49
48
|
const { container, getByTestId } = render(<NsNavTabComponent showDrawer className="mb-2" tabs={tabs} />);
|
|
50
49
|
const li = container.querySelectorAll('li');
|
|
51
50
|
expect(li.length).toBe(4);
|
|
@@ -57,7 +56,7 @@ describe('Nav Bar Component', () => {
|
|
|
57
56
|
expect(getByTestId('nav-drawer-container').firstChild).not.toBeInTheDocument();
|
|
58
57
|
});
|
|
59
58
|
|
|
60
|
-
it('should show the underline on hover', () => {
|
|
59
|
+
it('3. should show the underline on hover', () => {
|
|
61
60
|
const { getByTestId } = render(<NsNavTabComponent showDrawer={false} className="mb-2" tabs={tabs} />);
|
|
62
61
|
fireEvent.mouseOver(getByTestId('Skin & Beauty'));
|
|
63
62
|
expect(getByTestId('underline')).toBeInTheDocument();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { StoryObj, Meta } from '@storybook/react';
|
|
2
2
|
import { withCenterDecorator } from '@/stories/decorators/withCenterDecorator';
|
|
3
|
-
import { NsNavTab } from '
|
|
3
|
+
import { NsNavTab } from '.';
|
|
4
4
|
|
|
5
5
|
type ComponentType = typeof NsNavTab;
|
|
6
6
|
type Story = StoryObj<ComponentType>;
|
|
@@ -19,14 +19,14 @@ export default {
|
|
|
19
19
|
tabName: 'Tab One',
|
|
20
20
|
activeColor: 'info',
|
|
21
21
|
color: 'primary',
|
|
22
|
-
tabContent: '
|
|
22
|
+
tabContent: 'Tab one content',
|
|
23
23
|
textVariant: 'h5',
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
26
|
tabName: 'Tab Two',
|
|
27
27
|
activeColor: 'info',
|
|
28
28
|
color: 'primary',
|
|
29
|
-
tabContent: '
|
|
29
|
+
tabContent: 'Tab two content',
|
|
30
30
|
textVariant: 'h5',
|
|
31
31
|
},
|
|
32
32
|
],
|
|
@@ -3,14 +3,13 @@ import { motion } from 'framer-motion';
|
|
|
3
3
|
|
|
4
4
|
const { paletteColor } = ColorUtils;
|
|
5
5
|
|
|
6
|
-
|
|
7
6
|
export const NavTabContainer = styled.div`
|
|
8
7
|
.shadow {
|
|
9
8
|
box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.15);
|
|
10
9
|
}
|
|
11
10
|
`;
|
|
12
11
|
|
|
13
|
-
export const
|
|
12
|
+
export const NavTabBox = styled(motion.li)`
|
|
14
13
|
margin: 0px 14px;
|
|
15
14
|
align-items: center;
|
|
16
15
|
white-space: normal;
|
|
@@ -19,17 +18,17 @@ export const NavTabLine = styled(motion.li)`
|
|
|
19
18
|
list-style: none;
|
|
20
19
|
position: relative;
|
|
21
20
|
min-width: 60px;
|
|
21
|
+
padding: 8px 4px;
|
|
22
22
|
`;
|
|
23
23
|
|
|
24
24
|
export const NavTabUnderLine = styled(motion.div)<{ color?: FoundationTheme.PaletteColors }>`
|
|
25
25
|
width: 100%;
|
|
26
26
|
position: absolute;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
background-color: ${({ theme, color = 'primary' }) => paletteColor(color)({ theme })};
|
|
27
|
+
height: 3px;
|
|
28
|
+
background-color: ${({ theme, color }) => paletteColor(color)({ theme })};
|
|
30
29
|
`;
|
|
31
30
|
|
|
32
|
-
export const
|
|
31
|
+
export const NavDrawerStyled = styled.div`
|
|
33
32
|
position: absolute;
|
|
34
33
|
left: 0;
|
|
35
34
|
display: flex;
|
|
@@ -63,6 +62,13 @@ export const NavDrawerContainer = styled(motion.div)`
|
|
|
63
62
|
max-height: 590px;
|
|
64
63
|
overflow: auto;
|
|
65
64
|
.drawer-container {
|
|
66
|
-
max-width:
|
|
65
|
+
max-width: 1024px;
|
|
66
|
+
margin: 0 auto;
|
|
67
|
+
overflow: hidden;
|
|
67
68
|
}
|
|
68
69
|
`;
|
|
70
|
+
|
|
71
|
+
export const NavTitlesBox = styled.div`
|
|
72
|
+
display: flex;
|
|
73
|
+
height: 39px;
|
|
74
|
+
`;
|
|
@@ -1,89 +1,35 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useCallback, useState } from 'react';
|
|
2
2
|
import { LayoutGroup } from 'framer-motion';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { NavTabContainer } from './NsNavTab.styled';
|
|
4
|
+
import { NavDrawer } from './NavDrawer';
|
|
5
|
+
import { NsNavTabComponentProps } from './types.d';
|
|
6
|
+
import { NavTitles } from './NavTitles';
|
|
6
7
|
|
|
7
|
-
export const NsNavTabComponent = (
|
|
8
|
-
|
|
8
|
+
export const NsNavTabComponent = ({
|
|
9
|
+
tabs,
|
|
10
|
+
className,
|
|
11
|
+
tabTitleClassName,
|
|
12
|
+
showDrawer = true,
|
|
13
|
+
}: NsNavTabComponentProps) => {
|
|
9
14
|
const [active, setActive] = useState<string | null>(null);
|
|
10
15
|
|
|
11
16
|
const activeTab = tabs?.find((tab) => tab.tabName === active);
|
|
12
17
|
|
|
13
|
-
const handleLeave = () => {
|
|
18
|
+
const handleLeave = useCallback(() => {
|
|
14
19
|
setActive(null);
|
|
15
|
-
};
|
|
20
|
+
}, []);
|
|
16
21
|
|
|
17
22
|
return (
|
|
18
|
-
<NavTabContainer data-testid="nav-container" className={className}>
|
|
23
|
+
<NavTabContainer data-testid="nav-container" className={`${className} ns-nav-tab-component`}>
|
|
19
24
|
<LayoutGroup>
|
|
20
25
|
<div onMouseLeave={handleLeave} data-testid="nav-container-draw" className="p-0 m-0">
|
|
21
|
-
<
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
<div
|
|
29
|
-
key={tab?.tabName}
|
|
30
|
-
data-testid={tab?.tabName}
|
|
31
|
-
className="relative cursor-pointer"
|
|
32
|
-
onMouseEnter={handleMouseEnter}
|
|
33
|
-
>
|
|
34
|
-
<NavTabLine
|
|
35
|
-
data-testid={tab.tabName + '-list'}
|
|
36
|
-
transition={{
|
|
37
|
-
duration: 0.3,
|
|
38
|
-
}}
|
|
39
|
-
animate
|
|
40
|
-
>
|
|
41
|
-
<NsTypography
|
|
42
|
-
variant={tab.textVariant}
|
|
43
|
-
additionalProps={{ ...tab?.liveTag }}
|
|
44
|
-
className={`mb-2 ${tabTitleClassName} ${!active ? 'opacity-8' : ''}`}
|
|
45
|
-
color={tab.tabName === active ? tab.activeColor : tab.color}
|
|
46
|
-
>
|
|
47
|
-
{tab.tabName}
|
|
48
|
-
</NsTypography>
|
|
49
|
-
</NavTabLine>
|
|
50
|
-
{active === tab.tabName && (
|
|
51
|
-
<NavTabUnderLine
|
|
52
|
-
data-testid="underline"
|
|
53
|
-
layoutId="underline"
|
|
54
|
-
color={tab.activeColor}
|
|
55
|
-
/>
|
|
56
|
-
)}
|
|
57
|
-
</div>
|
|
58
|
-
);
|
|
59
|
-
})}
|
|
60
|
-
</div>
|
|
61
|
-
</div>
|
|
62
|
-
<NavDrawer data-testid="nav-drawer-container">
|
|
63
|
-
{active && showDrawer ? (
|
|
64
|
-
<NavDrawerContainer
|
|
65
|
-
data-testid="nav-drawer"
|
|
66
|
-
initial={{
|
|
67
|
-
height: 0,
|
|
68
|
-
}}
|
|
69
|
-
animate={{
|
|
70
|
-
height: 'auto',
|
|
71
|
-
}}
|
|
72
|
-
exit={{
|
|
73
|
-
height: 0,
|
|
74
|
-
}}
|
|
75
|
-
transition={{
|
|
76
|
-
duration: 0.3,
|
|
77
|
-
}}
|
|
78
|
-
>
|
|
79
|
-
{active ? (
|
|
80
|
-
<div className="flex w-full overflow-hidden justify-center">
|
|
81
|
-
<div className="drawer-container w-full">{activeTab?.tabContent}</div>
|
|
82
|
-
</div>
|
|
83
|
-
) : null}
|
|
84
|
-
</NavDrawerContainer>
|
|
85
|
-
) : null}
|
|
86
|
-
</NavDrawer>
|
|
26
|
+
<NavTitles
|
|
27
|
+
tabTitleClassName={tabTitleClassName}
|
|
28
|
+
tabs={tabs}
|
|
29
|
+
active={active}
|
|
30
|
+
setActive={setActive}
|
|
31
|
+
/>
|
|
32
|
+
<NavDrawer active={active} content={activeTab?.tabContent} showDrawer={showDrawer} />
|
|
87
33
|
</div>
|
|
88
34
|
</LayoutGroup>
|
|
89
35
|
</NavTabContainer>
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { NsNavTabComponent as NsNavTab } from './NsNavTab';
|
|
2
|
-
export type {
|
|
2
|
+
export type { NsNavTabComponentProps, NavTabs } from './types';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
2
|
import { FoundationTheme } from '@nuskin/foundation-theme';
|
|
3
3
|
import { Variants } from '../typography/types';
|
|
4
|
-
import { AdditionalProps,
|
|
4
|
+
import { AdditionalProps, CslpTag } from '../common.types';
|
|
5
5
|
|
|
6
6
|
export type NavTabs = {
|
|
7
7
|
tabName: string;
|
|
@@ -9,10 +9,10 @@ export type NavTabs = {
|
|
|
9
9
|
activeColor: FoundationTheme.PaletteColors;
|
|
10
10
|
color?: FoundationTheme.PaletteColors;
|
|
11
11
|
textVariant: Variants;
|
|
12
|
-
liveTag?:
|
|
12
|
+
liveTag?: CslpTag;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
export type
|
|
15
|
+
export type NsNavTabComponentProps = {
|
|
16
16
|
tabs: NavTabs[];
|
|
17
17
|
className?: string;
|
|
18
18
|
tabTitleClassName?: string;
|
|
@@ -3,14 +3,12 @@ import { render, fireEvent, screen } from '@testing-library/react';
|
|
|
3
3
|
import { NsRadioGroup } from './';
|
|
4
4
|
import { FoundationTheme } from '@nuskin/foundation-theme';
|
|
5
5
|
|
|
6
|
-
|
|
7
6
|
describe('NsRadioGroup', () => {
|
|
8
|
-
|
|
9
7
|
const options = [
|
|
10
8
|
{ id: 'Option1', label: 'Option 1', value: 'Option1' },
|
|
11
9
|
{ id: 'Option2', label: 'Option 2', value: 'Option2' },
|
|
12
10
|
{ id: 'Option3', label: 'Option 3', value: 'Option3' },
|
|
13
|
-
]
|
|
11
|
+
];
|
|
14
12
|
|
|
15
13
|
const props = {
|
|
16
14
|
disable: false,
|
|
@@ -27,38 +25,39 @@ describe('NsRadioGroup', () => {
|
|
|
27
25
|
};
|
|
28
26
|
const onChange = jest.fn();
|
|
29
27
|
|
|
30
|
-
it('renders options correctly', () => {
|
|
31
|
-
render(
|
|
32
|
-
<NsRadioGroup {...props} onChange={onChange}
|
|
33
|
-
/>,
|
|
34
|
-
);
|
|
28
|
+
it('1. renders options correctly', () => {
|
|
29
|
+
render(<NsRadioGroup {...props} onChange={onChange} />);
|
|
35
30
|
|
|
36
31
|
options.forEach((option) => {
|
|
37
32
|
const radioOption = screen.getByLabelText(option.label) as HTMLInputElement;
|
|
38
33
|
expect(radioOption).toBeInTheDocument();
|
|
39
|
-
expect(radioOption.value).toBe(option.value)
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
|
|
34
|
+
expect(radioOption.value).toBe(option.value);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
it('2. renders options correctly without additional slot', () => {
|
|
38
|
+
render(<NsRadioGroup {...props} onChange={onChange} additionalSlot={''} />);
|
|
43
39
|
|
|
44
|
-
|
|
40
|
+
options.forEach((option) => {
|
|
41
|
+
const radioOption = screen.getByLabelText(option.label) as HTMLInputElement;
|
|
42
|
+
expect(radioOption).toBeInTheDocument();
|
|
43
|
+
expect(radioOption.value).toBe(option.value);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
45
46
|
|
|
46
|
-
|
|
47
|
+
it('3. calls OnChange when selecting option', () => {
|
|
48
|
+
render(<NsRadioGroup {...props} onChange={onChange} />);
|
|
47
49
|
|
|
48
|
-
const radioOption = screen.getByLabelText('Option 2') as HTMLInputElement
|
|
50
|
+
const radioOption = screen.getByLabelText('Option 2') as HTMLInputElement;
|
|
49
51
|
fireEvent.click(radioOption);
|
|
50
52
|
expect(onChange).toHaveBeenCalledTimes(1);
|
|
53
|
+
});
|
|
51
54
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
it('does not call Onchange when the same option is clicked', () => {
|
|
55
|
+
it('4. does not call Onchange when the same option is clicked', () => {
|
|
55
56
|
const onChange = jest.fn();
|
|
56
|
-
render(<NsRadioGroup {...props} onChange={onChange} />)
|
|
57
|
+
render(<NsRadioGroup {...props} onChange={onChange} />);
|
|
57
58
|
|
|
58
|
-
const radioOption = screen.getByLabelText('Option 1') as HTMLInputElement
|
|
59
|
-
fireEvent.click(radioOption)
|
|
59
|
+
const radioOption = screen.getByLabelText('Option 1') as HTMLInputElement;
|
|
60
|
+
fireEvent.click(radioOption);
|
|
60
61
|
expect(onChange).not.toHaveBeenCalled();
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
})
|
|
62
|
+
});
|
|
63
|
+
});
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
|
|
2
1
|
import type { StoryObj, Meta } from '@storybook/react';
|
|
3
2
|
import { within, userEvent } from '@storybook/testing-library';
|
|
4
3
|
import { expect } from '@storybook/jest';
|
|
5
|
-
import { NsRadioGroup } from './'
|
|
4
|
+
import { NsRadioGroup } from './';
|
|
6
5
|
import { FoundationTheme } from '@nuskin/foundation-theme';
|
|
7
6
|
|
|
8
7
|
type ComponentType = typeof NsRadioGroup;
|
|
@@ -14,43 +13,29 @@ export default {
|
|
|
14
13
|
title: 'Components/Inputs/NsRadioGroup',
|
|
15
14
|
argTypes: {
|
|
16
15
|
disable: {
|
|
17
|
-
description:
|
|
18
|
-
'Indicates whether the radio button is enabled/disabled',
|
|
19
|
-
|
|
16
|
+
description: 'Indicates whether the radio button is enabled/disabled',
|
|
20
17
|
},
|
|
21
18
|
items: {
|
|
22
|
-
description:
|
|
23
|
-
'Value of the component to be emitted when selected.',
|
|
19
|
+
description: 'Value of the component to be emitted when selected.',
|
|
24
20
|
},
|
|
25
21
|
name: {
|
|
26
|
-
description:
|
|
27
|
-
'Name of the component',
|
|
28
|
-
|
|
22
|
+
description: 'Name of the component',
|
|
29
23
|
},
|
|
30
24
|
label: {
|
|
31
|
-
description:
|
|
32
|
-
'Label of the radio group',
|
|
33
|
-
|
|
25
|
+
description: 'Label of the radio group',
|
|
34
26
|
},
|
|
35
27
|
color: {
|
|
36
|
-
description:
|
|
37
|
-
'Color of the radio button',
|
|
38
|
-
|
|
28
|
+
description: 'Color of the radio button',
|
|
39
29
|
},
|
|
40
30
|
size: {
|
|
41
|
-
description:
|
|
42
|
-
'Margin Left for Additional Slot text',
|
|
43
|
-
|
|
31
|
+
description: 'Margin Left for Additional Slot text',
|
|
44
32
|
},
|
|
45
33
|
labelFontSize: {
|
|
46
|
-
description:
|
|
47
|
-
'Used to change font-size of the label'
|
|
34
|
+
description: 'Used to change font-size of the label',
|
|
48
35
|
},
|
|
49
36
|
additionalSlot: {
|
|
50
|
-
description:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
37
|
+
description: 'An additional slot allows for more text',
|
|
38
|
+
},
|
|
54
39
|
},
|
|
55
40
|
} as MetaStory;
|
|
56
41
|
|
|
@@ -61,7 +46,7 @@ export const RadioGroup: Story = {
|
|
|
61
46
|
{
|
|
62
47
|
id: 'individual',
|
|
63
48
|
label: `Vendeur à domicile indépendant mandataire (The VDI mandataire
|
|
64
|
-
enters into sales or service agreements
|
|
49
|
+
enters into sales or service agreements
|
|
65
50
|
with customers in the name and on behalf of the company.
|
|
66
51
|
His remuneration will be based on commissions made
|
|
67
52
|
on the sales of products to customers.)`,
|
|
@@ -70,7 +55,7 @@ export const RadioGroup: Story = {
|
|
|
70
55
|
{
|
|
71
56
|
id: ' retailer',
|
|
72
57
|
label: `Vendeur à domicile indépendant acheteur-revendeur
|
|
73
|
-
(The VDI acheteur-revendeur sells the company's products in his own name and behalf.
|
|
58
|
+
(The VDI acheteur-revendeur sells the company's products in his own name and behalf.
|
|
74
59
|
His remuneration will be based on commissions and on the margins made on the sales of
|
|
75
60
|
products to customers.)`,
|
|
76
61
|
value: 'retailer',
|
|
@@ -91,12 +76,9 @@ export const RadioGroup: Story = {
|
|
|
91
76
|
await userEvent.hover(canvas.getByTestId('radio-group'));
|
|
92
77
|
await expect(
|
|
93
78
|
canvas.getByText(
|
|
79
|
+
// eslint-disable-next-line max-len
|
|
94
80
|
'Vendeur à domicile indépendant mandataire (The VDI mandataire enters into sales or service agreements with customers in the name and on behalf of the company. His remuneration will be based on commissions made on the sales of products to customers.)'
|
|
95
81
|
)
|
|
96
82
|
).toBeInTheDocument();
|
|
97
83
|
},
|
|
98
84
|
};
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { Radio, FormControlLabel, FormLabel, RadioGroup } from '@mui/material';
|
|
2
2
|
import { ColorUtils, FoundationTheme, styled } from '@nuskin/foundation-theme';
|
|
3
|
+
import { skipDarkModeEnabled } from '../util';
|
|
3
4
|
|
|
4
5
|
const { paletteColor, isDarkMode, color } = ColorUtils;
|
|
5
6
|
|
|
6
7
|
export const StyledHelperText = styled('div')`
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
justify-self: flex-start;
|
|
8
|
+
margin-top :10px;
|
|
9
|
+
justify-self:flex-start;
|
|
10
|
+
padding-left: 0.5em;
|
|
11
11
|
)`;
|
|
12
12
|
|
|
13
13
|
export const StyledSpan = styled('span')`
|
|
@@ -23,7 +23,7 @@ export const StyledLabel = styled(FormLabel)`
|
|
|
23
23
|
`;
|
|
24
24
|
|
|
25
25
|
export const StyledRadio = styled(Radio)`
|
|
26
|
-
color: ${(props) =>
|
|
26
|
+
color: ${(props) => color('primary', !isDarkMode(props) ? 'black' : 'white')(props)};
|
|
27
27
|
`;
|
|
28
28
|
|
|
29
29
|
export const StyledFormControlLabel = styled(FormControlLabel)<{ darkModeEnabled?: boolean }>((props) => {
|
|
@@ -31,20 +31,21 @@ export const StyledFormControlLabel = styled(FormControlLabel)<{ darkModeEnabled
|
|
|
31
31
|
color: paletteColor('primary')(props),
|
|
32
32
|
marginBottom: '10px',
|
|
33
33
|
'.MuiFormControlLabel-label.Mui-disabled': {
|
|
34
|
-
color: `${
|
|
34
|
+
color: `${color('neutral', !isDarkMode(props) ? 60 : 20)(props)}`,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
const options = {
|
|
39
|
+
shouldForwardProp: skipDarkModeEnabled,
|
|
40
|
+
};
|
|
41
|
+
export const StyledRadioGroup = styled(
|
|
42
|
+
RadioGroup,
|
|
43
|
+
options
|
|
44
|
+
)<{ color: FoundationTheme.PaletteColors; darkModeEnabled?: boolean }>(({ theme, color, darkModeEnabled }) => {
|
|
45
|
+
return {
|
|
46
|
+
marginTop: '10px',
|
|
47
|
+
'.MuiRadio-root.custom-radio.Mui-checked': {
|
|
48
|
+
color: paletteColor(color)({ theme, darkModeEnabled }),
|
|
35
49
|
},
|
|
36
50
|
};
|
|
37
51
|
});
|
|
38
|
-
|
|
39
|
-
export const StyledRadioGroup = styled(RadioGroup)<
|
|
40
|
-
{ color: FoundationTheme.PaletteColors; darkModeEnabled?: boolean }
|
|
41
|
-
>(
|
|
42
|
-
({ theme, color, darkModeEnabled }) => {
|
|
43
|
-
return {
|
|
44
|
-
marginTop: '10px',
|
|
45
|
-
'.MuiRadio-root.custom-radio.Mui-checked': {
|
|
46
|
-
color: paletteColor(color)({ theme, darkModeEnabled })
|
|
47
|
-
},
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
);
|
|
@@ -22,7 +22,7 @@ const NsRadioGroup = (props: NsRadioGroupProps) => {
|
|
|
22
22
|
size,
|
|
23
23
|
additionalProps,
|
|
24
24
|
labelFontSize,
|
|
25
|
-
darkModeEnabled = true
|
|
25
|
+
darkModeEnabled = true,
|
|
26
26
|
} = props;
|
|
27
27
|
|
|
28
28
|
return (
|
|
@@ -50,10 +50,11 @@ const NsRadioGroup = (props: NsRadioGroupProps) => {
|
|
|
50
50
|
))}
|
|
51
51
|
</StyledRadioGroup>
|
|
52
52
|
</FormControl>
|
|
53
|
-
{additionalSlot ?
|
|
54
|
-
<
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
{additionalSlot ? (
|
|
54
|
+
<StyledHelperText className={`ml-${size}`}>
|
|
55
|
+
<StyledSpan className="text-sm">{additionalSlot}</StyledSpan>
|
|
56
|
+
</StyledHelperText>
|
|
57
|
+
) : null}
|
|
57
58
|
</>
|
|
58
59
|
);
|
|
59
60
|
};
|
|
@@ -2,8 +2,6 @@ import React from 'react';
|
|
|
2
2
|
import InputBase from '@mui/material/InputBase';
|
|
3
3
|
import { styled } from '@nuskin/foundation-theme';
|
|
4
4
|
|
|
5
|
-
interface NsSearchBarProps {}
|
|
6
|
-
|
|
7
5
|
const Search = styled('div')`
|
|
8
6
|
position: relative;
|
|
9
7
|
borderRadius: 0;
|
|
@@ -31,7 +29,7 @@ const StyledInputBase = styled(InputBase)(() => ({
|
|
|
31
29
|
},
|
|
32
30
|
}));
|
|
33
31
|
|
|
34
|
-
const NsSearchBar: React.FC
|
|
32
|
+
const NsSearchBar: React.FC = () => {
|
|
35
33
|
return (
|
|
36
34
|
<div>
|
|
37
35
|
<Search>
|