@transferwise/components 46.98.1 → 46.100.0
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/build/accordion/Accordion.js +4 -0
- package/build/accordion/Accordion.js.map +1 -1
- package/build/accordion/Accordion.mjs +4 -0
- package/build/accordion/Accordion.mjs.map +1 -1
- package/build/accordion/AccordionItem/AccordionItem.js +14 -5
- package/build/accordion/AccordionItem/AccordionItem.js.map +1 -1
- package/build/accordion/AccordionItem/AccordionItem.mjs +14 -5
- package/build/accordion/AccordionItem/AccordionItem.mjs.map +1 -1
- package/build/body/Body.js +2 -1
- package/build/body/Body.js.map +1 -1
- package/build/body/Body.mjs +2 -1
- package/build/body/Body.mjs.map +1 -1
- package/build/instructionsList/InstructionsList.js +1 -0
- package/build/instructionsList/InstructionsList.js.map +1 -1
- package/build/instructionsList/InstructionsList.mjs +1 -0
- package/build/instructionsList/InstructionsList.mjs.map +1 -1
- package/build/main.css +19 -16
- package/build/styles/accordion/Accordion.css +4 -1
- package/build/styles/body/Body.css +3 -0
- package/build/styles/main.css +19 -16
- package/build/styles/switch/Switch.css +22 -41
- package/build/styles/switchOption/SwitchOption.css +4 -0
- package/build/switch/Switch.js +7 -18
- package/build/switch/Switch.js.map +1 -1
- package/build/switch/Switch.mjs +8 -19
- package/build/switch/Switch.mjs.map +1 -1
- package/build/switchOption/SwitchOption.js +1 -0
- package/build/switchOption/SwitchOption.js.map +1 -1
- package/build/switchOption/SwitchOption.mjs +1 -0
- package/build/switchOption/SwitchOption.mjs.map +1 -1
- package/build/types/accordion/Accordion.d.ts +1 -1
- package/build/types/accordion/Accordion.d.ts.map +1 -1
- package/build/types/accordion/AccordionItem/AccordionItem.d.ts +12 -0
- package/build/types/accordion/AccordionItem/AccordionItem.d.ts.map +1 -1
- package/build/types/body/Body.d.ts +5 -0
- package/build/types/body/Body.d.ts.map +1 -1
- package/build/types/switch/Switch.d.ts.map +1 -1
- package/build/types/switchOption/SwitchOption.d.ts.map +1 -1
- package/package.json +7 -7
- package/src/accordion/Accordion.css +4 -1
- package/src/accordion/Accordion.less +10 -5
- package/src/accordion/Accordion.story.tsx +30 -1
- package/src/accordion/Accordion.tsx +5 -4
- package/src/accordion/AccordionItem/AccordionItem.tsx +25 -4
- package/src/body/Body.css +3 -0
- package/src/body/Body.less +3 -0
- package/src/body/Body.spec.tsx +8 -0
- package/src/body/Body.story.tsx +12 -0
- package/src/body/Body.tsx +11 -2
- package/src/instructionsList/InstructionsList.story.tsx +35 -37
- package/src/instructionsList/InstructionsList.tsx +1 -1
- package/src/main.css +19 -16
- package/src/main.less +2 -0
- package/src/switch/Switch.css +22 -41
- package/src/switch/Switch.less +6 -12
- package/src/switch/Switch.spec.tsx +11 -9
- package/src/switch/Switch.story.tsx +158 -33
- package/src/switch/Switch.tsx +6 -15
- package/src/switchOption/SwitchOption.css +4 -0
- package/src/switchOption/SwitchOption.less +8 -0
- package/src/switchOption/SwitchOption.spec.tsx +4 -5
- package/src/switchOption/SwitchOption.story.tsx +42 -38
- package/src/switchOption/SwitchOption.tsx +1 -0
- package/src/switch/__snapshots__/Switch.spec.tsx.snap +0 -44
package/src/body/Body.story.tsx
CHANGED
|
@@ -18,6 +18,9 @@ export const Basic = () => {
|
|
|
18
18
|
We’re building the world’s most <strong>international account</strong>. We’re building the
|
|
19
19
|
world’s most <b>international account</b>.
|
|
20
20
|
</Body>
|
|
21
|
+
<Body as="p" type={Typography.BODY_LARGE_BOLD} preserveNewlines>
|
|
22
|
+
{'This is line one.\nThis is line two.'}
|
|
23
|
+
</Body>
|
|
21
24
|
<Body as="p" type={Typography.BODY_LARGE_BOLD}>
|
|
22
25
|
Ми будуємо найбільш <strong>міжнародний рахунок у світі</strong>. Ми будуємо найбільш{' '}
|
|
23
26
|
<b>міжнародний рахунок у світі</b>.
|
|
@@ -40,6 +43,9 @@ export const Basic = () => {
|
|
|
40
43
|
We’re building the world’s most <strong>international account</strong>. We’re building the
|
|
41
44
|
world’s most <b>international account</b>.
|
|
42
45
|
</Body>
|
|
46
|
+
<Body as="p" preserveNewlines>
|
|
47
|
+
{'This is line one.\nThis is line two.'}
|
|
48
|
+
</Body>
|
|
43
49
|
<Body as="p" type={Typography.BODY_DEFAULT}>
|
|
44
50
|
Ми будуємо найбільш <strong>міжнародний рахунок у світі</strong>. Ми будуємо найбільш{' '}
|
|
45
51
|
<b>міжнародний рахунок у світі</b>.
|
|
@@ -62,6 +68,9 @@ export const Basic = () => {
|
|
|
62
68
|
We’re building the world’s most <strong>international account</strong>. We’re building the
|
|
63
69
|
world’s most <b>international account</b>.
|
|
64
70
|
</Body>
|
|
71
|
+
<Body as="p" type={Typography.BODY_DEFAULT_BOLD} preserveNewlines>
|
|
72
|
+
{'This is line one.\nThis is line two.'}
|
|
73
|
+
</Body>
|
|
65
74
|
<Body as="p" type={Typography.BODY_DEFAULT_BOLD}>
|
|
66
75
|
Ми будуємо найбільш <strong>міжнародний рахунок у світі</strong>. Ми будуємо найбільш{' '}
|
|
67
76
|
<b>міжнародний рахунок у світі</b>.
|
|
@@ -84,6 +93,9 @@ export const Basic = () => {
|
|
|
84
93
|
We’re building the world’s most <strong>international account</strong>. We’re building the
|
|
85
94
|
world’s most <b>international account</b>.
|
|
86
95
|
</Body>
|
|
96
|
+
<Body as="p" type={Typography.BODY_LARGE} preserveNewlines>
|
|
97
|
+
{'This is line one.\nThis is line two.'}
|
|
98
|
+
</Body>
|
|
87
99
|
<Body as="p" type={Typography.BODY_LARGE}>
|
|
88
100
|
Ми будуємо найбільш <strong>міжнародний рахунок у світі</strong>. Ми будуємо найбільш{' '}
|
|
89
101
|
<b>міжнародний рахунок у світі</b>.
|
package/src/body/Body.tsx
CHANGED
|
@@ -21,10 +21,15 @@ type Props = HTMLAttributes<HTMLSpanElement | HTMLParagraphElement> & {
|
|
|
21
21
|
* Default value: `div`
|
|
22
22
|
*/
|
|
23
23
|
as?: 'span' | 'p' | 'div';
|
|
24
|
+
/**
|
|
25
|
+
* When true, preserves newline characters in the text
|
|
26
|
+
* @default false
|
|
27
|
+
*/
|
|
28
|
+
preserveNewlines?: boolean;
|
|
24
29
|
};
|
|
25
30
|
|
|
26
31
|
const Body = forwardRef(function Body(
|
|
27
|
-
{ as: Element = 'div', type = DEFAULT_TYPE, className, ...props }: Props,
|
|
32
|
+
{ as: Element = 'div', type = DEFAULT_TYPE, className, preserveNewlines, ...props }: Props,
|
|
28
33
|
reference: React.ForwardedRef<
|
|
29
34
|
| {
|
|
30
35
|
[key in typeof Element]: React.ElementRef<key>;
|
|
@@ -39,7 +44,11 @@ const Body = forwardRef(function Body(
|
|
|
39
44
|
// @ts-expect-error TODO: Remove when component could be rewritten with generics
|
|
40
45
|
// See: https://fettblog.eu/typescript-react-generic-forward-refs/
|
|
41
46
|
ref={reference}
|
|
42
|
-
className={clsx(
|
|
47
|
+
className={clsx(
|
|
48
|
+
`np-text-${isTypeSupported ? type : DEFAULT_TYPE}`,
|
|
49
|
+
preserveNewlines && 'np-text--pre-line',
|
|
50
|
+
className,
|
|
51
|
+
)}
|
|
43
52
|
/>
|
|
44
53
|
);
|
|
45
54
|
});
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { fn } from '@storybook/test';
|
|
3
|
+
import { storyConfig } from '../test-utils';
|
|
2
4
|
|
|
3
5
|
import Link from '../link';
|
|
4
6
|
|
|
@@ -7,46 +9,42 @@ import InstructionsList, { InstructionsListProps } from './InstructionsList';
|
|
|
7
9
|
export default {
|
|
8
10
|
component: InstructionsList,
|
|
9
11
|
title: 'Typography/InstructionsList',
|
|
10
|
-
}
|
|
12
|
+
render: (args) => <InstructionsList {...args} />,
|
|
13
|
+
tags: ['autodocs'],
|
|
14
|
+
} satisfies Meta<typeof InstructionsList>;
|
|
15
|
+
|
|
16
|
+
type Story = StoryObj<typeof InstructionsList>;
|
|
11
17
|
|
|
12
|
-
export const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
donts={['Paying extra hidden fees for transfers', 'Use bad exchange rate']}
|
|
29
|
-
sort={args.sort}
|
|
30
|
-
/>
|
|
31
|
-
<hr />
|
|
32
|
-
<InstructionsList
|
|
33
|
-
dos={[
|
|
34
|
-
{ content: 'Multiple currencies', 'aria-label': 'Supports multiple currencies' },
|
|
35
|
-
{ content: 'Existing recipients', 'aria-label': 'Supports existing recipients' },
|
|
36
|
-
]}
|
|
37
|
-
donts={[
|
|
38
|
-
{ content: 'Create recipients', 'aria-label': "Doesn't support creating recipients" },
|
|
39
|
-
{ content: 'Edit recipients', 'aria-label': "Doesn't support editing recipients" },
|
|
40
|
-
]}
|
|
41
|
-
sort={args.sort}
|
|
42
|
-
/>
|
|
43
|
-
</>
|
|
44
|
-
);
|
|
18
|
+
export const Basic: Story = {
|
|
19
|
+
args: {
|
|
20
|
+
sort: 'dosFirst',
|
|
21
|
+
dos: [
|
|
22
|
+
'Do an initial money transfer',
|
|
23
|
+
'Invite at least 3 friends',
|
|
24
|
+
<span key="12">
|
|
25
|
+
Paying extra{' '}
|
|
26
|
+
<Link href="" type="link-large">
|
|
27
|
+
hidden fees
|
|
28
|
+
</Link>{' '}
|
|
29
|
+
for transfers
|
|
30
|
+
</span>,
|
|
31
|
+
],
|
|
32
|
+
donts: ['Paying extra hidden fees for transfers', 'Use bad exchange rate'],
|
|
33
|
+
},
|
|
45
34
|
};
|
|
46
35
|
|
|
47
|
-
export const
|
|
48
|
-
render: Template,
|
|
36
|
+
export const WithNewLine: Story = {
|
|
49
37
|
args: {
|
|
50
38
|
sort: 'dosFirst',
|
|
39
|
+
dos: [
|
|
40
|
+
'Do an initial money transfer',
|
|
41
|
+
'Invite at least 3 friends',
|
|
42
|
+
'This do item has a newline:\nSecond line appears below',
|
|
43
|
+
],
|
|
44
|
+
donts: [
|
|
45
|
+
'Paying extra hidden fees for transfers',
|
|
46
|
+
'Use bad exchange rate',
|
|
47
|
+
'This dont item has a newline:\nSecond line appears below',
|
|
48
|
+
],
|
|
51
49
|
},
|
|
52
50
|
};
|
|
@@ -71,7 +71,7 @@ function Instruction({ item, type }: { item: ReactNode | InstructionNode; type:
|
|
|
71
71
|
title={isInstructionNode ? item['aria-label'] : undefined}
|
|
72
72
|
/>
|
|
73
73
|
)}
|
|
74
|
-
<Body className="text-primary" type={Typography.BODY_LARGE}>
|
|
74
|
+
<Body className="text-primary" type={Typography.BODY_LARGE} preserveNewlines>
|
|
75
75
|
{isInstructionNode ? item.content : item}
|
|
76
76
|
</Body>
|
|
77
77
|
</li>
|
package/src/main.css
CHANGED
|
@@ -72,11 +72,15 @@
|
|
|
72
72
|
font-weight: 600;
|
|
73
73
|
font-weight: var(--font-weight-semi-bold);
|
|
74
74
|
}
|
|
75
|
+
.np-theme-personal .np-accordion-item--with-media .media {
|
|
76
|
+
display: flex;
|
|
77
|
+
align-items: center;
|
|
78
|
+
}
|
|
75
79
|
.np-theme-personal .np-accordion-item--with-icon .np-accordion-item__content {
|
|
76
80
|
padding: 0 56px 16px;
|
|
77
81
|
padding: 0 var(--size-56) var(--size-16);
|
|
78
82
|
}
|
|
79
|
-
.np-theme-personal .np-accordion-item .media {
|
|
83
|
+
.np-theme-personal .np-accordion-item--with-icon .media {
|
|
80
84
|
display: flex;
|
|
81
85
|
align-items: flex-start;
|
|
82
86
|
}
|
|
@@ -658,6 +662,9 @@
|
|
|
658
662
|
border-width: 1px;
|
|
659
663
|
border-color: var(--badge-border-color);
|
|
660
664
|
}
|
|
665
|
+
.np-text--pre-line {
|
|
666
|
+
white-space: pre-line;
|
|
667
|
+
}
|
|
661
668
|
.np-btn {
|
|
662
669
|
position: relative;
|
|
663
670
|
}
|
|
@@ -5142,6 +5149,8 @@ html:not([dir="rtl"]) .np-navigation-option {
|
|
|
5142
5149
|
margin-top: var(--size-24);
|
|
5143
5150
|
}
|
|
5144
5151
|
.np-switch {
|
|
5152
|
+
all: unset;
|
|
5153
|
+
box-sizing: border-box;
|
|
5145
5154
|
display: inline-flex;
|
|
5146
5155
|
overflow: hidden;
|
|
5147
5156
|
width: 50px;
|
|
@@ -5150,6 +5159,7 @@ html:not([dir="rtl"]) .np-navigation-option {
|
|
|
5150
5159
|
-webkit-user-select: none;
|
|
5151
5160
|
-moz-user-select: none;
|
|
5152
5161
|
user-select: none;
|
|
5162
|
+
cursor: pointer;
|
|
5153
5163
|
}
|
|
5154
5164
|
.np-switch:focus {
|
|
5155
5165
|
outline: none;
|
|
@@ -5182,21 +5192,10 @@ html:not([dir="rtl"]) .np-navigation-option {
|
|
|
5182
5192
|
[dir="rtl"] .np-switch--checked .np-switch--thumb {
|
|
5183
5193
|
transform: translateX(-20px) ;
|
|
5184
5194
|
}
|
|
5185
|
-
.np-switch
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
width: 0;
|
|
5190
|
-
height: 0;
|
|
5191
|
-
opacity: 0;
|
|
5192
|
-
}
|
|
5193
|
-
[dir="rtl"] .np-switch input {
|
|
5194
|
-
right: -100%;
|
|
5195
|
-
left: auto;
|
|
5196
|
-
left: initial;
|
|
5197
|
-
}
|
|
5198
|
-
.np-switch:not([aria-disabled]) {
|
|
5199
|
-
cursor: pointer;
|
|
5195
|
+
.np-switch.disabled {
|
|
5196
|
+
filter: grayscale(1);
|
|
5197
|
+
opacity: 0.45;
|
|
5198
|
+
cursor: not-allowed !important;
|
|
5200
5199
|
}
|
|
5201
5200
|
.np-theme-personal .np-switch {
|
|
5202
5201
|
padding: 1px 2px;
|
|
@@ -5212,6 +5211,10 @@ html:not([dir="rtl"]) .np-navigation-option {
|
|
|
5212
5211
|
background-color: #ffffff;
|
|
5213
5212
|
background-color: var(--color-background-screen);
|
|
5214
5213
|
}
|
|
5214
|
+
.np-switch-option.disabled .np-switch {
|
|
5215
|
+
filter: none;
|
|
5216
|
+
opacity: 1;
|
|
5217
|
+
}
|
|
5215
5218
|
.tabs {
|
|
5216
5219
|
position: relative;
|
|
5217
5220
|
}
|
package/src/main.less
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
@import "./avatarLayout/AvatarLayout.less";
|
|
9
9
|
@import "./iconButton/IconButton.less";
|
|
10
10
|
@import "./badge/Badge.less";
|
|
11
|
+
@import "./body/Body.less";
|
|
11
12
|
@import "./button/LegacyButton.less";
|
|
12
13
|
@import "./button/Button.less";
|
|
13
14
|
@import "./card/Card.less";
|
|
@@ -64,6 +65,7 @@
|
|
|
64
65
|
@import "./segmentedControl/SegmentedControl.less";
|
|
65
66
|
@import "./summary/Summary.less";
|
|
66
67
|
@import "./switch/Switch.less";
|
|
68
|
+
@import "./switchOption/SwitchOption.less";
|
|
67
69
|
@import "./tabs/Tabs.less";
|
|
68
70
|
@import "./table/Table.less";
|
|
69
71
|
@import "./tile/Tile.less";
|
package/src/switch/Switch.css
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
@media (min-width: 768px) {
|
|
2
|
+
}@media (min-width: 768px) {
|
|
3
|
+
}.np-switch {
|
|
4
|
+
all: unset;
|
|
5
|
+
box-sizing: border-box;
|
|
2
6
|
display: inline-flex;
|
|
3
7
|
overflow: hidden;
|
|
4
8
|
width: 50px;
|
|
@@ -7,61 +11,38 @@
|
|
|
7
11
|
-webkit-user-select: none;
|
|
8
12
|
-moz-user-select: none;
|
|
9
13
|
user-select: none;
|
|
10
|
-
|
|
11
|
-
.np-switch:focus {
|
|
14
|
+
cursor: pointer;
|
|
15
|
+
}.np-switch:focus {
|
|
12
16
|
outline: none;
|
|
13
|
-
}
|
|
14
|
-
.np-switch:focus-visible {
|
|
17
|
+
}.np-switch:focus-visible {
|
|
15
18
|
outline: var(--ring-outline-color) solid var(--ring-outline-width);
|
|
16
19
|
outline-offset: var(--ring-outline-offset);
|
|
17
|
-
}
|
|
18
|
-
.np-switch--thumb {
|
|
20
|
+
}.np-switch--thumb {
|
|
19
21
|
display: flex;
|
|
20
22
|
transition: transform cubic-bezier(0, 0.94, 0.62, 1) 350ms;
|
|
21
|
-
}
|
|
22
|
-
.np-switch--thumb .tw-icon {
|
|
23
|
+
}.np-switch--thumb .tw-icon {
|
|
23
24
|
color: #fff;
|
|
24
|
-
}
|
|
25
|
-
.np-switch--unchecked {
|
|
25
|
+
}.np-switch--unchecked {
|
|
26
26
|
background: #c9cbce;
|
|
27
27
|
background: var(--color-interactive-secondary);
|
|
28
|
-
}
|
|
29
|
-
.np-switch--unchecked .switch--thumb {
|
|
28
|
+
}.np-switch--unchecked .switch--thumb {
|
|
30
29
|
transform: translateX(0);
|
|
31
|
-
}
|
|
32
|
-
.np-switch--checked {
|
|
30
|
+
}.np-switch--checked {
|
|
33
31
|
background: #00a2dd;
|
|
34
32
|
background: var(--color-interactive-accent);
|
|
35
|
-
}
|
|
36
|
-
.np-switch--checked .np-switch--thumb {
|
|
33
|
+
}.np-switch--checked .np-switch--thumb {
|
|
37
34
|
transform: translateX(20px) ;
|
|
38
|
-
}
|
|
39
|
-
[dir="rtl"] .np-switch--checked .np-switch--thumb {
|
|
35
|
+
}[dir="rtl"] .np-switch--checked .np-switch--thumb {
|
|
40
36
|
transform: translateX(-20px) ;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
width: 0;
|
|
47
|
-
height: 0;
|
|
48
|
-
opacity: 0;
|
|
49
|
-
}
|
|
50
|
-
[dir="rtl"] .np-switch input {
|
|
51
|
-
right: -100%;
|
|
52
|
-
left: auto;
|
|
53
|
-
left: initial;
|
|
54
|
-
}
|
|
55
|
-
.np-switch:not([aria-disabled]) {
|
|
56
|
-
cursor: pointer;
|
|
57
|
-
}
|
|
58
|
-
.np-theme-personal .np-switch {
|
|
37
|
+
}.np-switch.disabled {
|
|
38
|
+
filter: grayscale(1);
|
|
39
|
+
opacity: 0.45;
|
|
40
|
+
cursor: not-allowed !important;
|
|
41
|
+
}.np-theme-personal .np-switch {
|
|
59
42
|
padding: 1px 2px;
|
|
60
|
-
}
|
|
61
|
-
.np-theme-personal .np-switch--checked {
|
|
43
|
+
}.np-theme-personal .np-switch--checked {
|
|
62
44
|
background: var(--color-interactive-primary);
|
|
63
|
-
}
|
|
64
|
-
.np-theme-personal .np-switch--thumb {
|
|
45
|
+
}.np-theme-personal .np-switch--thumb {
|
|
65
46
|
width: 20px;
|
|
66
47
|
height: 20px;
|
|
67
48
|
margin: 3px;
|
package/src/switch/Switch.less
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
@import (reference) "../../node_modules/@transferwise/neptune-css/src/variables/neptune-tokens.less";
|
|
2
2
|
@import (reference) "../../node_modules/@transferwise/neptune-css/src/less/mixins/_logical-properties.less";
|
|
3
3
|
@import (reference) "../../node_modules/@transferwise/neptune-css/src/less/ring.less";
|
|
4
|
+
@import (reference) "../../node_modules/@transferwise/neptune-css/src/less/core/_scaffolding.less";
|
|
4
5
|
|
|
5
6
|
.np-switch {
|
|
7
|
+
all: unset;
|
|
8
|
+
box-sizing: border-box;
|
|
6
9
|
display: inline-flex;
|
|
7
10
|
overflow: hidden;
|
|
8
11
|
width: 50px;
|
|
9
12
|
padding: 2px;
|
|
10
13
|
border-radius: 16px;
|
|
11
14
|
user-select: none;
|
|
15
|
+
cursor: pointer;
|
|
12
16
|
|
|
13
17
|
.focus-ring();
|
|
14
18
|
|
|
@@ -37,18 +41,8 @@
|
|
|
37
41
|
}
|
|
38
42
|
}
|
|
39
43
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
.left(-100%);
|
|
43
|
-
|
|
44
|
-
display: none;
|
|
45
|
-
width: 0;
|
|
46
|
-
height: 0;
|
|
47
|
-
opacity: 0;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
&:not([aria-disabled]) {
|
|
51
|
-
cursor: pointer;
|
|
44
|
+
&.disabled{
|
|
45
|
+
.disabled();
|
|
52
46
|
}
|
|
53
47
|
}
|
|
54
48
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Field } from '../field/Field';
|
|
2
|
-
import { render, fireEvent, screen } from '../test-utils';
|
|
2
|
+
import { render, userEvent, fireEvent, screen } from '../test-utils';
|
|
3
3
|
|
|
4
4
|
import Switch from './Switch';
|
|
5
5
|
|
|
@@ -22,7 +22,7 @@ describe('Switch', () => {
|
|
|
22
22
|
onClick={props.onClick}
|
|
23
23
|
/>,
|
|
24
24
|
);
|
|
25
|
-
expect(
|
|
25
|
+
expect(screen.getByRole('switch')).toBeChecked();
|
|
26
26
|
});
|
|
27
27
|
|
|
28
28
|
it('renders component associated with label', () => {
|
|
@@ -54,25 +54,27 @@ describe('Switch', () => {
|
|
|
54
54
|
onClick={props.onClick}
|
|
55
55
|
/>,
|
|
56
56
|
);
|
|
57
|
-
expect(
|
|
57
|
+
expect(screen.getByLabelText(props['aria-label'])).not.toBeChecked();
|
|
58
58
|
});
|
|
59
59
|
|
|
60
|
-
it('calls onClick when user press space key', () => {
|
|
60
|
+
it('calls onClick when user press space or enter key', async () => {
|
|
61
61
|
render(
|
|
62
62
|
<Switch
|
|
63
|
-
checked={props.checked}
|
|
64
63
|
className={props.className}
|
|
65
|
-
id={props.id}
|
|
66
64
|
aria-label={props['aria-label']}
|
|
67
65
|
onClick={props.onClick}
|
|
68
66
|
/>,
|
|
69
67
|
);
|
|
70
68
|
|
|
71
|
-
const input = screen.getAllByRole('checkbox')[0];
|
|
72
|
-
fireEvent.keyDown(input, { key: 'Enter' });
|
|
73
69
|
expect(props.onClick).not.toHaveBeenCalled();
|
|
74
|
-
|
|
70
|
+
|
|
71
|
+
await userEvent.tab();
|
|
72
|
+
|
|
73
|
+
await userEvent.keyboard(' ');
|
|
75
74
|
expect(props.onClick).toHaveBeenCalledTimes(1);
|
|
75
|
+
|
|
76
|
+
await userEvent.keyboard('{Enter}');
|
|
77
|
+
expect(props.onClick).toHaveBeenCalledTimes(2);
|
|
76
78
|
});
|
|
77
79
|
|
|
78
80
|
it('should not call onClick if disabled', () => {
|
|
@@ -1,59 +1,184 @@
|
|
|
1
1
|
import { useState } from 'react';
|
|
2
|
+
import { fn } from '@storybook/test';
|
|
2
3
|
|
|
3
|
-
import Switch from './Switch';
|
|
4
|
+
import Switch, { SwitchProps } from './Switch';
|
|
4
5
|
import { Field } from '../field/Field';
|
|
6
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
7
|
+
import { Label } from '../label';
|
|
5
8
|
|
|
6
|
-
|
|
9
|
+
const meta: Meta<typeof Switch> = {
|
|
7
10
|
component: Switch,
|
|
8
11
|
title: 'Actions/Switch',
|
|
12
|
+
args: {
|
|
13
|
+
checked: false,
|
|
14
|
+
disabled: false,
|
|
15
|
+
id: 'switchId',
|
|
16
|
+
className: 'switchClassName',
|
|
17
|
+
'aria-labelledby': undefined,
|
|
18
|
+
'aria-label': undefined,
|
|
19
|
+
onClick: fn(),
|
|
20
|
+
},
|
|
21
|
+
tags: ['autodocs'],
|
|
22
|
+
} satisfies Meta<typeof Switch>;
|
|
23
|
+
|
|
24
|
+
export default meta;
|
|
25
|
+
type Story = StoryObj<typeof Switch>;
|
|
26
|
+
|
|
27
|
+
export const Basic: Story = {
|
|
28
|
+
tags: ['!autodocs', '!dev'],
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const Playground: Story = {
|
|
32
|
+
tags: ['!autodocs'],
|
|
33
|
+
argTypes: {
|
|
34
|
+
onClick: { table: { disable: true } },
|
|
35
|
+
},
|
|
9
36
|
};
|
|
10
37
|
|
|
11
|
-
export const
|
|
38
|
+
export const Interactivity: Story = {
|
|
39
|
+
render: function Render({ disabled }: SwitchProps) {
|
|
40
|
+
const [checked1, setCheck1] = useState(false);
|
|
41
|
+
const [checked2, setCheck2] = useState(true);
|
|
42
|
+
const [checked3, setCheck3] = useState(false);
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<>
|
|
46
|
+
<Field id="fieldId" label="Using Field component">
|
|
47
|
+
<Switch checked={checked1} disabled={disabled} onClick={() => setCheck1(!checked1)} />
|
|
48
|
+
</Field>
|
|
49
|
+
|
|
50
|
+
<div>
|
|
51
|
+
<Label htmlFor="labelId">Using Label component</Label>
|
|
52
|
+
<Switch
|
|
53
|
+
id="labelId"
|
|
54
|
+
checked={checked2}
|
|
55
|
+
disabled={disabled}
|
|
56
|
+
onClick={() => setCheck2(!checked2)}
|
|
57
|
+
/>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<div>
|
|
61
|
+
<strong id="ariaId" className="d-block">
|
|
62
|
+
Using `aria-labelledby`
|
|
63
|
+
</strong>
|
|
64
|
+
<Switch
|
|
65
|
+
aria-labelledby="ariaId"
|
|
66
|
+
checked={checked3}
|
|
67
|
+
disabled={disabled}
|
|
68
|
+
onClick={() => setCheck3(!checked3)}
|
|
69
|
+
/>
|
|
70
|
+
</div>
|
|
71
|
+
</>
|
|
72
|
+
);
|
|
73
|
+
},
|
|
74
|
+
parameters: {
|
|
75
|
+
docs: {
|
|
76
|
+
source: {
|
|
77
|
+
code: `
|
|
78
|
+
function Render() {
|
|
12
79
|
const [checked1, setCheck1] = useState(false);
|
|
13
80
|
const [checked2, setCheck2] = useState(true);
|
|
14
|
-
|
|
81
|
+
const [checked3, setCheck3] = useState(false);
|
|
82
|
+
|
|
15
83
|
return (
|
|
16
|
-
|
|
17
|
-
<Field id="
|
|
84
|
+
<>
|
|
85
|
+
<Field id="fieldId" label="Using Field component">
|
|
18
86
|
<Switch
|
|
19
87
|
checked={checked1}
|
|
20
|
-
className="a-class-name"
|
|
21
|
-
id="switchId"
|
|
22
88
|
onClick={() => setCheck1(!checked1)}
|
|
23
89
|
/>
|
|
24
90
|
</Field>
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
91
|
+
|
|
92
|
+
<div>
|
|
93
|
+
<Label htmlFor="labelId">Using standalone Label component</Label>
|
|
94
|
+
<Switch
|
|
95
|
+
id="labelId"
|
|
96
|
+
checked={checked2}
|
|
97
|
+
onClick={() => setCheck2(!checked2)}
|
|
98
|
+
/>
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
<div>
|
|
102
|
+
<strong id="ariaId" className="d-block">Using \`aria-labelledby\`</strong>
|
|
103
|
+
<Switch
|
|
104
|
+
aria-labelledby="ariaId"
|
|
105
|
+
checked={checked3}
|
|
106
|
+
onClick={() => setCheck3(!setCheck3)}
|
|
107
|
+
/>
|
|
108
|
+
</div>
|
|
109
|
+
</>
|
|
110
|
+
)
|
|
111
|
+
}`,
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
decorators: [
|
|
116
|
+
(Story: any) => (
|
|
117
|
+
<div className="d-flex flex-column" style={{ gap: '1rem' }}>
|
|
118
|
+
<Story />
|
|
119
|
+
</div>
|
|
120
|
+
),
|
|
121
|
+
],
|
|
122
|
+
args: {},
|
|
123
|
+
argTypes: {
|
|
124
|
+
checked: { table: { disable: true } },
|
|
125
|
+
onClick: { table: { disable: true } },
|
|
126
|
+
},
|
|
33
127
|
};
|
|
34
128
|
|
|
35
|
-
export const Disabled =
|
|
36
|
-
|
|
129
|
+
export const Disabled: Story = {
|
|
130
|
+
render: function Render(args) {
|
|
131
|
+
const [checked1, setCheck1] = useState(false);
|
|
132
|
+
const [checked2, setCheck2] = useState(true);
|
|
133
|
+
|
|
134
|
+
return (
|
|
135
|
+
<>
|
|
136
|
+
<Field label="Switch label">
|
|
137
|
+
<Switch checked={checked1} disabled onClick={() => setCheck1(!checked1)} />
|
|
138
|
+
</Field>
|
|
139
|
+
|
|
140
|
+
<Field label="Switch label">
|
|
141
|
+
<Switch checked={checked2} disabled onClick={() => setCheck2(!checked2)} />
|
|
142
|
+
</Field>
|
|
143
|
+
</>
|
|
144
|
+
);
|
|
145
|
+
},
|
|
146
|
+
parameters: {
|
|
147
|
+
docs: {
|
|
148
|
+
source: {
|
|
149
|
+
code: `
|
|
150
|
+
function Render() {
|
|
151
|
+
const [checked1, setCheck1] = useState(false);
|
|
152
|
+
const [checked2, setCheck2] = useState(true);
|
|
37
153
|
|
|
38
154
|
return (
|
|
39
|
-
|
|
40
|
-
<Field
|
|
155
|
+
<>
|
|
156
|
+
<Field label="Switch label">
|
|
157
|
+
<Switch
|
|
158
|
+
checked={checked1}
|
|
159
|
+
disabled
|
|
160
|
+
onClick={() => setCheck1(!checked1)}
|
|
161
|
+
/>
|
|
162
|
+
</Fie
|
|
163
|
+
<Field label="Switch label">
|
|
41
164
|
<Switch
|
|
42
|
-
checked={
|
|
165
|
+
checked={checked2}
|
|
43
166
|
disabled
|
|
44
|
-
|
|
45
|
-
id="switchId"
|
|
46
|
-
onClick={() => setCheck(!checked)}
|
|
167
|
+
onClick={() => setCheck2(!checked2)}
|
|
47
168
|
/>
|
|
48
169
|
</Field>
|
|
49
|
-
|
|
50
|
-
aria-label="I'm a switch without label"
|
|
51
|
-
checked={!checked}
|
|
52
|
-
disabled
|
|
53
|
-
className="a-class-name"
|
|
54
|
-
id="switchId1"
|
|
55
|
-
onClick={() => setCheck(!checked)}
|
|
56
|
-
/>
|
|
57
|
-
</div>
|
|
170
|
+
</>
|
|
58
171
|
);
|
|
172
|
+
}`,
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
args: {
|
|
177
|
+
disabled: true,
|
|
178
|
+
},
|
|
179
|
+
argTypes: {
|
|
180
|
+
disabled: { table: { readonly: true } },
|
|
181
|
+
onClick: { table: { disable: true } },
|
|
182
|
+
checked: { table: { disable: true } },
|
|
183
|
+
},
|
|
59
184
|
};
|