@transferwise/components 0.0.0-experimental-d16bb5a → 0.0.0-experimental-fe2498c

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 (64) hide show
  1. package/build/field/Field.js +11 -0
  2. package/build/field/Field.js.map +1 -1
  3. package/build/field/Field.mjs +11 -0
  4. package/build/field/Field.mjs.map +1 -1
  5. package/build/index.js +99 -99
  6. package/build/index.mjs +25 -25
  7. package/build/inputs/SelectInput.js +4 -36
  8. package/build/inputs/SelectInput.js.map +1 -1
  9. package/build/inputs/SelectInput.mjs +5 -37
  10. package/build/inputs/SelectInput.mjs.map +1 -1
  11. package/build/inputs/_BottomSheet.js +2 -5
  12. package/build/inputs/_BottomSheet.js.map +1 -1
  13. package/build/inputs/_BottomSheet.mjs +3 -6
  14. package/build/inputs/_BottomSheet.mjs.map +1 -1
  15. package/build/inputs/_Popover.js +0 -2
  16. package/build/inputs/_Popover.js.map +1 -1
  17. package/build/inputs/_Popover.mjs +0 -2
  18. package/build/inputs/_Popover.mjs.map +1 -1
  19. package/build/listItem/Prompt/ListItemPrompt.js +11 -0
  20. package/build/listItem/Prompt/ListItemPrompt.js.map +1 -1
  21. package/build/listItem/Prompt/ListItemPrompt.mjs +11 -0
  22. package/build/listItem/Prompt/ListItemPrompt.mjs.map +1 -1
  23. package/build/main.css +6 -0
  24. package/build/styles/main.css +6 -0
  25. package/build/styles/prompt/ActionPrompt/ActionPrompt.css +3 -0
  26. package/build/styles/prompt/InfoPrompt/InfoPrompt.css +3 -0
  27. package/build/typeahead/Typeahead.js +11 -0
  28. package/build/typeahead/Typeahead.js.map +1 -1
  29. package/build/typeahead/Typeahead.mjs +11 -0
  30. package/build/typeahead/Typeahead.mjs.map +1 -1
  31. package/build/types/inputs/SelectInput.d.ts +1 -2
  32. package/build/types/inputs/SelectInput.d.ts.map +1 -1
  33. package/build/types/inputs/_BottomSheet.d.ts.map +1 -1
  34. package/build/types/inputs/_Popover.d.ts.map +1 -1
  35. package/build/types/prompt/ActionPrompt/ActionPrompt.d.ts +31 -0
  36. package/build/types/prompt/ActionPrompt/ActionPrompt.d.ts.map +1 -0
  37. package/build/types/prompt/ActionPrompt/index.d.ts +3 -0
  38. package/build/types/prompt/ActionPrompt/index.d.ts.map +1 -0
  39. package/build/types/prompt/InfoPrompt/InfoPrompt.d.ts +23 -0
  40. package/build/types/prompt/InfoPrompt/InfoPrompt.d.ts.map +1 -0
  41. package/build/types/prompt/InfoPrompt/index.d.ts +3 -0
  42. package/build/types/prompt/InfoPrompt/index.d.ts.map +1 -0
  43. package/build/types/prompt/index.d.ts +4 -0
  44. package/build/types/prompt/index.d.ts.map +1 -1
  45. package/package.json +3 -4
  46. package/src/inputs/SelectInput.spec.tsx +7 -57
  47. package/src/inputs/SelectInput.story.tsx +0 -68
  48. package/src/inputs/SelectInput.tsx +14 -71
  49. package/src/inputs/_BottomSheet.tsx +4 -7
  50. package/src/inputs/_Popover.tsx +0 -2
  51. package/src/main.css +6 -0
  52. package/src/main.less +2 -0
  53. package/src/moneyInput/MoneyInput.spec.tsx +7 -26
  54. package/src/prompt/ActionPrompt/ActionPrompt.css +3 -0
  55. package/src/prompt/ActionPrompt/ActionPrompt.less +3 -0
  56. package/src/prompt/ActionPrompt/ActionPrompt.story.tsx +174 -0
  57. package/src/prompt/ActionPrompt/ActionPrompt.tsx +109 -0
  58. package/src/prompt/ActionPrompt/index.ts +2 -0
  59. package/src/prompt/InfoPrompt/InfoPrompt.css +3 -0
  60. package/src/prompt/InfoPrompt/InfoPrompt.less +3 -0
  61. package/src/prompt/InfoPrompt/InfoPrompt.story.tsx +216 -0
  62. package/src/prompt/InfoPrompt/InfoPrompt.tsx +92 -0
  63. package/src/prompt/InfoPrompt/index.ts +2 -0
  64. package/src/prompt/index.ts +8 -0
@@ -0,0 +1,174 @@
1
+ import { Bank } from '@transferwise/icons';
2
+ import { ActionPrompt } from './ActionPrompt';
3
+
4
+ export default {
5
+ title: 'Prompts/ActionPrompt',
6
+ component: ActionPrompt,
7
+ tags: ['early-access'],
8
+ };
9
+
10
+ export const AllSentiments = () => {
11
+ return (
12
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 16 }}>
13
+ <ActionPrompt
14
+ sentiment="negative"
15
+ title="Title"
16
+ description="Description"
17
+ actionPrimary={{ label: 'Primary', onClick: () => {} }}
18
+ actionSecondary={{ label: 'Secondary', onClick: () => {} }}
19
+ onDismiss={() => {}}
20
+ />
21
+ <ActionPrompt
22
+ sentiment="negative"
23
+ title="Title"
24
+ description="Description"
25
+ actionPrimary={{ label: 'Primary', onClick: () => {} }}
26
+ actionSecondary={{ label: 'Secondary', onClick: () => {} }}
27
+ />
28
+ <ActionPrompt
29
+ sentiment="warning"
30
+ title="Title"
31
+ description="Description"
32
+ actionPrimary={{ label: 'Primary', onClick: () => {} }}
33
+ actionSecondary={{ label: 'Secondary', onClick: () => {} }}
34
+ onDismiss={() => {}}
35
+ />
36
+ <ActionPrompt
37
+ sentiment="warning"
38
+ title="Title"
39
+ description="Description"
40
+ actionPrimary={{ label: 'Primary', onClick: () => {} }}
41
+ actionSecondary={{ label: 'Secondary', onClick: () => {} }}
42
+ />
43
+ <ActionPrompt
44
+ sentiment="neutral"
45
+ title="Title"
46
+ description="Description"
47
+ actionPrimary={{ label: 'Primary', onClick: () => {} }}
48
+ actionSecondary={{ label: 'Secondary', onClick: () => {} }}
49
+ onDismiss={() => {}}
50
+ />
51
+ <ActionPrompt
52
+ sentiment="neutral"
53
+ title="Title"
54
+ description="Description"
55
+ actionPrimary={{ label: 'Primary', onClick: () => {} }}
56
+ actionSecondary={{ label: 'Secondary', onClick: () => {} }}
57
+ />
58
+ <ActionPrompt
59
+ sentiment="success"
60
+ title="Title"
61
+ description="Description"
62
+ actionPrimary={{ label: 'Primary', onClick: () => {} }}
63
+ actionSecondary={{ label: 'Secondary', onClick: () => {} }}
64
+ onDismiss={() => {}}
65
+ />
66
+ <ActionPrompt
67
+ sentiment="success"
68
+ title="Title"
69
+ description="Description"
70
+ actionPrimary={{ label: 'Primary', onClick: () => {} }}
71
+ actionSecondary={{ label: 'Secondary', onClick: () => {} }}
72
+ />
73
+ <ActionPrompt
74
+ sentiment="proposition"
75
+ title="Title"
76
+ description="Description"
77
+ actionPrimary={{ label: 'Primary', onClick: () => {} }}
78
+ actionSecondary={{ label: 'Secondary', onClick: () => {} }}
79
+ onDismiss={() => {}}
80
+ />
81
+ <ActionPrompt
82
+ sentiment="proposition"
83
+ title="Title"
84
+ description="Description"
85
+ actionPrimary={{ label: 'Primary', onClick: () => {} }}
86
+ actionSecondary={{ label: 'Secondary', onClick: () => {} }}
87
+ />
88
+ </div>
89
+ );
90
+ };
91
+
92
+ export const PrimaryActionOnly = () => {
93
+ return (
94
+ <div style={{ display: 'flex', flexDirection: 'column', gap: 16, maxWidth: 340 }}>
95
+ <ActionPrompt
96
+ sentiment="success"
97
+ title="Payment successful"
98
+ description="Your money is on its way"
99
+ actionPrimary={{ label: 'View details', onClick: () => {} }}
100
+ onDismiss={() => {}}
101
+ />
102
+ <ActionPrompt
103
+ sentiment="negative"
104
+ title="Payment failed"
105
+ description="Please try again"
106
+ actionPrimary={{ label: 'Retry', onClick: () => {} }}
107
+ onDismiss={() => {}}
108
+ />
109
+ </div>
110
+ );
111
+ };
112
+
113
+ export const CustomMedia = () => {
114
+ return (
115
+ <div style={{ display: 'flex', flexDirection: 'column', gap: 16, maxWidth: 340 }}>
116
+ <ActionPrompt
117
+ sentiment="negative"
118
+ title="Special offer!"
119
+ description="Invite a friend and get £50"
120
+ media={{ avatar: { imgSrc: '../../tapestry-01.png', badge: { status: 'negative' } } }}
121
+ actionPrimary={{ label: 'Invite now', onClick: () => {} }}
122
+ actionSecondary={{ label: 'Maybe later', onClick: () => {} }}
123
+ onDismiss={() => {}}
124
+ />
125
+ <ActionPrompt
126
+ sentiment="warning"
127
+ title="Special offer!"
128
+ description="Invite a friend and get £50"
129
+ media={{ avatar: { asset: <Bank />, badge: { status: 'warning' } } }}
130
+ actionPrimary={{ label: 'Invite now', onClick: () => {} }}
131
+ actionSecondary={{ label: 'Maybe later', onClick: () => {} }}
132
+ onDismiss={() => {}}
133
+ />
134
+ <ActionPrompt
135
+ sentiment="success"
136
+ title="Special offer!"
137
+ description="Invite a friend and get £50"
138
+ media={{ avatar: { profileName: 'John Doe', badge: { status: 'success' } } }}
139
+ actionPrimary={{ label: 'Invite now', onClick: () => {} }}
140
+ actionSecondary={{ label: 'Maybe later', onClick: () => {} }}
141
+ onDismiss={() => {}}
142
+ />
143
+ </div>
144
+ );
145
+ };
146
+
147
+ export const WithLinks = () => {
148
+ return (
149
+ <div style={{ display: 'flex', flexDirection: 'column', gap: 16, maxWidth: 340 }}>
150
+ <ActionPrompt
151
+ sentiment="neutral"
152
+ title="Update available"
153
+ description="A new version is ready"
154
+ actionPrimary={{ label: 'Update now', href: '#update' }}
155
+ actionSecondary={{ label: 'Release notes', href: '#notes', target: '_blank' }}
156
+ onDismiss={() => {}}
157
+ />
158
+ </div>
159
+ );
160
+ };
161
+
162
+ export const WithoutDescription = () => {
163
+ return (
164
+ <div style={{ display: 'flex', flexDirection: 'column', gap: 16, maxWidth: 340 }}>
165
+ <ActionPrompt
166
+ sentiment="warning"
167
+ title="Session expiring soon"
168
+ actionPrimary={{ label: 'Stay logged in', onClick: () => {} }}
169
+ actionSecondary={{ label: 'Log out', onClick: () => {} }}
170
+ onDismiss={() => {}}
171
+ />
172
+ </div>
173
+ );
174
+ };
@@ -0,0 +1,109 @@
1
+ import { ReactNode } from 'react';
2
+ import { clsx } from 'clsx';
3
+
4
+ import StatusIcon from '../../statusIcon';
5
+ import Body from '../../body';
6
+ import Button from '../../button';
7
+ import { Typography } from '../../common';
8
+ import Title from '../../title';
9
+ import AvatarView, { AvatarViewProps } from '../../avatarView';
10
+ import Image from '../../image';
11
+ import { ButtonProps } from '../../button/Button.types';
12
+ import { PrimitivePrompt } from '../PrimitivePrompt';
13
+ import { SentimentSurfaceProps } from '../../sentimentSurface';
14
+ import { BadgeAssetsProps } from '../../badge';
15
+
16
+ export type ActionPromptProps = {
17
+ sentiment?: SentimentSurfaceProps['sentiment'];
18
+ title: ReactNode;
19
+ description?: ReactNode;
20
+ onDismiss?: () => void;
21
+ media?: {
22
+ imgSrc?: string;
23
+ avatar: Pick<AvatarViewProps, 'imgSrc' | 'profileName' | 'profileType'> & {
24
+ asset?: AvatarViewProps['children'];
25
+ badge?: Pick<BadgeAssetsProps, 'flagCode' | 'status'>;
26
+ };
27
+ 'aria-label'?: string;
28
+ };
29
+ actionPrimary: Pick<ButtonProps, 'onClick' | 'href' | 'target'> & {
30
+ label: ButtonProps['children'];
31
+ };
32
+ actionSecondary?: Pick<ButtonProps, 'onClick' | 'href' | 'target'> & {
33
+ label: ButtonProps['children'];
34
+ };
35
+ id?: string;
36
+ className?: string;
37
+ 'data-testid'?: string;
38
+ };
39
+
40
+ export const ActionPrompt = ({
41
+ sentiment = 'neutral',
42
+ title,
43
+ description,
44
+ onDismiss,
45
+ media,
46
+ actionPrimary,
47
+ actionSecondary,
48
+ id,
49
+ className,
50
+ 'data-testid': testId,
51
+ }: ActionPromptProps) => {
52
+ const renderMedia = () => {
53
+ if (media?.imgSrc) {
54
+ return <Image src={media.imgSrc} alt={media['aria-label'] ?? ''} />;
55
+ }
56
+ if (media?.avatar) {
57
+ return (
58
+ <AvatarView {...media.avatar} size={48}>
59
+ {media.avatar.asset}
60
+ </AvatarView>
61
+ );
62
+ }
63
+ return <StatusIcon size={48} sentiment={sentiment === 'proposition' ? 'success' : sentiment} />;
64
+ };
65
+
66
+ return (
67
+ <PrimitivePrompt
68
+ id={id}
69
+ sentiment={sentiment}
70
+ data-testid={testId}
71
+ className={clsx('wds-action-prompt', `wds-action-prompt--${sentiment}`, className)}
72
+ media={renderMedia()}
73
+ actions={
74
+ <>
75
+ {actionSecondary && (
76
+ // @ts-expect-error later
77
+ <Button
78
+ size="md"
79
+ priority="secondary"
80
+ href={actionSecondary.href}
81
+ v2
82
+ onClick={actionSecondary.onClick}
83
+ >
84
+ {actionSecondary.label}
85
+ </Button>
86
+ )}
87
+ {/* @ts-expect-error later */}
88
+ <Button
89
+ v2
90
+ size="md"
91
+ priority="primary"
92
+ href={actionPrimary.href}
93
+ onClick={actionPrimary.onClick}
94
+ >
95
+ {actionPrimary.label}
96
+ </Button>
97
+ </>
98
+ }
99
+ onDismiss={onDismiss}
100
+ >
101
+ <div>
102
+ <Title type={Typography.TITLE_BODY}>{title}</Title>
103
+ {description && <Body>{description}</Body>}
104
+ </div>
105
+ </PrimitivePrompt>
106
+ );
107
+ };
108
+
109
+ export default ActionPrompt;
@@ -0,0 +1,2 @@
1
+ export type { ActionPromptProps } from './ActionPrompt';
2
+ export { ActionPrompt } from './ActionPrompt';
@@ -0,0 +1,3 @@
1
+ .wds-info-prompt {
2
+ --Prompt-gap: calc(var(--size-12) / 2);
3
+ }
@@ -0,0 +1,3 @@
1
+ .wds-info-prompt {
2
+ --Prompt-gap: calc(var(--size-12) / 2);
3
+ }
@@ -0,0 +1,216 @@
1
+ import { InfoPrompt } from './InfoPrompt';
2
+
3
+ export default {
4
+ title: 'Prompts/InfoPrompt',
5
+ component: InfoPrompt,
6
+ };
7
+
8
+ export const AllSentiments = () => {
9
+ return (
10
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 16 }}>
11
+ {/* Positive */}
12
+ <InfoPrompt
13
+ sentiment="positive"
14
+ title="Title (Positive)"
15
+ description="Description"
16
+ primaryAction={{ label: 'Link/Action (Button)', as: 'button', onClick: () => {} }}
17
+ onClose={() => {}}
18
+ />
19
+ <InfoPrompt
20
+ sentiment="positive"
21
+ title="Title (Positive)"
22
+ description="Description"
23
+ primaryAction={{ label: 'Link/Action (Link)', as: 'a', href: '#' }}
24
+ />
25
+
26
+ {/* Warning */}
27
+ <InfoPrompt
28
+ sentiment="warning"
29
+ title="Title (Warning)"
30
+ description="Description"
31
+ primaryAction={{ label: 'Link/Action (Button)', as: 'button', onClick: () => {} }}
32
+ onClose={() => {}}
33
+ />
34
+ <InfoPrompt
35
+ sentiment="warning"
36
+ title="Title (Warning)"
37
+ description="Description"
38
+ primaryAction={{ label: 'Link/Action (Link)', as: 'a', href: '#' }}
39
+ />
40
+
41
+ {/* Negative */}
42
+ <InfoPrompt
43
+ sentiment="negative"
44
+ title="Title (Negative)"
45
+ description="Description"
46
+ primaryAction={{ label: 'Link/Action (Button)', as: 'button', onClick: () => {} }}
47
+ onClose={() => {}}
48
+ />
49
+ <InfoPrompt
50
+ sentiment="negative"
51
+ title="Title (Negative)"
52
+ description="Description"
53
+ primaryAction={{ label: 'Link/Action (Link)', as: 'a', href: '#' }}
54
+ />
55
+
56
+ {/* Neutral */}
57
+ <InfoPrompt
58
+ sentiment="neutral"
59
+ title="Title (Neutral)"
60
+ description="Description"
61
+ primaryAction={{ label: 'Link/Action (Button)', as: 'button', onClick: () => {} }}
62
+ onClose={() => {}}
63
+ />
64
+ <InfoPrompt
65
+ sentiment="neutral"
66
+ title="Title (Neutral)"
67
+ description="Description"
68
+ primaryAction={{ label: 'Link/Action (Link)', as: 'a', href: '#' }}
69
+ />
70
+
71
+ {/* Proposition */}
72
+ <InfoPrompt
73
+ sentiment="proposition"
74
+ title="Title (Proposition)"
75
+ description="Description"
76
+ primaryAction={{ label: 'Link/Action (Button)', as: 'button', onClick: () => {} }}
77
+ onClose={() => {}}
78
+ />
79
+ <InfoPrompt
80
+ sentiment="proposition"
81
+ title="Title (Proposition)"
82
+ description="Description"
83
+ primaryAction={{ label: 'Link/Action (Link)', as: 'a', href: '#' }}
84
+ />
85
+ </div>
86
+ );
87
+ };
88
+
89
+ export const TitleAndActionOnly = () => {
90
+ return (
91
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 16 }}>
92
+ <InfoPrompt
93
+ sentiment="positive"
94
+ title="Title (Positive)"
95
+ description=""
96
+ primaryAction={{ label: 'Link/Action (Button)', as: 'button', onClick: () => {} }}
97
+ onClose={() => {}}
98
+ />
99
+ <InfoPrompt
100
+ sentiment="warning"
101
+ title="Title (Warning)"
102
+ description=""
103
+ primaryAction={{ label: 'Link/Action (Button)', as: 'button', onClick: () => {} }}
104
+ onClose={() => {}}
105
+ />
106
+ <InfoPrompt
107
+ sentiment="negative"
108
+ title="Title (Negative)"
109
+ description=""
110
+ primaryAction={{ label: 'Link/Action (Button)', as: 'button', onClick: () => {} }}
111
+ onClose={() => {}}
112
+ />
113
+ <InfoPrompt
114
+ sentiment="neutral"
115
+ title="Title (Neutral)"
116
+ description=""
117
+ primaryAction={{ label: 'Link/Action (Button)', as: 'button', onClick: () => {} }}
118
+ onClose={() => {}}
119
+ />
120
+ <InfoPrompt
121
+ sentiment="proposition"
122
+ title="Title (Proposition)"
123
+ description=""
124
+ primaryAction={{ label: 'Link/Action (Button)', as: 'button', onClick: () => {} }}
125
+ onClose={() => {}}
126
+ />
127
+ </div>
128
+ );
129
+ };
130
+
131
+ export const DescriptionOnly = () => {
132
+ return (
133
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 16 }}>
134
+ <InfoPrompt sentiment="positive" description="Description" onClose={() => {}} />
135
+ <InfoPrompt sentiment="positive" description="Description" />
136
+ <InfoPrompt sentiment="warning" description="Description" onClose={() => {}} />
137
+ <InfoPrompt sentiment="warning" description="Description" />
138
+ <InfoPrompt sentiment="negative" description="Description" onClose={() => {}} />
139
+ <InfoPrompt sentiment="negative" description="Description" />
140
+ <InfoPrompt sentiment="neutral" description="Description" onClose={() => {}} />
141
+ <InfoPrompt sentiment="neutral" description="Description" />
142
+ <InfoPrompt sentiment="proposition" description="Description" onClose={() => {}} />
143
+ <InfoPrompt sentiment="proposition" description="Description" />
144
+ </div>
145
+ );
146
+ };
147
+
148
+ export const TitleAndDescriptionOnly = () => {
149
+ return (
150
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 16 }}>
151
+ <InfoPrompt
152
+ sentiment="positive"
153
+ title="Title (Positive)"
154
+ description="Description"
155
+ onClose={() => {}}
156
+ />
157
+ <InfoPrompt sentiment="positive" title="Title (Positive)" description="Description" />
158
+ <InfoPrompt
159
+ sentiment="warning"
160
+ title="Title (Warning)"
161
+ description="Description"
162
+ onClose={() => {}}
163
+ />
164
+ <InfoPrompt sentiment="warning" title="Title (Warning)" description="Description" />
165
+ <InfoPrompt
166
+ sentiment="negative"
167
+ title="Title (Negative)"
168
+ description="Description"
169
+ onClose={() => {}}
170
+ />
171
+ <InfoPrompt sentiment="negative" title="Title (Negative)" description="Description" />
172
+ <InfoPrompt
173
+ sentiment="neutral"
174
+ title="Title (Neutral)"
175
+ description="Description"
176
+ onClose={() => {}}
177
+ />
178
+ <InfoPrompt sentiment="neutral" title="Title (Neutral)" description="Description" />
179
+ <InfoPrompt
180
+ sentiment="proposition"
181
+ title="Title (Proposition)"
182
+ description="Description"
183
+ onClose={() => {}}
184
+ />
185
+ <InfoPrompt sentiment="proposition" title="Title (Proposition)" description="Description" />
186
+ </div>
187
+ );
188
+ };
189
+
190
+ export const PrimaryActionAsButton = () => {
191
+ return (
192
+ <div style={{ display: 'flex', flexDirection: 'column', gap: 16, maxWidth: 400 }}>
193
+ <InfoPrompt
194
+ sentiment="neutral"
195
+ title="Action with Button"
196
+ description="This example uses as='button' for the primary action"
197
+ primaryAction={{ label: 'Click me', as: 'button', onClick: () => alert('Button clicked!') }}
198
+ onClose={() => {}}
199
+ />
200
+ </div>
201
+ );
202
+ };
203
+
204
+ export const PrimaryActionAsLink = () => {
205
+ return (
206
+ <div style={{ display: 'flex', flexDirection: 'column', gap: 16, maxWidth: 400 }}>
207
+ <InfoPrompt
208
+ sentiment="neutral"
209
+ title="Action with Link"
210
+ description="This example uses as='a' (anchor) for the primary action"
211
+ primaryAction={{ label: 'Visit page', as: 'a', href: 'https://wise.com', target: '_blank' }}
212
+ onClose={() => {}}
213
+ />
214
+ </div>
215
+ );
216
+ };
@@ -0,0 +1,92 @@
1
+ import { ReactNode, HTMLAttributes } from 'react';
2
+ import { clsx } from 'clsx';
3
+
4
+ import StatusIcon from '../../statusIcon';
5
+ import Body from '../../body';
6
+ import Button from '../../button';
7
+ import { Typography } from '../../common';
8
+ import Title from '../../title';
9
+ import { ButtonProps } from '../../button/Button.types';
10
+ import { PrimitivePrompt } from '../PrimitivePrompt';
11
+
12
+ type PrimaryAction = Pick<ButtonProps, 'onClick' | 'href' | 'target'> & {
13
+ label: ButtonProps['children'];
14
+ as?: 'button' | 'a';
15
+ };
16
+
17
+ export type InfoPromptProps = Omit<HTMLAttributes<HTMLDivElement>, 'title'> & {
18
+ sentiment?: 'positive' | 'neutral' | 'warning' | 'negative' | 'proposition';
19
+ title?: ReactNode;
20
+ description: ReactNode;
21
+ onClose?: () => void;
22
+ media?: {
23
+ asset: ReactNode;
24
+ 'aria-label': string;
25
+ };
26
+ primaryAction?: PrimaryAction;
27
+ id?: string;
28
+ className?: string;
29
+ 'data-testid'?: string;
30
+ };
31
+
32
+ export const InfoPrompt = ({
33
+ sentiment = 'neutral',
34
+ title,
35
+ description,
36
+ onClose,
37
+ media,
38
+ primaryAction,
39
+ id,
40
+ className,
41
+ 'data-testid': testId,
42
+ ...restProps
43
+ }: InfoPromptProps) => {
44
+ const surfaceSentiment = sentiment === 'positive' ? 'success' : sentiment;
45
+
46
+ const renderMedia = () => {
47
+ if (media?.asset) {
48
+ return media.asset;
49
+ }
50
+ return (
51
+ <StatusIcon
52
+ size={48}
53
+ sentiment={surfaceSentiment === 'proposition' ? 'success' : surfaceSentiment}
54
+ />
55
+ );
56
+ };
57
+
58
+ return (
59
+ <PrimitivePrompt
60
+ id={id}
61
+ sentiment={surfaceSentiment}
62
+ data-testid={testId}
63
+ className={clsx('wds-info-prompt', `wds-info-prompt--${sentiment}`, className)}
64
+ media={renderMedia()}
65
+ actions={
66
+ primaryAction ? (
67
+ // @ts-expect-error later
68
+ <Button
69
+ v2
70
+ size="md"
71
+ priority="tertiary"
72
+ as={primaryAction.as}
73
+ href={primaryAction.href}
74
+ target={primaryAction.target}
75
+ onClick={primaryAction.onClick}
76
+ >
77
+ {primaryAction.label}
78
+ </Button>
79
+ ) : undefined
80
+ }
81
+ onDismiss={onClose}
82
+ {...restProps}
83
+ >
84
+ <div>
85
+ {title && <Title type={Typography.TITLE_BODY}>{title}</Title>}
86
+ <Body>{description}</Body>
87
+ </div>
88
+ </PrimitivePrompt>
89
+ );
90
+ };
91
+
92
+ export default InfoPrompt;
@@ -0,0 +1,2 @@
1
+ export type { InfoPromptProps } from './InfoPrompt';
2
+ export { InfoPrompt } from './InfoPrompt';
@@ -4,3 +4,11 @@
4
4
  // InlinePrompt
5
5
  export type { InlinePromptProps } from './InlinePrompt';
6
6
  export { InlinePrompt } from './InlinePrompt';
7
+
8
+ // ActionPrompt
9
+ export type { ActionPromptProps } from './ActionPrompt';
10
+ export { ActionPrompt } from './ActionPrompt';
11
+
12
+ // InfoPrompt
13
+ export type { InfoPromptProps } from './InfoPrompt';
14
+ export { InfoPrompt } from './InfoPrompt';