@transferwise/components 46.122.1 → 46.123.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.
Files changed (69) hide show
  1. package/build/inputs/SelectInput.js +32 -1
  2. package/build/inputs/SelectInput.js.map +1 -1
  3. package/build/inputs/SelectInput.mjs +32 -1
  4. package/build/inputs/SelectInput.mjs.map +1 -1
  5. package/build/main.css +97 -77
  6. package/build/prompt/InlinePrompt/InlinePrompt.js +8 -10
  7. package/build/prompt/InlinePrompt/InlinePrompt.js.map +1 -1
  8. package/build/prompt/InlinePrompt/InlinePrompt.mjs +9 -11
  9. package/build/prompt/InlinePrompt/InlinePrompt.mjs.map +1 -1
  10. package/build/prompt/PrimitivePrompt/PrimitivePrompt.js +45 -0
  11. package/build/prompt/PrimitivePrompt/PrimitivePrompt.js.map +1 -0
  12. package/build/prompt/PrimitivePrompt/PrimitivePrompt.mjs +43 -0
  13. package/build/prompt/PrimitivePrompt/PrimitivePrompt.mjs.map +1 -0
  14. package/build/styles/main.css +97 -77
  15. package/build/styles/prompt/InlinePrompt/InlinePrompt.css +2 -23
  16. package/build/styles/prompt/PrimitivePrompt/PrimitivePrompt.css +41 -0
  17. package/build/types/inputs/SelectInput.d.ts +2 -1
  18. package/build/types/inputs/SelectInput.d.ts.map +1 -1
  19. package/build/types/prompt/InlinePrompt/InlinePrompt.d.ts +1 -1
  20. package/build/types/prompt/InlinePrompt/InlinePrompt.d.ts.map +1 -1
  21. package/build/types/prompt/PrimitivePrompt/PrimitivePrompt.d.ts +30 -0
  22. package/build/types/prompt/PrimitivePrompt/PrimitivePrompt.d.ts.map +1 -0
  23. package/build/types/prompt/PrimitivePrompt/index.d.ts +3 -0
  24. package/build/types/prompt/PrimitivePrompt/index.d.ts.map +1 -0
  25. package/package.json +8 -8
  26. package/src/alert/Alert.tests.story.tsx +1 -0
  27. package/src/button/_stories/Button.brightGreen.tests.story.tsx +1 -1
  28. package/src/button/_stories/Button.dark.tests.story.tsx +1 -1
  29. package/src/button/_stories/Button.default.tests.story.tsx +1 -1
  30. package/src/button/_stories/Button.forestGreen.tests.story.tsx +1 -1
  31. package/src/button/_stories/Button.tests.story.tsx +1 -1
  32. package/src/circularButton/CircularButton.tests.story.tsx +1 -0
  33. package/src/dateInput/DateInput.tests.story.tsx +1 -0
  34. package/src/dateLookup/DateLookup.tests.story.tsx +1 -0
  35. package/src/header/Header.tests.story.tsx +1 -1
  36. package/src/inputs/SelectInput.spec.tsx +54 -0
  37. package/src/inputs/SelectInput.story.tsx +68 -0
  38. package/src/inputs/SelectInput.tsx +57 -6
  39. package/src/legacylistItem/LegacyListItem.tests.story.tsx +1 -1
  40. package/src/listItem/ListItem.spec.tsx +6 -8
  41. package/src/listItem/_stories/ListItem.focus.test.story.tsx +1 -1
  42. package/src/listItem/_stories/ListItem.layout.test.story.tsx +1 -1
  43. package/src/listItem/_stories/variants/ListItem.brightGreen.test.story.tsx +1 -1
  44. package/src/listItem/_stories/variants/ListItem.dark.test.story.tsx +1 -1
  45. package/src/listItem/_stories/variants/ListItem.forestGreen.test.story.tsx +1 -1
  46. package/src/listItem/_stories/variants/ListItem.medium.test.story.tsx +1 -1
  47. package/src/listItem/_stories/variants/ListItem.neutral.test.story.tsx +1 -1
  48. package/src/listItem/_stories/variants/ListItem.personal.test.story.tsx +1 -1
  49. package/src/listItem/_stories/variants/ListItem.rtl.test.story.tsx +1 -1
  50. package/src/listItem/_stories/variants/ListItem.small.test.story.tsx +1 -1
  51. package/src/main.css +97 -77
  52. package/src/main.less +2 -1
  53. package/src/prompt/InlinePrompt/InlinePrompt.css +2 -23
  54. package/src/prompt/InlinePrompt/InlinePrompt.less +3 -18
  55. package/src/prompt/InlinePrompt/InlinePrompt.spec.tsx +6 -6
  56. package/src/prompt/InlinePrompt/InlinePrompt.tsx +6 -7
  57. package/src/prompt/PrimitivePrompt/PrimitivePrompt.css +41 -0
  58. package/src/prompt/PrimitivePrompt/PrimitivePrompt.less +37 -0
  59. package/src/prompt/PrimitivePrompt/PrimitivePrompt.tsx +70 -0
  60. package/src/prompt/PrimitivePrompt/index.ts +2 -0
  61. package/src/radioGroup/RadioGroup.test.story.tsx +1 -1
  62. package/src/sentimentSurface/SentimentSurface.tests.story.tsx +1 -1
  63. package/src/snackbar/Snackbar.tests.story.tsx +1 -1
  64. package/src/stepper/Stepper.tests.story.tsx +1 -0
  65. package/src/summary/Summary.tests.story.tsx +1 -0
  66. package/src/title/Title.test.story.tsx +1 -0
  67. package/src/upload/Upload.tests.story.tsx +1 -0
  68. package/src/uploadInput/UploadInput.tests.story.tsx +1 -0
  69. package/src/withId/withId.story.tsx +1 -1
@@ -1,18 +1,9 @@
1
1
  .wds-inline-prompt {
2
+ --Prompt-gap: calc(var(--size-12) / 2);
3
+ --Prompt-padding: calc(var(--padding-x-small) / 2) var(--padding-x-small);
2
4
  display: inline-flex;
3
- text-align: left;
4
- padding-top: calc(8px / 2);
5
- padding-top: calc(var(--padding-x-small) / 2);
6
- padding-bottom: calc(8px / 2);
7
- padding-bottom: calc(var(--padding-x-small) / 2);
8
- padding-left: calc(8px - 1px);
9
- padding-left: calc(var(--padding-x-small) - 1px);
10
- padding-right: 8px;
11
- padding-right: var(--padding-x-small);
12
5
  border-radius: 10px;
13
6
  border-radius: var(--radius-small);
14
- word-break: break-word;
15
- word-wrap: break-word;
16
7
  }
17
8
  .wds-inline-prompt:has(a),
18
9
  .wds-inline-prompt:has(button) {
@@ -54,18 +45,6 @@
54
45
  position: absolute;
55
46
  inset: 0;
56
47
  }
57
- .wds-inline-prompt__media-wrapper {
58
- padding-right: calc(12px / 2);
59
- padding-right: calc(var(--size-12) / 2);
60
- padding-top: calc(4px - 1px);
61
- padding-top: calc(var(--size-4) - 1px);
62
- padding-bottom: calc(4px - 1px);
63
- padding-bottom: calc(var(--size-4) - 1px);
64
- }
65
- .wds-inline-prompt__media-wrapper .tw-icon-tags,
66
- .wds-inline-prompt__media-wrapper .tw-icon-confetti {
67
- color: var(--color-sentiment-content-primary);
68
- }
69
48
  .wds-inline-prompt .wds-inline-prompt-process-indicator {
70
49
  width: 16px;
71
50
  width: var(--size-16);
@@ -1,13 +1,9 @@
1
1
  .wds-inline-prompt {
2
+ --Prompt-gap: calc(var(--size-12) / 2);
3
+ --Prompt-padding: calc(var(--padding-x-small) / 2) var(--padding-x-small);
4
+
2
5
  display: inline-flex;
3
- text-align: left;
4
- padding-top: calc(var(--padding-x-small) / 2);
5
- padding-bottom: calc(var(--padding-x-small) / 2);
6
- padding-left: calc(var(--padding-x-small) - 1px);
7
- padding-right: var(--padding-x-small);
8
6
  border-radius: var(--radius-small);
9
- word-break: break-word;
10
- overflow-wrap: break-word;
11
7
 
12
8
  &:has(a),
13
9
  &:has(button) {
@@ -54,17 +50,6 @@
54
50
  }
55
51
  }
56
52
 
57
- &__media-wrapper {
58
- padding-right: calc(var(--size-12) / 2);
59
- padding-top: calc(var(--size-4) - 1px);
60
- padding-bottom: calc(var(--size-4) - 1px);
61
-
62
- .tw-icon-tags,
63
- .tw-icon-confetti {
64
- color: var(--color-sentiment-content-primary);
65
- }
66
- }
67
-
68
53
  .wds-inline-prompt-process-indicator {
69
54
  width: var(--size-16);
70
55
  height: var(--size-16);
@@ -32,8 +32,8 @@ describe('InlinePrompt', () => {
32
32
  describe(sentiment, () => {
33
33
  it('should apply correct styles', () => {
34
34
  render(<InlinePrompt {...defaultProps} sentiment={sentiment} />);
35
- expect(screen.getByText('Prompt message').parentElement).toHaveClass(
36
- `wds-inline-prompt--${sentiment}`,
35
+ expect(screen.getByText('Prompt message').parentElement?.parentElement).toHaveClass(
36
+ `wds-prompt--${sentiment === Sentiment.POSITIVE ? 'success' : sentiment}`,
37
37
  );
38
38
  });
39
39
 
@@ -47,7 +47,7 @@ describe('InlinePrompt', () => {
47
47
  describe('muted state', () => {
48
48
  it('should render icon and apply css', () => {
49
49
  render(<InlinePrompt {...defaultProps} muted sentiment={sentiment} />);
50
- expect(screen.getByText('Prompt message').parentElement).toHaveClass(
50
+ expect(screen.getByText('Prompt message').parentElement?.parentElement).toHaveClass(
51
51
  'wds-inline-prompt--muted',
52
52
  );
53
53
  expect(screen.getByTestId('InlinePrompt_Muted')).toBeInTheDocument();
@@ -63,7 +63,7 @@ describe('InlinePrompt', () => {
63
63
  describe('loading state', () => {
64
64
  it('should render icon and apply css', () => {
65
65
  render(<InlinePrompt {...defaultProps} sentiment={sentiment} loading />);
66
- expect(screen.getByText('Prompt message').parentElement).toHaveClass(
66
+ expect(screen.getByText('Prompt message').parentElement?.parentElement).toHaveClass(
67
67
  'wds-inline-prompt--loading',
68
68
  );
69
69
  expect(screen.getByTestId('InlinePrompt_ProcessIndicator')).toBeInTheDocument();
@@ -134,7 +134,7 @@ describe('InlinePrompt', () => {
134
134
  );
135
135
  const el = screen.getByTestId('prompt');
136
136
  // The component should have both the original class and the SentimentSurface class
137
- expect(el).toHaveClass('wds-inline-prompt--positive');
137
+ expect(el).toHaveClass('wds-prompt--success');
138
138
  expect(el).toHaveClass('wds-sentiment-surface');
139
139
  });
140
140
 
@@ -143,7 +143,7 @@ describe('InlinePrompt', () => {
143
143
  <InlinePrompt {...defaultProps} sentiment={Sentiment.NEGATIVE} data-testid="prompt" />,
144
144
  );
145
145
  const el = screen.getByTestId('prompt');
146
- expect(el).toHaveClass('wds-inline-prompt--negative');
146
+ expect(el).toHaveClass('wds-prompt--negative');
147
147
  expect(el).toHaveClass('wds-sentiment-surface');
148
148
  });
149
149
  });
@@ -4,7 +4,7 @@ import ProcessIndicator from '../../processIndicator';
4
4
  import StatusIcon from '../../statusIcon';
5
5
  import { clsx } from 'clsx';
6
6
  import Body from '../../body';
7
- import SentimentSurface from '../../sentimentSurface';
7
+ import { PrimitivePrompt } from '../PrimitivePrompt';
8
8
 
9
9
  export type InlinePromptProps = {
10
10
  /**
@@ -60,7 +60,7 @@ export const InlinePrompt = ({
60
60
  mediaLabel,
61
61
  width = 'auto',
62
62
  'data-testid': dataTestId,
63
- ...rest
63
+ ...restProps
64
64
  }: InlinePromptProps) => {
65
65
  const surfaceSentiment = sentiment === Sentiment.POSITIVE ? 'success' : sentiment;
66
66
 
@@ -87,12 +87,12 @@ export const InlinePrompt = ({
87
87
  };
88
88
 
89
89
  return (
90
- <SentimentSurface
90
+ <PrimitivePrompt
91
91
  sentiment={surfaceSentiment}
92
+ media={renderMedia()}
92
93
  data-testid={dataTestId}
93
94
  className={clsx(
94
95
  'wds-inline-prompt',
95
- `wds-inline-prompt--${sentiment}`,
96
96
  {
97
97
  'wds-inline-prompt--full-width': width === 'full',
98
98
  'wds-inline-prompt--muted': muted,
@@ -100,10 +100,9 @@ export const InlinePrompt = ({
100
100
  },
101
101
  className,
102
102
  )}
103
- {...rest}
103
+ {...restProps}
104
104
  >
105
- <div className="wds-inline-prompt__media-wrapper">{renderMedia()}</div>
106
105
  <Body>{children}</Body>
107
- </SentimentSurface>
106
+ </PrimitivePrompt>
108
107
  );
109
108
  };
@@ -0,0 +1,41 @@
1
+ .wds-prompt {
2
+ border-radius: 10px;
3
+ border-radius: var(--radius-small);
4
+ display: flex;
5
+ word-wrap: break-word;
6
+ padding: 8px;
7
+ padding: var(--Prompt-padding, var(--padding-x-small));
8
+ text-align: left;
9
+ word-break: break-word;
10
+ }
11
+ .wds-prompt__content-wrapper {
12
+ display: grid;
13
+ grid-gap: 16px;
14
+ grid-gap: var(--Prompt-gap, var(--size-16));
15
+ gap: 16px;
16
+ gap: var(--Prompt-gap, var(--size-16));
17
+ grid-template-columns: auto 1fr;
18
+ width: 100%;
19
+ }
20
+ .wds-prompt__media-wrapper {
21
+ align-self: flex-start;
22
+ padding-top: calc(4px - 1px);
23
+ padding-top: calc(var(--size-4) - 1px);
24
+ }
25
+ .wds-prompt__media-wrapper .tw-icon-tags,
26
+ .wds-prompt__media-wrapper .tw-icon-confetti {
27
+ color: var(--color-sentiment-content-primary);
28
+ }
29
+ .wds-prompt__actions-wrapper {
30
+ display: flex;
31
+ flex-wrap: wrap;
32
+ gap: 8px;
33
+ gap: var(--Prompt-actions-gap, var(--size-8));
34
+ grid-column-start: 2;
35
+ }
36
+ @media (max-width: 991px) {
37
+ .wds-prompt__actions-wrapper {
38
+ grid-column: span 2;
39
+ width: 100%;
40
+ }
41
+ }
@@ -0,0 +1,37 @@
1
+ .wds-prompt {
2
+ border-radius: var(--radius-small);
3
+ display: flex;
4
+ overflow-wrap: break-word;
5
+ padding: var(--Prompt-padding, var(--padding-x-small));
6
+ text-align: left;
7
+ word-break: break-word;
8
+
9
+ &__content-wrapper {
10
+ display: grid;
11
+ gap: var(--Prompt-gap, var(--size-16));
12
+ grid-template-columns: auto 1fr;
13
+ width: 100%;
14
+ }
15
+
16
+ &__media-wrapper {
17
+ align-self: flex-start;
18
+ padding-top: calc(var(--size-4) - 1px);
19
+
20
+ .tw-icon-tags,
21
+ .tw-icon-confetti {
22
+ color: var(--color-sentiment-content-primary);
23
+ }
24
+ }
25
+
26
+ &__actions-wrapper {
27
+ display: flex;
28
+ flex-wrap: wrap;
29
+ gap: var(--Prompt-actions-gap, var(--size-8));
30
+ grid-column-start: 2;
31
+
32
+ @media (--screen-md-max) {
33
+ grid-column: span 2;
34
+ width: 100%;
35
+ }
36
+ }
37
+ }
@@ -0,0 +1,70 @@
1
+ import { Cross } from '@transferwise/icons';
2
+ import { clsx } from 'clsx';
3
+ import SentimentSurface, { Sentiment } from '../../sentimentSurface';
4
+ import IconButton from '../../iconButton';
5
+ import { useIntl } from 'react-intl';
6
+ import closeBtnMessages from '../../common/closeButton/CloseButton.messages';
7
+ import { ReactNode } from 'react';
8
+
9
+ export type PrimitivePromptProps = {
10
+ /**
11
+ * The sentiment determines the colour scheme
12
+ * @default success
13
+ */
14
+ sentiment?: Sentiment;
15
+ /**
16
+ * Media to be displayed on the prompt (icon/image/etc).
17
+ */
18
+ media: ReactNode;
19
+ /**
20
+ * Any actions to be displayed on the prompt.
21
+ */
22
+ actions?: ReactNode;
23
+ /**
24
+ * Handler called when the close button is clicked. If not provided, then the close button is hidden.
25
+ */
26
+ onDismiss?: () => void;
27
+ id?: string;
28
+ className?: string;
29
+ 'data-testid'?: string;
30
+ children: ReactNode;
31
+ };
32
+
33
+ /**
34
+ * PrimitivePrompt is a low-level component that provides the structure, sentiment support and styling for various prompts.
35
+ * Uses several css variables to handle styling from within the consuming component, e.g. --Prompt-padding. */
36
+ export const PrimitivePrompt = ({
37
+ sentiment = 'success',
38
+ media,
39
+ actions,
40
+ onDismiss,
41
+ className,
42
+ children,
43
+ ...restProps
44
+ }: PrimitivePromptProps) => {
45
+ const intl = useIntl();
46
+
47
+ return (
48
+ <SentimentSurface
49
+ sentiment={sentiment}
50
+ className={clsx('wds-prompt', `wds-prompt--${sentiment}`, className)}
51
+ {...restProps}
52
+ >
53
+ <div className="wds-prompt__content-wrapper">
54
+ <div className={clsx('wds-prompt__media-wrapper')}>{media}</div>
55
+ {children}
56
+ {actions && <div className="wds-prompt__actions-wrapper">{actions}</div>}
57
+ </div>
58
+ {onDismiss && (
59
+ <IconButton
60
+ size={24}
61
+ priority="secondary"
62
+ aria-label={intl.formatMessage(closeBtnMessages.ariaLabel)}
63
+ onClick={onDismiss}
64
+ >
65
+ <Cross />
66
+ </IconButton>
67
+ )}
68
+ </SentimentSurface>
69
+ );
70
+ };
@@ -0,0 +1,2 @@
1
+ export type { PrimitivePromptProps } from './PrimitivePrompt';
2
+ export { PrimitivePrompt } from './PrimitivePrompt';
@@ -6,7 +6,7 @@ import { fn } from 'storybook/test';
6
6
  const meta = {
7
7
  component: RadioGroup,
8
8
  title: 'Forms/RadioGroup/tests',
9
- tags: ['!autodocs'],
9
+ tags: ['!autodocs', '!manifest'],
10
10
  args: {
11
11
  selectedValue: 'radio-2',
12
12
  name: 'radio-group',
@@ -22,7 +22,7 @@ const screenModes: Theming['screenMode'][] = ['light', 'dark'];
22
22
  export default {
23
23
  component: SentimentSurface,
24
24
  title: 'Foundations/SentimentSurface/Tests',
25
- tags: ['!autodocs'],
25
+ tags: ['!autodocs', '!manifest'],
26
26
  } satisfies Meta<typeof SentimentSurface>;
27
27
 
28
28
  type Story = StoryObj<typeof SentimentSurface>;
@@ -13,7 +13,7 @@ export default {
13
13
  title: 'Dialogs/Snackbar/Tests',
14
14
  component: Snackbar,
15
15
  argTypes: {},
16
- tags: ['!autodocs'],
16
+ tags: ['!autodocs', '!manifest'],
17
17
  };
18
18
 
19
19
  const launchSnackbar = async (canvasElement: HTMLElement) => {
@@ -27,6 +27,7 @@ const STEPS = [
27
27
  const meta = {
28
28
  component: Stepper,
29
29
  title: 'Navigation/Stepper/tests',
30
+ tags: ['!manifest'],
30
31
  argTypes: {
31
32
  activeStep: {
32
33
  control: 'radio',
@@ -5,6 +5,7 @@ import Summary, { type SummaryProps } from '.';
5
5
  export default {
6
6
  component: Summary,
7
7
  title: 'Content/Summary/tests',
8
+ tags: ['deprecated', '!manifest'],
8
9
  };
9
10
 
10
11
  export const LongText = () => {
@@ -6,6 +6,7 @@ import Title from './Title';
6
6
  export default {
7
7
  component: Title,
8
8
  title: 'Typography/Title/Tests',
9
+ tags: ['!autodocs', '!manifest'],
9
10
  args: {
10
11
  children: lorem1000.replaceAll(' ', ''),
11
12
  },
@@ -7,6 +7,7 @@ import { Field } from '../field/Field';
7
7
  const meta = {
8
8
  component: Upload,
9
9
  title: 'Forms/Upload/Tests',
10
+ tags: ['!manifest'],
10
11
  argTypes: {
11
12
  maxSize: {
12
13
  control: {
@@ -8,6 +8,7 @@ import { userEvent } from 'storybook/test';
8
8
 
9
9
  const meta: Meta<typeof UploadInput> = {
10
10
  title: 'Forms/UploadInput/Tests',
11
+ tags: ['!manifest'],
11
12
  component: UploadInput,
12
13
  };
13
14
  export default meta;
@@ -27,7 +27,7 @@ DescribedButton.displayName = 'DescribedButton';
27
27
  export default {
28
28
  component: DescribedButton,
29
29
  title: 'HoCs/withId',
30
- tags: ['docs-only', '!manifest'],
30
+ tags: ['!manifest'],
31
31
  } satisfies Meta<typeof withId>;
32
32
 
33
33
  export const WithoutId: Story = {};