@transferwise/components 46.96.1 → 46.97.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/build/alert/Alert.js.map +1 -1
- package/build/alert/Alert.mjs.map +1 -1
- package/build/avatarWrapper/AvatarWrapper.js.map +1 -1
- package/build/avatarWrapper/AvatarWrapper.mjs.map +1 -1
- package/build/common/propsValues/sentiment.js +1 -0
- package/build/common/propsValues/sentiment.js.map +1 -1
- package/build/common/propsValues/sentiment.mjs +1 -0
- package/build/common/propsValues/sentiment.mjs.map +1 -1
- package/build/main.css +60 -4
- package/build/progressBar/ProgressBar.js.map +1 -1
- package/build/progressBar/ProgressBar.mjs.map +1 -1
- package/build/statusIcon/StatusIcon.js +2 -2
- package/build/statusIcon/StatusIcon.js.map +1 -1
- package/build/statusIcon/StatusIcon.mjs +2 -2
- package/build/statusIcon/StatusIcon.mjs.map +1 -1
- package/build/styles/inputs/Input.css +28 -2
- package/build/styles/inputs/TextArea.css +28 -2
- package/build/styles/main.css +60 -4
- package/build/styles/popover/Popover.css +28 -2
- package/build/title/Title.js.map +1 -1
- package/build/title/Title.mjs.map +1 -1
- package/build/types/alert/Alert.d.ts +2 -2
- package/build/types/alert/Alert.d.ts.map +1 -1
- package/build/types/avatarWrapper/AvatarWrapper.d.ts +2 -2
- package/build/types/avatarWrapper/AvatarWrapper.d.ts.map +1 -1
- package/build/types/common/propsValues/sentiment.d.ts.map +1 -1
- package/build/types/progressBar/ProgressBar.d.ts +3 -3
- package/build/types/progressBar/ProgressBar.d.ts.map +1 -1
- package/build/types/statusIcon/StatusIcon.d.ts +3 -2
- package/build/types/statusIcon/StatusIcon.d.ts.map +1 -1
- package/build/types/title/Title.d.ts.map +1 -1
- package/package.json +6 -6
- package/src/alert/Alert.story.tsx +5 -3
- package/src/alert/Alert.tsx +11 -2
- package/src/avatarWrapper/AvatarWrapper.story.tsx +2 -2
- package/src/avatarWrapper/AvatarWrapper.tsx +3 -2
- package/src/common/propsValues/sentiment.ts +1 -0
- package/src/inputs/Input.css +28 -2
- package/src/inputs/TextArea.css +28 -2
- package/src/main.css +60 -4
- package/src/popover/Popover.css +28 -2
- package/src/progressBar/ProgressBar.spec.tsx +33 -8
- package/src/progressBar/ProgressBar.story.tsx +15 -0
- package/src/progressBar/ProgressBar.tsx +3 -3
- package/src/statusIcon/StatusIcon.docs.mdx +1 -1
- package/src/statusIcon/StatusIcon.spec.tsx +10 -4
- package/src/statusIcon/StatusIcon.story.tsx +10 -5
- package/src/statusIcon/StatusIcon.tsx +6 -4
- package/src/title/Title.test.story.tsx +19 -12
- package/src/title/Title.tsx +1 -0
package/src/popover/Popover.css
CHANGED
|
@@ -24,8 +24,6 @@
|
|
|
24
24
|
line-height: 1.2;
|
|
25
25
|
line-height: var(--line-height-title);
|
|
26
26
|
letter-spacing: 0;
|
|
27
|
-
-webkit-hyphens: auto;
|
|
28
|
-
hyphens: auto;
|
|
29
27
|
margin-bottom: 0;
|
|
30
28
|
margin-bottom: initial;
|
|
31
29
|
font-weight: 600;
|
|
@@ -34,6 +32,34 @@
|
|
|
34
32
|
font-size: var(--font-size-26);
|
|
35
33
|
letter-spacing: -0.02em;
|
|
36
34
|
line-height: 122%;
|
|
35
|
+
}@supports (hyphenate-limit-chars: 1) {
|
|
36
|
+
.np-popover__container.np-bottom-sheet .np-popover__title {
|
|
37
|
+
-webkit-hyphens: auto;
|
|
38
|
+
hyphens: auto;
|
|
39
|
+
hyphenate-limit-chars: 7 3;
|
|
40
|
+
}
|
|
41
|
+
@media (min-width: 768px) {
|
|
42
|
+
.np-popover__container.np-bottom-sheet .np-popover__title {
|
|
43
|
+
hyphenate-limit-chars: 8 3;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
@media (min-width: 992px) {
|
|
47
|
+
.np-popover__container.np-bottom-sheet .np-popover__title {
|
|
48
|
+
hyphenate-limit-chars: 10 4 3;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}@supports (not (hyphenate-limit-chars: 1)) and (-webkit-hyphenate-limit-before: 1) {
|
|
52
|
+
.np-popover__container.np-bottom-sheet .np-popover__title {
|
|
53
|
+
-webkit-hyphens: auto;
|
|
54
|
+
hyphens: auto;
|
|
55
|
+
-webkit-hyphenate-limit-before: 3;
|
|
56
|
+
-webkit-hyphenate-limit-after: 3;
|
|
57
|
+
}
|
|
58
|
+
@media (min-width: 992px) {
|
|
59
|
+
.np-popover__container.np-bottom-sheet .np-popover__title {
|
|
60
|
+
-webkit-hyphenate-limit-before: 4;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
37
63
|
}.np-popover__container.np-bottom-sheet .np-popover__title + p,
|
|
38
64
|
.np-popover__container.np-bottom-sheet .np-popover__title + ul:not(.list-unstyled),
|
|
39
65
|
.np-popover__container.np-bottom-sheet .np-popover__title + ol:not(.list-unstyled) {
|
|
@@ -3,15 +3,15 @@ import { render, screen } from '../test-utils';
|
|
|
3
3
|
import ProgressBar from './ProgressBar';
|
|
4
4
|
|
|
5
5
|
describe('ProgressBar', () => {
|
|
6
|
-
const props = {
|
|
7
|
-
description: 'description',
|
|
8
|
-
title: 'title',
|
|
9
|
-
progress: { value: 50, max: 100 },
|
|
10
|
-
textEnd: 'textEnd',
|
|
11
|
-
className: 'className',
|
|
12
|
-
id: 'id',
|
|
13
|
-
};
|
|
14
6
|
describe('by default', () => {
|
|
7
|
+
const props = {
|
|
8
|
+
description: 'description',
|
|
9
|
+
title: 'title',
|
|
10
|
+
progress: { value: 50, max: 100 },
|
|
11
|
+
textEnd: 'textEnd',
|
|
12
|
+
className: 'className',
|
|
13
|
+
id: 'id',
|
|
14
|
+
};
|
|
15
15
|
beforeEach(() => {
|
|
16
16
|
render(<ProgressBar {...props} />);
|
|
17
17
|
});
|
|
@@ -28,4 +28,29 @@ describe('ProgressBar', () => {
|
|
|
28
28
|
expect(screen.getByText('textEnd')).toBeInTheDocument();
|
|
29
29
|
});
|
|
30
30
|
});
|
|
31
|
+
describe('with custom React node type as props', () => {
|
|
32
|
+
const props = {
|
|
33
|
+
description: <span>Custom Description</span>,
|
|
34
|
+
title: <span>Custom Title</span>,
|
|
35
|
+
progress: { value: 50, max: 100 },
|
|
36
|
+
textEnd: <span>Custom TextEnd</span>,
|
|
37
|
+
className: 'className',
|
|
38
|
+
id: 'id',
|
|
39
|
+
};
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
render(<ProgressBar {...props} />);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('renders the custom title', () => {
|
|
45
|
+
expect(screen.getByText('Custom Title')).toBeInTheDocument();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('renders the custom description', () => {
|
|
49
|
+
expect(screen.getByText('Custom Description')).toBeInTheDocument();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('renders the custom textEnd', () => {
|
|
53
|
+
expect(screen.getByText('Custom TextEnd')).toBeInTheDocument();
|
|
54
|
+
});
|
|
55
|
+
});
|
|
31
56
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Meta, StoryObj } from '@storybook/react';
|
|
2
2
|
|
|
3
3
|
import ProgressBar from './ProgressBar';
|
|
4
|
+
import Info from '../info';
|
|
4
5
|
|
|
5
6
|
export default {
|
|
6
7
|
component: ProgressBar,
|
|
@@ -19,3 +20,17 @@ export const Basic: Story = {
|
|
|
19
20
|
textEnd: '200 GBP to go',
|
|
20
21
|
},
|
|
21
22
|
};
|
|
23
|
+
|
|
24
|
+
export const WithInfoTooltip: Story = {
|
|
25
|
+
args: {
|
|
26
|
+
description: <span>1,000 GBP</span>,
|
|
27
|
+
id: 'progress-bar-id',
|
|
28
|
+
title: (
|
|
29
|
+
<span>
|
|
30
|
+
Total limit <Info content="This is the total limit of your Wise account" />
|
|
31
|
+
</span>
|
|
32
|
+
),
|
|
33
|
+
progress: { value: 800, max: 1000 },
|
|
34
|
+
textEnd: <span>200 GBP remaining</span>,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
@@ -8,11 +8,11 @@ import Title from '../title/Title';
|
|
|
8
8
|
|
|
9
9
|
export type ProgressBarProps = {
|
|
10
10
|
className?: string;
|
|
11
|
-
description?:
|
|
11
|
+
description?: React.ReactNode;
|
|
12
12
|
id: string;
|
|
13
|
-
title:
|
|
13
|
+
title: React.ReactNode;
|
|
14
14
|
progress: { value: number; max: number };
|
|
15
|
-
textEnd:
|
|
15
|
+
textEnd: React.ReactNode;
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
const ProgressBar = ({
|
|
@@ -10,7 +10,7 @@ By default, the component offers accessible names for all the icons, to ensure t
|
|
|
10
10
|
Sentiment.NEGATIVE -> 'Error:'
|
|
11
11
|
Sentiment.POSITIVE -> 'Success:'
|
|
12
12
|
Sentiment.WARNING -> 'Warning:'
|
|
13
|
-
|
|
13
|
+
Status.PENDING -> 'Pending:'
|
|
14
14
|
Sentiment.NEUTRAL -> 'Information:'
|
|
15
15
|
|
|
16
16
|
// deprecated
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { Sentiment, Size } from '../common';
|
|
1
|
+
import { Sentiment, Size, Status } from '../common';
|
|
2
2
|
import { render, cleanup, screen, mockMatchMedia } from '../test-utils';
|
|
3
3
|
|
|
4
4
|
import StatusIcon, { type StatusIconProps } from '.';
|
|
5
|
+
import { StatusIconSentiment } from './StatusIcon';
|
|
5
6
|
|
|
6
7
|
mockMatchMedia();
|
|
7
8
|
|
|
@@ -29,12 +30,13 @@ describe('StatusIcon', () => {
|
|
|
29
30
|
[Sentiment.NEGATIVE, Sentiment.NEGATIVE],
|
|
30
31
|
[Sentiment.NEUTRAL, Sentiment.NEUTRAL],
|
|
31
32
|
[Sentiment.PENDING, Sentiment.PENDING],
|
|
33
|
+
[Status.PENDING, Status.PENDING],
|
|
32
34
|
[Sentiment.POSITIVE, Sentiment.POSITIVE],
|
|
33
35
|
[Sentiment.WARNING, Sentiment.WARNING],
|
|
34
36
|
])(
|
|
35
37
|
"if prop 'sentiment' equals '%s' is passed, renders the status icon with class '%s'",
|
|
36
38
|
(sentiment, expectedClass) => {
|
|
37
|
-
renderStatusIcon({ sentiment });
|
|
39
|
+
renderStatusIcon({ sentiment: sentiment as StatusIconSentiment });
|
|
38
40
|
|
|
39
41
|
expect(screen.getByTestId('status-icon')).toHaveClass(expectedClass);
|
|
40
42
|
cleanup();
|
|
@@ -48,6 +50,10 @@ describe('StatusIcon', () => {
|
|
|
48
50
|
|
|
49
51
|
renderStatusIcon({ sentiment: Sentiment.PENDING });
|
|
50
52
|
expect(screen.getByTestId('clock-borderless-icon')).toHaveClass('dark');
|
|
53
|
+
cleanup();
|
|
54
|
+
|
|
55
|
+
renderStatusIcon({ sentiment: Status.PENDING });
|
|
56
|
+
expect(screen.getByTestId('clock-borderless-icon')).toHaveClass('dark');
|
|
51
57
|
});
|
|
52
58
|
|
|
53
59
|
it("'positive', 'negative', and 'neutral' sentiments generate 'light' colored icons", () => {
|
|
@@ -68,13 +74,13 @@ describe('StatusIcon', () => {
|
|
|
68
74
|
['Error', Sentiment.NEGATIVE],
|
|
69
75
|
['Success', Sentiment.POSITIVE],
|
|
70
76
|
['Warning', Sentiment.WARNING],
|
|
71
|
-
['Pending',
|
|
77
|
+
['Pending', Status.PENDING],
|
|
72
78
|
['Information', Sentiment.NEUTRAL],
|
|
73
79
|
['Error', Sentiment.ERROR],
|
|
74
80
|
['Information', Sentiment.INFO],
|
|
75
81
|
['Success', Sentiment.SUCCESS],
|
|
76
82
|
])("should set '%s' as an accessible name for the '%s' sentiment", (label, sentiment) => {
|
|
77
|
-
renderStatusIcon({ sentiment });
|
|
83
|
+
renderStatusIcon({ sentiment: sentiment as StatusIconSentiment });
|
|
78
84
|
|
|
79
85
|
expect(screen.getByLabelText(`${label}:`)).toBeInTheDocument();
|
|
80
86
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Meta, StoryObj } from '@storybook/react';
|
|
2
2
|
|
|
3
|
-
import { Sentiment, Size } from '../common';
|
|
3
|
+
import { Sentiment, Size, Status } from '../common';
|
|
4
4
|
|
|
5
|
-
import StatusIcon from './StatusIcon';
|
|
5
|
+
import StatusIcon, { StatusIconSentiment } from './StatusIcon';
|
|
6
6
|
import { storyConfig } from '../test-utils';
|
|
7
7
|
|
|
8
8
|
export default {
|
|
@@ -42,6 +42,7 @@ export const Variants = storyConfig(
|
|
|
42
42
|
Sentiment.WARNING,
|
|
43
43
|
Sentiment.NEUTRAL,
|
|
44
44
|
Sentiment.PENDING,
|
|
45
|
+
Status.PENDING,
|
|
45
46
|
].map((sentiment) => {
|
|
46
47
|
return (
|
|
47
48
|
<span
|
|
@@ -55,7 +56,9 @@ export const Variants = storyConfig(
|
|
|
55
56
|
}}
|
|
56
57
|
>
|
|
57
58
|
{([16, 24, 32, 40, 48, 56, 72] as const).map((size) => {
|
|
58
|
-
return
|
|
59
|
+
return (
|
|
60
|
+
<StatusIcon key={size} size={size} sentiment={sentiment as StatusIconSentiment} />
|
|
61
|
+
);
|
|
59
62
|
})}
|
|
60
63
|
</span>
|
|
61
64
|
);
|
|
@@ -74,7 +77,7 @@ export const LegacySizes: Story = {
|
|
|
74
77
|
Sentiment.NEGATIVE,
|
|
75
78
|
Sentiment.NEUTRAL,
|
|
76
79
|
Sentiment.WARNING,
|
|
77
|
-
|
|
80
|
+
Status.PENDING,
|
|
78
81
|
].map((sentiment) => {
|
|
79
82
|
return (
|
|
80
83
|
<span
|
|
@@ -88,7 +91,9 @@ export const LegacySizes: Story = {
|
|
|
88
91
|
}}
|
|
89
92
|
>
|
|
90
93
|
{([Size.SMALL, Size.MEDIUM, Size.LARGE] as const).map((size) => {
|
|
91
|
-
return
|
|
94
|
+
return (
|
|
95
|
+
<StatusIcon key={size} size={size} sentiment={sentiment as StatusIconSentiment} />
|
|
96
|
+
);
|
|
92
97
|
})}
|
|
93
98
|
</span>
|
|
94
99
|
);
|
|
@@ -2,7 +2,7 @@ import { Info, Alert, Cross, Check, ClockBorderless } from '@transferwise/icons'
|
|
|
2
2
|
import { clsx } from 'clsx';
|
|
3
3
|
import { useIntl } from 'react-intl';
|
|
4
4
|
|
|
5
|
-
import { SizeSmall, SizeMedium, SizeLarge, Sentiment, Size, Breakpoint } from '../common';
|
|
5
|
+
import { SizeSmall, SizeMedium, SizeLarge, Sentiment, Size, Breakpoint, Status } from '../common';
|
|
6
6
|
import Circle, { CircleProps } from '../common/circle';
|
|
7
7
|
import { useMedia } from '../common/hooks/useMedia';
|
|
8
8
|
|
|
@@ -13,8 +13,10 @@ import messages from './StatusIcon.messages';
|
|
|
13
13
|
*/
|
|
14
14
|
type LegacySizes = SizeSmall | SizeMedium | SizeLarge;
|
|
15
15
|
|
|
16
|
+
export type StatusIconSentiment = Sentiment | Status.PENDING;
|
|
17
|
+
|
|
16
18
|
export type StatusIconProps = {
|
|
17
|
-
sentiment?: `${
|
|
19
|
+
sentiment?: `${StatusIconSentiment}`;
|
|
18
20
|
size?: LegacySizes | 16 | 24 | 32 | 40 | 48 | 56 | 72;
|
|
19
21
|
/**
|
|
20
22
|
* Override for the sentiment's-derived, default, accessible
|
|
@@ -34,7 +36,7 @@ const StatusIcon = ({ sentiment = 'neutral', size: sizeProp = 40, iconLabel }: S
|
|
|
34
36
|
const intl = useIntl();
|
|
35
37
|
|
|
36
38
|
const iconMetaBySentiment: Record<
|
|
37
|
-
`${Sentiment}
|
|
39
|
+
`${Sentiment}` | Status.PENDING,
|
|
38
40
|
{
|
|
39
41
|
Icon: React.ElementType;
|
|
40
42
|
defaultIconLabel: string;
|
|
@@ -52,7 +54,7 @@ const StatusIcon = ({ sentiment = 'neutral', size: sizeProp = 40, iconLabel }: S
|
|
|
52
54
|
Icon: Alert,
|
|
53
55
|
defaultIconLabel: intl.formatMessage(messages.warningLabel),
|
|
54
56
|
},
|
|
55
|
-
[
|
|
57
|
+
[Status.PENDING]: {
|
|
56
58
|
Icon: ClockBorderless,
|
|
57
59
|
defaultIconLabel: intl.formatMessage(messages.pendingLabel),
|
|
58
60
|
},
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Typography } from '../common/propsValues/typography';
|
|
2
|
-
import Modal from '../modal';
|
|
3
2
|
import { lorem1000 } from '../test-utils';
|
|
4
3
|
|
|
5
4
|
import Title from './Title';
|
|
@@ -7,19 +6,27 @@ import Title from './Title';
|
|
|
7
6
|
export default {
|
|
8
7
|
component: Title,
|
|
9
8
|
title: 'Typography/Title/Tests',
|
|
9
|
+
args: {
|
|
10
|
+
children: lorem1000.replaceAll(' ', ''),
|
|
11
|
+
},
|
|
12
|
+
argTypes: {
|
|
13
|
+
as: {
|
|
14
|
+
table: {
|
|
15
|
+
disable: true,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
type: {
|
|
19
|
+
table: {
|
|
20
|
+
disable: true,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
},
|
|
10
24
|
};
|
|
11
25
|
|
|
12
|
-
export const Hyphenation = () => {
|
|
26
|
+
export const Hyphenation = ({ children }: { children: string }) => {
|
|
13
27
|
return (
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
<Title type={Typography.TITLE_SCREEN} style={{ maxWidth: '600px' }}>
|
|
18
|
-
This Screen Title is mostly one very long word and it hyphenates{' '}
|
|
19
|
-
{lorem1000.replaceAll(' ', '')}
|
|
20
|
-
</Title>
|
|
21
|
-
}
|
|
22
|
-
onClose={() => {}}
|
|
23
|
-
/>
|
|
28
|
+
<Title type={Typography.TITLE_SCREEN} style={{ maxWidth: '600px', wordWrap: 'break-word' }}>
|
|
29
|
+
{` ${children}`}
|
|
30
|
+
</Title>
|
|
24
31
|
);
|
|
25
32
|
};
|
package/src/title/Title.tsx
CHANGED
|
@@ -28,6 +28,7 @@ type Props = LabelHTMLAttributes<HTMLHeadingElement | HTMLSpanElement | HTMLLabe
|
|
|
28
28
|
function Title({ as, type = DEFAULT_TYPE, className, ...props }: Props) {
|
|
29
29
|
const mapping = titleTypeMapping[type];
|
|
30
30
|
const isTypeSupported = mapping !== undefined;
|
|
31
|
+
|
|
31
32
|
if (isTypeSupported) {
|
|
32
33
|
const HeaderTag = as ?? mapping;
|
|
33
34
|
return <HeaderTag {...props} className={clsx(`np-text-${type}`, className)} />;
|