@nuskin/foundation-ui-components 1.0.2 → 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 +105 -101
- 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 +32 -14
- package/src/common/accordion/stories/NsAccordionHeader.stories.tsx +6 -2
- package/src/common/accordion/stories/NsAccordionItem.stories.tsx +9 -4
- package/src/common/accordion/stories/NsCollapse.stories.tsx +20 -5
- package/src/common/accordion/stories/NsToggleSection.stories.tsx +7 -4
- 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 +3 -3
- 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.stories.tsx +1 -1
- package/src/common/auth-dropdown/NsAuthDropdown.styled.ts +11 -7
- 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 +19 -3
- 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/banner/NsBanner.stories.tsx +1 -1
- package/src/common/brand-components/NsBrand.stories.tsx +1 -1
- package/src/common/brand-components/NsBrandComponent.tsx +2 -2
- package/src/common/breadcrumb/NsBreadcrumb.spec.tsx +8 -3
- package/src/common/breadcrumb/NsBreadcrumb.stories.tsx +1 -1
- package/src/common/breadcrumb/data.ts +8 -5
- package/src/common/button/NsButton.spec.tsx +65 -49
- package/src/common/button/NsButton.stories.tsx +59 -2
- 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/button/types.d.ts +2 -0
- package/src/common/card/NsFfgCard.tsx +13 -7
- package/src/common/card/specs/NsFfgCard.spec.tsx +18 -8
- package/src/common/card/stories/NsBgCard.stories.tsx +1 -1
- package/src/common/card/stories/NsBrandProductCard.stories.tsx +1 -1
- package/src/common/card/stories/NsFfgCard.stories.tsx +48 -15
- 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/carousal/stories/NSCarousal.stories.tsx +1 -1
- package/src/common/carousal/stories/NsScrollingCarousal.stories.tsx +1 -1
- package/src/common/cart-icon/NsCartIcon.spec.tsx +5 -16
- package/src/common/cart-icon/NsCartIcon.stories.tsx +2 -2
- 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.stories.tsx +1 -1
- package/src/common/checkbox/NsCheckbox.styled.tsx +15 -16
- package/src/common/checkbox/NsCheckbox.tsx +1 -1
- package/src/common/column-control/stories/DivArray.stories.tsx +1 -1
- package/src/common/column-control/stories/NsColumnControl.stories.tsx +1 -1
- package/src/common/column-control/stories/NsFlexColumns.stories.tsx +1 -1
- package/src/common/column-control/stories/NsGridColumns.stories.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/dropdown/stories/NsDropdown.stories.tsx +1 -1
- package/src/common/dropdown/stories/NsDropdownCountry.stories.tsx +1 -1
- package/src/common/flag/NsFlag.stories.tsx +1 -1
- 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 +4 -1
- 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.stories.tsx +1 -1
- package/src/common/image/NsImage.tsx +23 -11
- package/src/common/image/NsNextImage.stories.tsx +1 -1
- 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/label/NsLabel.stories.tsx +1 -1
- package/src/common/link/NsLink.stories.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-product-card/NsNavProductCard.stories.tsx +1 -1
- 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 +4 -4
- 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 +14 -32
- 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 +11 -11
- 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.stories.tsx +1 -1
- package/src/common/table/NsTable.tsx +32 -49
- package/src/common/table/NsTableHeader.tsx +30 -51
- package/src/common/text-strip/NsTextStrip.stories.tsx +1 -1
- package/src/common/typography/NsTypography.stories.tsx +1 -1
- 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/NsVideo.stories.tsx +1 -1
- package/src/common/videos/types.d.ts +1 -1
- /package/src/common/brand-components/{NsBrandContanier.styled.tsx → NsBrandContainer.styled.tsx} +0 -0
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
import { styled } from '@nuskin/foundation-theme';
|
|
2
|
-
import { AccordionVariant } from '
|
|
2
|
+
import { AccordionVariant, AccordionVariantType } from '../';
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
const border = '1px solid rgb(0,0,0,0.125)';
|
|
5
|
+
|
|
6
|
+
type StyledType = { variant: AccordionVariantType };
|
|
7
|
+
|
|
8
|
+
export const StyledToggleSection = styled('section')<StyledType>(({ variant }) => {
|
|
5
9
|
if (variant === AccordionVariant.Compact) {
|
|
6
|
-
return { borderRight:
|
|
10
|
+
return { borderRight: border };
|
|
7
11
|
}
|
|
8
12
|
return {
|
|
9
|
-
margin: '5px',
|
|
13
|
+
margin: '5px 0',
|
|
10
14
|
};
|
|
11
15
|
});
|
|
12
16
|
|
|
13
|
-
export const StyledAccordionWrapper = styled('div')<
|
|
17
|
+
export const StyledAccordionWrapper = styled('div')<StyledType>(({ variant }) => {
|
|
14
18
|
if (variant === AccordionVariant.Compact) {
|
|
15
19
|
return {
|
|
16
20
|
display: 'flex',
|
|
17
21
|
flexDirection: 'column',
|
|
18
22
|
gap: '0',
|
|
19
|
-
borderTop:
|
|
20
|
-
borderLeft:
|
|
23
|
+
borderTop: border,
|
|
24
|
+
borderLeft: border,
|
|
21
25
|
};
|
|
22
26
|
}
|
|
23
27
|
return {
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import {Themed} from '../common.types';
|
|
2
|
+
import {AccordionVariantType} from './enums';
|
|
3
|
+
import {ColorUtils, FoundationTheme} from '@nuskin/foundation-theme';
|
|
4
|
+
const {isDarkMode, color} = ColorUtils;
|
|
5
|
+
const compKeys = ['contentBg', 'contentText', 'headBg', 'headText'];
|
|
6
|
+
type CompKeys = (typeof compKeys)[number];
|
|
7
|
+
type VariantColors = Record<
|
|
8
|
+
CompKeys,
|
|
9
|
+
{
|
|
10
|
+
light: [FoundationTheme.AppColors, string];
|
|
11
|
+
dark: [FoundationTheme.AppColors, string];
|
|
12
|
+
}
|
|
13
|
+
>;
|
|
14
|
+
|
|
15
|
+
const colorObject: Record<string, [FoundationTheme.AppColors, string]> = {
|
|
16
|
+
n10: ['primary', 'dark'], // #121212
|
|
17
|
+
n20: ['primary', 'black'], // #252525
|
|
18
|
+
n40: ['neutral', '80'], // #444444
|
|
19
|
+
n45: ['neutral', '70'], // #5f5f5f
|
|
20
|
+
n50: ['neutral', '60'], // #8c8c8c
|
|
21
|
+
n80: ['neutral', '50'], // #b2b2b2
|
|
22
|
+
n85: ['neutral', '40'], // #e0e0e0
|
|
23
|
+
n90: ['neutral', '30'], // #ededed
|
|
24
|
+
n95: ['primary', 'gray'], // #f5f5f5
|
|
25
|
+
n100: ['primary', 'white'], // #fff
|
|
26
|
+
};
|
|
27
|
+
export const colorMap: Record<AccordionVariantType, VariantColors> = {
|
|
28
|
+
basic: {
|
|
29
|
+
contentBg: {
|
|
30
|
+
light: colorObject.n95,
|
|
31
|
+
dark: colorObject.n20,
|
|
32
|
+
},
|
|
33
|
+
contentText: {
|
|
34
|
+
light: colorObject.n10,
|
|
35
|
+
dark: colorObject.n95,
|
|
36
|
+
},
|
|
37
|
+
headBg: {
|
|
38
|
+
light: colorObject.n100,
|
|
39
|
+
dark: colorObject.n20,
|
|
40
|
+
},
|
|
41
|
+
headText: {
|
|
42
|
+
light: colorObject.n10,
|
|
43
|
+
dark: colorObject.n95,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
compact: {
|
|
47
|
+
contentBg: {
|
|
48
|
+
light: colorObject.n100,
|
|
49
|
+
dark: colorObject.n10,
|
|
50
|
+
},
|
|
51
|
+
contentText: {
|
|
52
|
+
light: colorObject.n10,
|
|
53
|
+
dark: colorObject.n90,
|
|
54
|
+
},
|
|
55
|
+
headBg: {
|
|
56
|
+
light: colorObject.n100,
|
|
57
|
+
dark: colorObject.n10,
|
|
58
|
+
},
|
|
59
|
+
headText: {
|
|
60
|
+
light: colorObject.n10,
|
|
61
|
+
dark: colorObject.n90,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
gray: {
|
|
65
|
+
contentBg: {
|
|
66
|
+
light: colorObject.n85,
|
|
67
|
+
dark: colorObject.n40,
|
|
68
|
+
},
|
|
69
|
+
contentText: {
|
|
70
|
+
light: colorObject.n40,
|
|
71
|
+
dark: colorObject.n85,
|
|
72
|
+
},
|
|
73
|
+
headBg: {
|
|
74
|
+
light: colorObject.n90,
|
|
75
|
+
dark: colorObject.n45,
|
|
76
|
+
},
|
|
77
|
+
headText: {
|
|
78
|
+
light: colorObject.n45,
|
|
79
|
+
dark: colorObject.n90,
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
stripe: {
|
|
83
|
+
contentBg: {
|
|
84
|
+
light: colorObject.n90,
|
|
85
|
+
dark: colorObject.n45,
|
|
86
|
+
},
|
|
87
|
+
contentText: {
|
|
88
|
+
light: colorObject.n45,
|
|
89
|
+
dark: colorObject.n90,
|
|
90
|
+
},
|
|
91
|
+
headBg: {
|
|
92
|
+
light: colorObject.n100,
|
|
93
|
+
dark: colorObject.n40,
|
|
94
|
+
},
|
|
95
|
+
headText: {
|
|
96
|
+
light: colorObject.n40,
|
|
97
|
+
dark: colorObject.n100,
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
type GetAccordionColor = {
|
|
103
|
+
variant: AccordionVariantType;
|
|
104
|
+
invert: boolean;
|
|
105
|
+
keys: CompKeys[];
|
|
106
|
+
} & Themed;
|
|
107
|
+
export const getAccordionColor = ({theme, variant, invert, keys}: GetAccordionColor): Record<CompKeys, string> => {
|
|
108
|
+
const isDark = invert ? !isDarkMode({theme}) : isDarkMode({theme});
|
|
109
|
+
const darkLabel = isDark ? 'dark' : 'light';
|
|
110
|
+
const result: Record<string, string> = {};
|
|
111
|
+
for (const colorKey of keys) {
|
|
112
|
+
const [appColorBg, appSubColorBg] = colorMap[variant][colorKey][darkLabel];
|
|
113
|
+
const colorValue = color(appColorBg, appSubColorBg)({theme});
|
|
114
|
+
result[colorKey] = colorValue;
|
|
115
|
+
}
|
|
116
|
+
return result;
|
|
117
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const AccordionVariant = {
|
|
2
|
+
Basic: 'basic',
|
|
3
|
+
Compact: 'compact',
|
|
4
|
+
Gray: 'gray',
|
|
5
|
+
Stripe: 'stripe',
|
|
6
|
+
} as const;
|
|
7
|
+
const variantValues = Object.values(AccordionVariant);
|
|
8
|
+
export type AccordionVariantType = (typeof variantValues)[number];
|
|
9
|
+
|
|
10
|
+
export const AccordionContentTypeObject = {
|
|
11
|
+
text: 'text',
|
|
12
|
+
html: 'html',
|
|
13
|
+
accordion: 'accordion',
|
|
14
|
+
jsx: 'jsx',
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const contentValues = Object.values(AccordionContentTypeObject);
|
|
18
|
+
export type AccordionContentType = (typeof contentValues)[number];
|
|
@@ -1,50 +1,56 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { render, fireEvent, screen } from '@/test-utils/index';
|
|
3
|
-
import { AccordionVariant, NsAccordion
|
|
3
|
+
import { AccordionContentTypeObject, AccordionItem, AccordionVariant, NsAccordion } from '@/common/index';
|
|
4
4
|
|
|
5
|
-
const generateContentArray = (count: number) => {
|
|
6
|
-
const arr = [] as
|
|
5
|
+
const generateContentArray = (count: number, isDefaultOpen = true) => {
|
|
6
|
+
const arr = [] as AccordionItem[];
|
|
7
7
|
for (let i = 1; i <= count; i++) {
|
|
8
|
-
arr
|
|
8
|
+
arr?.push({
|
|
9
9
|
title: `Title ${i}`,
|
|
10
|
-
|
|
11
|
-
isDefaultOpen
|
|
10
|
+
content: <div className="p-2">Content {i}</div>,
|
|
11
|
+
isDefaultOpen,
|
|
12
|
+
type: AccordionContentTypeObject.jsx,
|
|
13
|
+
id: `Test ${i}`,
|
|
12
14
|
});
|
|
13
15
|
}
|
|
14
16
|
return arr;
|
|
15
17
|
};
|
|
16
18
|
|
|
17
19
|
describe('NsAccordion', () => {
|
|
18
|
-
const
|
|
20
|
+
const items = generateContentArray(3);
|
|
19
21
|
const defaultProps = {
|
|
20
22
|
additionalProps: {
|
|
21
23
|
testid: 'test-accordion',
|
|
22
24
|
},
|
|
23
25
|
allowMultipleExpanded: false,
|
|
24
|
-
|
|
26
|
+
items,
|
|
25
27
|
variant: AccordionVariant.Basic,
|
|
28
|
+
invert: false,
|
|
29
|
+
level: 0,
|
|
26
30
|
};
|
|
27
31
|
|
|
28
|
-
it('renders without error', () => {
|
|
32
|
+
it('1. renders without error', () => {
|
|
29
33
|
const { getByTestId } = render(<NsAccordion {...defaultProps} />);
|
|
30
34
|
const accordion = getByTestId(defaultProps.additionalProps.testid);
|
|
31
35
|
expect(accordion).toBeInTheDocument();
|
|
32
36
|
});
|
|
33
37
|
|
|
34
|
-
it(`only first section should be visible when allowMultipleExpanded prop is false and multiple items have
|
|
35
|
-
|
|
38
|
+
it(`2. only first section should be visible when allowMultipleExpanded prop is false and multiple items have
|
|
39
|
+
isDefaultOpen true`, () => {
|
|
36
40
|
const { getAllByText } = render(<NsAccordion {...defaultProps} />);
|
|
37
41
|
const [title1, title2, title3] = getAllByText(/Title /i);
|
|
38
42
|
|
|
39
43
|
expect(title1.closest('header')).toHaveAttribute('aria-expanded', 'true');
|
|
40
44
|
expect(title2.closest('header')).toHaveAttribute('aria-expanded', 'false');
|
|
41
45
|
expect(title3.closest('header')).toHaveAttribute('aria-expanded', 'false');
|
|
42
|
-
|
|
43
|
-
expect(
|
|
44
|
-
expect(
|
|
46
|
+
const [c1, c2, c3] = getAllByText(/Content /i);
|
|
47
|
+
expect(c1.parentNode).toHaveStyle('opacity: 1');
|
|
48
|
+
expect(c2.parentNode).toHaveStyle('opacity: 0');
|
|
49
|
+
expect(c3.parentNode).toHaveStyle('opacity: 0');
|
|
45
50
|
});
|
|
46
51
|
|
|
47
|
-
it(
|
|
52
|
+
it(`3. expands second section only when allowMultipleExpanded
|
|
53
|
+
prop is false and second title is clicked`, async () => {
|
|
48
54
|
const { getAllByText } = render(<NsAccordion {...defaultProps} />);
|
|
49
55
|
const [title1, title2, title3] = getAllByText(/Title /i);
|
|
50
56
|
const header = title2.closest('header');
|
|
@@ -54,40 +60,104 @@ describe('NsAccordion', () => {
|
|
|
54
60
|
expect(title1.closest('header')).toHaveAttribute('aria-expanded', 'false');
|
|
55
61
|
expect(title2.closest('header')).toHaveAttribute('aria-expanded', 'true');
|
|
56
62
|
expect(title3.closest('header')).toHaveAttribute('aria-expanded', 'false');
|
|
57
|
-
|
|
58
|
-
expect(
|
|
59
|
-
expect(
|
|
63
|
+
const [c1, c2, c3] = getAllByText(/Content /i);
|
|
64
|
+
expect(c1.parentNode).toHaveStyle('opacity: 0');
|
|
65
|
+
expect(c2.parentNode).toHaveStyle('opacity: 1');
|
|
66
|
+
expect(c3.parentNode).toHaveStyle('opacity: 0');
|
|
60
67
|
}
|
|
61
68
|
});
|
|
62
69
|
|
|
63
|
-
it('expands multiple sections by default when allowMultipleExpanded prop is true', () => {
|
|
64
|
-
const
|
|
65
|
-
|
|
70
|
+
it('4. expands multiple sections by default when allowMultipleExpanded prop is true', () => {
|
|
71
|
+
const items = generateContentArray(3);
|
|
72
|
+
items[2].isDefaultOpen = false;
|
|
66
73
|
const defaultProps = {
|
|
67
|
-
additionalProps: {
|
|
68
|
-
testid: 'test-accordion',
|
|
69
|
-
},
|
|
70
74
|
allowMultipleExpanded: false,
|
|
71
|
-
|
|
75
|
+
items,
|
|
72
76
|
variant: AccordionVariant.Basic,
|
|
77
|
+
level: 0,
|
|
78
|
+
invert: false,
|
|
73
79
|
};
|
|
74
80
|
const { getAllByText } = render(<NsAccordion {...defaultProps} allowMultipleExpanded />);
|
|
81
|
+
const accordion = screen.getByTestId('ns-accordion-testid');
|
|
82
|
+
expect(accordion).toBeDefined();
|
|
75
83
|
const [title1, title2, title3] = getAllByText(/Title /i);
|
|
76
84
|
|
|
77
85
|
expect(title1.closest('header')).toHaveAttribute('aria-expanded', 'true');
|
|
78
86
|
expect(title2.closest('header')).toHaveAttribute('aria-expanded', 'true');
|
|
79
87
|
expect(title3.closest('header')).toHaveAttribute('aria-expanded', 'false');
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
expect(
|
|
88
|
+
|
|
89
|
+
const [c1, c2, c3] = getAllByText(/Content /i);
|
|
90
|
+
expect(c1.parentNode).toHaveStyle('opacity: 1');
|
|
91
|
+
expect(c2.parentNode).toHaveStyle('opacity: 1');
|
|
92
|
+
expect(c3.parentNode).toHaveStyle('opacity: 0');
|
|
83
93
|
|
|
84
94
|
fireEvent.click(title3);
|
|
85
95
|
|
|
86
96
|
expect(title1.closest('header')).toHaveAttribute('aria-expanded', 'true');
|
|
87
97
|
expect(title2.closest('header')).toHaveAttribute('aria-expanded', 'true');
|
|
88
98
|
expect(title3.closest('header')).toHaveAttribute('aria-expanded', 'true');
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
expect(
|
|
99
|
+
|
|
100
|
+
const [c11, c12, c13] = getAllByText(/Content /i);
|
|
101
|
+
expect(c11.parentNode).toHaveStyle('opacity: 1');
|
|
102
|
+
expect(c12.parentNode).toHaveStyle('opacity: 1');
|
|
103
|
+
expect(c13.parentNode).toHaveStyle('opacity: 1');
|
|
104
|
+
});
|
|
105
|
+
it(`5. closes second section also when allowMultipleExpanded
|
|
106
|
+
prop is true and second title is clicked`, async () => {
|
|
107
|
+
const items = generateContentArray(3);
|
|
108
|
+
const defaultProps = {
|
|
109
|
+
additionalProps: {
|
|
110
|
+
testid: 'test-accordion',
|
|
111
|
+
},
|
|
112
|
+
allowMultipleExpanded: true,
|
|
113
|
+
items,
|
|
114
|
+
variant: AccordionVariant.Basic,
|
|
115
|
+
invert: false,
|
|
116
|
+
level: 0,
|
|
117
|
+
};
|
|
118
|
+
const { getAllByText } = render(<NsAccordion {...defaultProps} />);
|
|
119
|
+
const [title1, title2, title3] = getAllByText(/Title /i);
|
|
120
|
+
const header = title2.closest('header');
|
|
121
|
+
expect(header).toHaveAttribute('aria-expanded', 'true');
|
|
122
|
+
if (header) {
|
|
123
|
+
fireEvent.click(header);
|
|
124
|
+
expect(title1.closest('header')).toHaveAttribute('aria-expanded', 'true');
|
|
125
|
+
expect(title2.closest('header')).toHaveAttribute('aria-expanded', 'false');
|
|
126
|
+
expect(title3.closest('header')).toHaveAttribute('aria-expanded', 'true');
|
|
127
|
+
|
|
128
|
+
const [c1, c2, c3] = getAllByText(/Content /i);
|
|
129
|
+
expect(c1.parentNode).toHaveStyle('opacity: 1');
|
|
130
|
+
expect(c2.parentNode).toHaveStyle('opacity: 0');
|
|
131
|
+
expect(c3.parentNode).toHaveStyle('opacity: 1');
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
it(`6. closes second section also when allowMultipleExpanded
|
|
135
|
+
prop is true and second title is clicked`, async () => {
|
|
136
|
+
const items = generateContentArray(3, false);
|
|
137
|
+
items[1].isDefaultOpen = true;
|
|
138
|
+
const defaultProps = {
|
|
139
|
+
additionalProps: {
|
|
140
|
+
testid: 'test-accordion',
|
|
141
|
+
},
|
|
142
|
+
allowMultipleExpanded: false,
|
|
143
|
+
items,
|
|
144
|
+
variant: AccordionVariant.Compact,
|
|
145
|
+
level: 0,
|
|
146
|
+
invert: false,
|
|
147
|
+
};
|
|
148
|
+
const { getAllByText } = render(<NsAccordion {...defaultProps} />);
|
|
149
|
+
const [title1, title2, title3] = getAllByText(/Title /i);
|
|
150
|
+
const header = title2.closest('header');
|
|
151
|
+
expect(header).toHaveAttribute('aria-expanded', 'true');
|
|
152
|
+
if (header) {
|
|
153
|
+
fireEvent.click(header);
|
|
154
|
+
expect(title1.closest('header')).toHaveAttribute('aria-expanded', 'false');
|
|
155
|
+
expect(title2.closest('header')).toHaveAttribute('aria-expanded', 'false');
|
|
156
|
+
expect(title3.closest('header')).toHaveAttribute('aria-expanded', 'false');
|
|
157
|
+
const [c1, c2, c3] = getAllByText(/Content /i);
|
|
158
|
+
expect(c1.parentNode).toHaveStyle('opacity: 0');
|
|
159
|
+
expect(c2.parentNode).toHaveStyle('opacity: 0');
|
|
160
|
+
expect(c3.parentNode).toHaveStyle('opacity: 0');
|
|
161
|
+
}
|
|
92
162
|
});
|
|
93
163
|
});
|
|
@@ -3,7 +3,7 @@ import { render, fireEvent } from '@/test-utils/index';
|
|
|
3
3
|
import { NsAccordionHeader, AccordionVariant } from '@/common/index';
|
|
4
4
|
|
|
5
5
|
describe('NsAccordionHeader', () => {
|
|
6
|
-
it('renders title correctly', () => {
|
|
6
|
+
it('1. renders title correctly', () => {
|
|
7
7
|
const onClick = jest.fn();
|
|
8
8
|
const title = 'Section Header';
|
|
9
9
|
const { getByText } = render(
|
|
@@ -11,19 +11,41 @@ describe('NsAccordionHeader', () => {
|
|
|
11
11
|
variant={AccordionVariant.Basic}
|
|
12
12
|
title={title}
|
|
13
13
|
onClick={onClick}
|
|
14
|
+
invert={false}
|
|
15
|
+
isOpen={true}
|
|
14
16
|
/>
|
|
15
17
|
);
|
|
16
|
-
|
|
18
|
+
const el = getByText(title);
|
|
19
|
+
expect(el).toBeInTheDocument();
|
|
20
|
+
expect(el.closest('header')).toHaveAttribute('aria-expanded', 'true');
|
|
17
21
|
});
|
|
18
|
-
|
|
19
|
-
|
|
22
|
+
it('2. renders title correctly', () => {
|
|
23
|
+
const onClick = jest.fn();
|
|
24
|
+
const title = 'Section Header';
|
|
25
|
+
const { getByText } = render(
|
|
26
|
+
<NsAccordionHeader
|
|
27
|
+
variant={AccordionVariant.Compact}
|
|
28
|
+
title={<span>{title}</span>}
|
|
29
|
+
onClick={onClick}
|
|
30
|
+
invert={false}
|
|
31
|
+
isOpen={false}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
const el = getByText(title);
|
|
35
|
+
expect(el).toBeInTheDocument();
|
|
36
|
+
expect(el.closest('header')).toHaveAttribute('aria-expanded', 'false');
|
|
37
|
+
});
|
|
38
|
+
it('3. calls onClick handler when clicked', () => {
|
|
20
39
|
const onClick = jest.fn();
|
|
21
40
|
const { container } = render(
|
|
22
41
|
<NsAccordionHeader
|
|
23
42
|
variant={AccordionVariant.Basic}
|
|
24
43
|
title="Section Header"
|
|
25
44
|
onClick={onClick}
|
|
26
|
-
|
|
45
|
+
invert={false}
|
|
46
|
+
isOpen={false}
|
|
47
|
+
/>
|
|
48
|
+
);
|
|
27
49
|
const header = container.querySelector('header');
|
|
28
50
|
if (header) {
|
|
29
51
|
fireEvent.click(header);
|
|
@@ -31,33 +53,78 @@ describe('NsAccordionHeader', () => {
|
|
|
31
53
|
}
|
|
32
54
|
});
|
|
33
55
|
|
|
34
|
-
it('renders with additional class name', () => {
|
|
56
|
+
it('4. renders with additional class name', () => {
|
|
35
57
|
const additionalClassName = 'custom-class';
|
|
36
58
|
const onClick = jest.fn();
|
|
37
59
|
const { container } = render(
|
|
38
60
|
<NsAccordionHeader
|
|
61
|
+
isOpen={false}
|
|
39
62
|
variant={AccordionVariant.Basic}
|
|
40
63
|
title="Section Header"
|
|
41
64
|
additionalProps={{ className: additionalClassName }}
|
|
42
65
|
onClick={onClick}
|
|
66
|
+
invert={false}
|
|
43
67
|
/>
|
|
44
68
|
);
|
|
45
69
|
expect(container.querySelector('header')).toHaveClass(`section-header ${additionalClassName}`);
|
|
46
70
|
});
|
|
47
71
|
|
|
48
|
-
it('renders with expanded class when isOpen is true', () => {
|
|
72
|
+
it('5. renders with expanded class when isOpen is true', () => {
|
|
49
73
|
const onClick = jest.fn();
|
|
50
74
|
const { container } = render(
|
|
51
|
-
<NsAccordionHeader
|
|
75
|
+
<NsAccordionHeader
|
|
76
|
+
variant={AccordionVariant.Basic}
|
|
77
|
+
title="Section Header"
|
|
78
|
+
isOpen
|
|
79
|
+
onClick={onClick}
|
|
80
|
+
invert={false}
|
|
81
|
+
/>
|
|
52
82
|
);
|
|
53
83
|
expect(container.querySelector('header')).toHaveClass('expanded');
|
|
54
84
|
});
|
|
55
85
|
|
|
56
|
-
it('renders with header icon', () => {
|
|
86
|
+
it('6. renders with header icon', () => {
|
|
57
87
|
const onClick = jest.fn();
|
|
58
88
|
const { getByTestId } = render(
|
|
59
|
-
<NsAccordionHeader
|
|
89
|
+
<NsAccordionHeader
|
|
90
|
+
variant={AccordionVariant.Basic}
|
|
91
|
+
title="Section Header"
|
|
92
|
+
onClick={onClick}
|
|
93
|
+
invert={false}
|
|
94
|
+
isOpen
|
|
95
|
+
/>
|
|
60
96
|
);
|
|
97
|
+
// this icon refers to end icon which is either arrowUp or arrowDown
|
|
61
98
|
expect(getByTestId('icon')).toBeInTheDocument();
|
|
62
99
|
});
|
|
100
|
+
it('7. renders with custom start icon', () => {
|
|
101
|
+
const onClick = jest.fn();
|
|
102
|
+
const { getByTestId } = render(
|
|
103
|
+
<NsAccordionHeader
|
|
104
|
+
variant={AccordionVariant.Basic}
|
|
105
|
+
title="Section Header"
|
|
106
|
+
onClick={onClick}
|
|
107
|
+
invert={false}
|
|
108
|
+
isOpen
|
|
109
|
+
startIcon={{ name: 'hamburgerIcon', testId: 'hamburger-test' }}
|
|
110
|
+
/>
|
|
111
|
+
);
|
|
112
|
+
expect(getByTestId('hamburger-test')).toBeInTheDocument();
|
|
113
|
+
});
|
|
114
|
+
it('8. does not render start icon, when invalid icon name is passed', () => {
|
|
115
|
+
const onClick = jest.fn();
|
|
116
|
+
const invalidIconName = 'hambur';
|
|
117
|
+
const testId = 'hamburger-test';
|
|
118
|
+
const { queryByTestId } = render(
|
|
119
|
+
<NsAccordionHeader
|
|
120
|
+
variant={AccordionVariant.Basic}
|
|
121
|
+
title="Section Header"
|
|
122
|
+
onClick={onClick}
|
|
123
|
+
invert={false}
|
|
124
|
+
isOpen
|
|
125
|
+
startIcon={{ name: invalidIconName as any, testId }}
|
|
126
|
+
/>
|
|
127
|
+
);
|
|
128
|
+
expect(queryByTestId(testId)).toBeNull();
|
|
129
|
+
});
|
|
63
130
|
});
|
|
@@ -5,58 +5,75 @@ import { NsAccordionItem, AccordionVariant } from '@/common/index';
|
|
|
5
5
|
describe('NsAccordionItem', () => {
|
|
6
6
|
const title = 'Accordion Section Title';
|
|
7
7
|
const content = 'Accordion Section Content';
|
|
8
|
-
|
|
9
|
-
it('renders title correctly', () => {
|
|
8
|
+
const contentElement = <div className="p-2">{content}</div>;
|
|
9
|
+
it('1. renders title correctly', () => {
|
|
10
10
|
const { getByText } = render(
|
|
11
11
|
<NsAccordionItem
|
|
12
|
+
type="jsx"
|
|
12
13
|
variant={AccordionVariant.Basic}
|
|
13
14
|
isOpen={false}
|
|
14
15
|
toggleOpen={() => {}}
|
|
15
16
|
title={title}
|
|
16
|
-
content={
|
|
17
|
+
content={contentElement}
|
|
18
|
+
isChild={false}
|
|
19
|
+
invert={false}
|
|
20
|
+
level={1}
|
|
17
21
|
/>
|
|
18
22
|
);
|
|
19
23
|
expect(getByText(title)).toBeInTheDocument();
|
|
20
24
|
});
|
|
21
25
|
|
|
22
|
-
it('calls toggleOpen function when clicked on the section header', () => {
|
|
26
|
+
it('2. calls toggleOpen function when clicked on the section header', () => {
|
|
23
27
|
const toggleOpen = jest.fn();
|
|
24
28
|
const { getByText } = render(
|
|
25
29
|
<NsAccordionItem
|
|
30
|
+
type="jsx"
|
|
26
31
|
variant={AccordionVariant.Basic}
|
|
27
32
|
isOpen={false}
|
|
28
33
|
toggleOpen={toggleOpen}
|
|
29
34
|
title={title}
|
|
30
|
-
content={
|
|
35
|
+
content={contentElement}
|
|
36
|
+
isChild={false}
|
|
37
|
+
invert={false}
|
|
38
|
+
level={1}
|
|
31
39
|
/>
|
|
32
40
|
);
|
|
33
41
|
fireEvent.click(getByText(title));
|
|
34
42
|
expect(toggleOpen).toHaveBeenCalledTimes(1);
|
|
35
43
|
});
|
|
36
44
|
|
|
37
|
-
it('renders content when isOpen is true', () => {
|
|
45
|
+
it('3. renders content when isOpen is true', () => {
|
|
38
46
|
const { getByText } = render(
|
|
39
47
|
<NsAccordionItem
|
|
40
48
|
variant={AccordionVariant.Basic}
|
|
41
49
|
isOpen={true}
|
|
42
50
|
toggleOpen={() => {}}
|
|
43
51
|
title={title}
|
|
44
|
-
|
|
52
|
+
type="jsx"
|
|
53
|
+
content={contentElement}
|
|
54
|
+
isChild={false}
|
|
55
|
+
invert={false}
|
|
56
|
+
level={1}
|
|
45
57
|
/>
|
|
46
58
|
);
|
|
47
59
|
expect(getByText(content)).toBeInTheDocument();
|
|
48
60
|
});
|
|
49
61
|
|
|
50
|
-
it('
|
|
62
|
+
it('4. when isOpen is false, renders jsx dom content within container with 0 height', () => {
|
|
51
63
|
const { queryByText } = render(
|
|
52
64
|
<NsAccordionItem
|
|
65
|
+
type="jsx"
|
|
53
66
|
variant={AccordionVariant.Basic}
|
|
54
67
|
isOpen={false}
|
|
55
68
|
toggleOpen={() => {}}
|
|
56
69
|
title={title}
|
|
57
|
-
content={
|
|
70
|
+
content={contentElement}
|
|
71
|
+
isChild={false}
|
|
72
|
+
invert={false}
|
|
73
|
+
level={1}
|
|
58
74
|
/>
|
|
59
75
|
);
|
|
60
|
-
|
|
76
|
+
const bodyElement = queryByText(content);
|
|
77
|
+
expect(bodyElement?.parentNode).toHaveStyle('height:0px;');
|
|
61
78
|
});
|
|
62
79
|
});
|