@transferwise/components 0.0.0-experimental-c8d90fc → 0.0.0-experimental-2118b34
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 +1 -1
- package/build/alert/Alert.js.map +1 -1
- package/build/alert/Alert.mjs +1 -1
- package/build/alert/Alert.mjs.map +1 -1
- package/build/chips/Chip.js +3 -11
- package/build/chips/Chip.js.map +1 -1
- package/build/chips/Chip.mjs +3 -11
- package/build/chips/Chip.mjs.map +1 -1
- package/build/field/Field.js +6 -3
- package/build/field/Field.js.map +1 -1
- package/build/field/Field.mjs +6 -3
- package/build/field/Field.mjs.map +1 -1
- package/build/inlineAlert/InlineAlert.js +1 -7
- package/build/inlineAlert/InlineAlert.js.map +1 -1
- package/build/inlineAlert/InlineAlert.mjs +1 -7
- package/build/inlineAlert/InlineAlert.mjs.map +1 -1
- package/build/main.css +9 -1
- package/build/progressBar/ProgressBar.js +1 -5
- package/build/progressBar/ProgressBar.js.map +1 -1
- package/build/progressBar/ProgressBar.mjs +1 -5
- package/build/progressBar/ProgressBar.mjs.map +1 -1
- package/build/select/Select.js +1 -7
- package/build/select/Select.js.map +1 -1
- package/build/select/Select.mjs +1 -7
- package/build/select/Select.mjs.map +1 -1
- package/build/styles/field/Field.css +5 -1
- package/build/styles/main.css +9 -1
- package/build/styles/typeahead/Typeahead.css +4 -0
- package/build/typeahead/Typeahead.js +18 -6
- package/build/typeahead/Typeahead.js.map +1 -1
- package/build/typeahead/Typeahead.mjs +18 -6
- package/build/typeahead/Typeahead.mjs.map +1 -1
- package/build/types/alert/Alert.d.ts +1 -1
- package/build/types/alert/Alert.d.ts.map +1 -1
- package/build/types/chips/Chip.d.ts.map +1 -1
- package/build/types/field/Field.d.ts +8 -4
- package/build/types/field/Field.d.ts.map +1 -1
- package/build/types/inlineAlert/InlineAlert.d.ts +1 -7
- package/build/types/inlineAlert/InlineAlert.d.ts.map +1 -1
- package/build/types/progressBar/ProgressBar.d.ts.map +1 -1
- package/build/types/select/Select.d.ts.map +1 -1
- package/build/types/typeahead/Typeahead.d.ts +4 -4
- package/build/types/typeahead/Typeahead.d.ts.map +1 -1
- package/build/types/upload/Upload.d.ts +1 -1
- package/build/upload/Upload.js.map +1 -1
- package/build/upload/Upload.mjs.map +1 -1
- package/build/upload/steps/uploadImageStep/uploadImageStep.js +3 -3
- package/build/upload/steps/uploadImageStep/uploadImageStep.js.map +1 -1
- package/build/upload/steps/uploadImageStep/uploadImageStep.mjs +3 -3
- package/build/upload/steps/uploadImageStep/uploadImageStep.mjs.map +1 -1
- package/package.json +3 -3
- package/src/alert/Alert.spec.tsx +1 -1
- package/src/alert/Alert.tsx +2 -2
- package/src/chips/Chip.tsx +5 -14
- package/src/chips/__snapshots__/Chips.spec.tsx.snap +31 -29
- package/src/field/Field.css +5 -1
- package/src/field/Field.less +7 -2
- package/src/field/Field.spec.tsx +19 -3
- package/src/field/Field.story.tsx +18 -0
- package/src/field/Field.tsx +16 -5
- package/src/inlineAlert/InlineAlert.story.tsx +4 -0
- package/src/inlineAlert/InlineAlert.tsx +1 -7
- package/src/main.css +9 -1
- package/src/progressBar/ProgressBar.tsx +1 -6
- package/src/select/Select.tsx +1 -2
- package/src/typeahead/Typeahead.css +4 -0
- package/src/typeahead/Typeahead.less +5 -1
- package/src/typeahead/Typeahead.spec.tsx +1 -1
- package/src/typeahead/Typeahead.story.tsx +80 -3
- package/src/typeahead/Typeahead.tsx +28 -8
- package/src/upload/Upload.story.tsx +1 -1
- package/src/upload/Upload.tests.story.tsx +36 -1
- package/src/upload/Upload.tsx +1 -1
- package/src/upload/steps/uploadImageStep/uploadImageStep.tsx +3 -3
|
@@ -13,12 +13,12 @@ exports[`Chips Choice Chips renders as expected 1`] = `
|
|
|
13
13
|
role="radio"
|
|
14
14
|
tabindex="0"
|
|
15
15
|
>
|
|
16
|
-
<
|
|
16
|
+
<div
|
|
17
17
|
aria-hidden="false"
|
|
18
|
-
class="np-
|
|
18
|
+
class="np-text-body-default-bold"
|
|
19
19
|
>
|
|
20
20
|
Accounting
|
|
21
|
-
</
|
|
21
|
+
</div>
|
|
22
22
|
</div>
|
|
23
23
|
<div
|
|
24
24
|
aria-checked="true"
|
|
@@ -26,12 +26,12 @@ exports[`Chips Choice Chips renders as expected 1`] = `
|
|
|
26
26
|
role="radio"
|
|
27
27
|
tabindex="0"
|
|
28
28
|
>
|
|
29
|
-
<
|
|
29
|
+
<div
|
|
30
30
|
aria-hidden="false"
|
|
31
|
-
class="np-
|
|
31
|
+
class="np-text-body-default-bold"
|
|
32
32
|
>
|
|
33
33
|
Payroll
|
|
34
|
-
</
|
|
34
|
+
</div>
|
|
35
35
|
</div>
|
|
36
36
|
<div
|
|
37
37
|
aria-checked="false"
|
|
@@ -39,12 +39,12 @@ exports[`Chips Choice Chips renders as expected 1`] = `
|
|
|
39
39
|
role="radio"
|
|
40
40
|
tabindex="0"
|
|
41
41
|
>
|
|
42
|
-
<
|
|
42
|
+
<div
|
|
43
43
|
aria-hidden="false"
|
|
44
|
-
class="np-
|
|
44
|
+
class="np-text-body-default-bold"
|
|
45
45
|
>
|
|
46
46
|
Reporting
|
|
47
|
-
</
|
|
47
|
+
</div>
|
|
48
48
|
</div>
|
|
49
49
|
<div
|
|
50
50
|
aria-checked="false"
|
|
@@ -52,12 +52,12 @@ exports[`Chips Choice Chips renders as expected 1`] = `
|
|
|
52
52
|
role="radio"
|
|
53
53
|
tabindex="0"
|
|
54
54
|
>
|
|
55
|
-
<
|
|
55
|
+
<div
|
|
56
56
|
aria-hidden="false"
|
|
57
|
-
class="np-
|
|
57
|
+
class="np-text-body-default-bold"
|
|
58
58
|
>
|
|
59
59
|
Payments
|
|
60
|
-
</
|
|
60
|
+
</div>
|
|
61
61
|
</div>
|
|
62
62
|
</div>
|
|
63
63
|
</div>
|
|
@@ -76,12 +76,12 @@ exports[`Chips Filter Chips renders as expected 1`] = `
|
|
|
76
76
|
role="checkbox"
|
|
77
77
|
tabindex="0"
|
|
78
78
|
>
|
|
79
|
-
<
|
|
79
|
+
<div
|
|
80
80
|
aria-hidden="false"
|
|
81
|
-
class="np-
|
|
81
|
+
class="np-text-body-default-bold"
|
|
82
82
|
>
|
|
83
83
|
Accounting
|
|
84
|
-
</
|
|
84
|
+
</div>
|
|
85
85
|
</div>
|
|
86
86
|
<div
|
|
87
87
|
aria-checked="false"
|
|
@@ -89,12 +89,12 @@ exports[`Chips Filter Chips renders as expected 1`] = `
|
|
|
89
89
|
role="checkbox"
|
|
90
90
|
tabindex="0"
|
|
91
91
|
>
|
|
92
|
-
<
|
|
92
|
+
<div
|
|
93
93
|
aria-hidden="false"
|
|
94
|
-
class="np-
|
|
94
|
+
class="np-text-body-default-bold"
|
|
95
95
|
>
|
|
96
96
|
Payroll
|
|
97
|
-
</
|
|
97
|
+
</div>
|
|
98
98
|
</div>
|
|
99
99
|
<div
|
|
100
100
|
aria-checked="false"
|
|
@@ -102,12 +102,12 @@ exports[`Chips Filter Chips renders as expected 1`] = `
|
|
|
102
102
|
role="checkbox"
|
|
103
103
|
tabindex="0"
|
|
104
104
|
>
|
|
105
|
-
<
|
|
105
|
+
<div
|
|
106
106
|
aria-hidden="false"
|
|
107
|
-
class="np-
|
|
107
|
+
class="np-text-body-default-bold"
|
|
108
108
|
>
|
|
109
109
|
Reporting
|
|
110
|
-
</
|
|
110
|
+
</div>
|
|
111
111
|
</div>
|
|
112
112
|
<div
|
|
113
113
|
aria-checked="true"
|
|
@@ -115,20 +115,20 @@ exports[`Chips Filter Chips renders as expected 1`] = `
|
|
|
115
115
|
role="checkbox"
|
|
116
116
|
tabindex="-1"
|
|
117
117
|
>
|
|
118
|
-
<
|
|
119
|
-
aria-hidden="
|
|
120
|
-
class="np-
|
|
118
|
+
<div
|
|
119
|
+
aria-hidden="true"
|
|
120
|
+
class="np-text-body-default-bold"
|
|
121
121
|
>
|
|
122
122
|
Payments
|
|
123
|
-
</
|
|
123
|
+
</div>
|
|
124
124
|
<button
|
|
125
125
|
aria-label="Clear Payments"
|
|
126
|
-
class="np-close-button close btn-link text-no-decoration btn-unstyled
|
|
126
|
+
class="np-close-button close btn-link text-no-decoration btn-unstyled"
|
|
127
127
|
type="button"
|
|
128
128
|
>
|
|
129
129
|
<span
|
|
130
|
-
class="tw-icon tw-icon-cross "
|
|
131
|
-
data-testid="cross-icon"
|
|
130
|
+
class="tw-icon tw-icon-cross-circle-fill "
|
|
131
|
+
data-testid="cross-circle-fill-icon"
|
|
132
132
|
>
|
|
133
133
|
<svg
|
|
134
134
|
aria-hidden="true"
|
|
@@ -140,7 +140,9 @@ exports[`Chips Filter Chips renders as expected 1`] = `
|
|
|
140
140
|
width="16"
|
|
141
141
|
>
|
|
142
142
|
<path
|
|
143
|
-
|
|
143
|
+
clip-rule="evenodd"
|
|
144
|
+
d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10m-4.707-6.707L10.586 12 7.293 8.707l1.414-1.414L12 10.586l3.293-3.293 1.414 1.414L13.414 12l3.293 3.293-1.414 1.414L12 13.414l-3.293 3.293z"
|
|
145
|
+
fill-rule="evenodd"
|
|
144
146
|
/>
|
|
145
147
|
</svg>
|
|
146
148
|
</span>
|
package/src/field/Field.css
CHANGED
package/src/field/Field.less
CHANGED
package/src/field/Field.spec.tsx
CHANGED
|
@@ -71,7 +71,7 @@ describe('Field', () => {
|
|
|
71
71
|
expect(screen.getByLabelText(/Phone number/)).toHaveAttribute('aria-describedby');
|
|
72
72
|
});
|
|
73
73
|
|
|
74
|
-
it("should allow for
|
|
74
|
+
it("should allow for InlinePrompt's StatusIcon override via `messageIconLabel` prop", () => {
|
|
75
75
|
const customIconLabel = 'My custom icon label';
|
|
76
76
|
|
|
77
77
|
render(
|
|
@@ -86,8 +86,8 @@ describe('Field', () => {
|
|
|
86
86
|
</Field>,
|
|
87
87
|
);
|
|
88
88
|
|
|
89
|
-
expect(screen.
|
|
90
|
-
expect(screen.
|
|
89
|
+
expect(screen.queryByLabelText('Error:')).not.toBeInTheDocument();
|
|
90
|
+
expect(screen.getByLabelText(customIconLabel)).toBeInTheDocument();
|
|
91
91
|
});
|
|
92
92
|
|
|
93
93
|
it('should show or hide (Optional) suffix depending on required prop', () => {
|
|
@@ -147,4 +147,20 @@ describe('Field', () => {
|
|
|
147
147
|
const label = screen.getByText('Phone number');
|
|
148
148
|
await userEvent.click(label);
|
|
149
149
|
});
|
|
150
|
+
|
|
151
|
+
it('should show loading spinner when messageLoading is true', () => {
|
|
152
|
+
render(
|
|
153
|
+
<Field
|
|
154
|
+
label="Phone number"
|
|
155
|
+
message="Processing your request"
|
|
156
|
+
sentiment="neutral"
|
|
157
|
+
messageLoading
|
|
158
|
+
>
|
|
159
|
+
<Input />
|
|
160
|
+
</Field>,
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
expect(screen.getByTestId('InlinePrompt_ProcessIndicator')).toBeInTheDocument();
|
|
164
|
+
expect(screen.getByText('Processing your request')).toBeInTheDocument();
|
|
165
|
+
});
|
|
150
166
|
});
|
|
@@ -46,6 +46,7 @@ export const Basic = (args: FieldProps) => {
|
|
|
46
46
|
sentiment={Sentiment.NEGATIVE}
|
|
47
47
|
message="Validation error, please take a look"
|
|
48
48
|
messageIconLabel={args.messageIconLabel}
|
|
49
|
+
messageLoading={args.messageLoading}
|
|
49
50
|
>
|
|
50
51
|
<Input value={value} onChange={({ target }) => setValue(target.value)} />
|
|
51
52
|
</Field>
|
|
@@ -81,6 +82,7 @@ export const Basic = (args: FieldProps) => {
|
|
|
81
82
|
message={lorem10}
|
|
82
83
|
sentiment="negative"
|
|
83
84
|
messageIconLabel={args.messageIconLabel}
|
|
85
|
+
messageLoading={args.messageLoading}
|
|
84
86
|
>
|
|
85
87
|
<TextArea />
|
|
86
88
|
</Field>
|
|
@@ -109,6 +111,17 @@ export const WithStatusMessages = (args: FieldProps) => {
|
|
|
109
111
|
sentiment={Sentiment.POSITIVE}
|
|
110
112
|
message="Positive message"
|
|
111
113
|
messageIconLabel={args.messageIconLabel}
|
|
114
|
+
messageLoading={args.messageLoading}
|
|
115
|
+
>
|
|
116
|
+
<Input value={value} onChange={({ target }) => setValue(target.value)} />
|
|
117
|
+
</Field>
|
|
118
|
+
|
|
119
|
+
<Field
|
|
120
|
+
label="Text Input with Proposition Message"
|
|
121
|
+
sentiment="proposition"
|
|
122
|
+
message="Proposition message"
|
|
123
|
+
messageIconLabel={args.messageIconLabel}
|
|
124
|
+
messageLoading={args.messageLoading}
|
|
112
125
|
>
|
|
113
126
|
<Input value={value} onChange={({ target }) => setValue(target.value)} />
|
|
114
127
|
</Field>
|
|
@@ -118,6 +131,7 @@ export const WithStatusMessages = (args: FieldProps) => {
|
|
|
118
131
|
sentiment={Sentiment.WARNING}
|
|
119
132
|
message="Warning message"
|
|
120
133
|
messageIconLabel={args.messageIconLabel}
|
|
134
|
+
messageLoading={args.messageLoading}
|
|
121
135
|
>
|
|
122
136
|
<Input value={value} onChange={({ target }) => setValue(target.value)} />
|
|
123
137
|
</Field>
|
|
@@ -127,6 +141,7 @@ export const WithStatusMessages = (args: FieldProps) => {
|
|
|
127
141
|
sentiment={Sentiment.NEGATIVE}
|
|
128
142
|
message="This is a required field"
|
|
129
143
|
messageIconLabel={args.messageIconLabel}
|
|
144
|
+
messageLoading={args.messageLoading}
|
|
130
145
|
>
|
|
131
146
|
<Input value={value} onChange={({ target }) => setValue(target.value)} />
|
|
132
147
|
</Field>
|
|
@@ -138,6 +153,7 @@ export const WithStatusMessages = (args: FieldProps) => {
|
|
|
138
153
|
sentiment={Sentiment.NEGATIVE}
|
|
139
154
|
message="Validation error, please take a look"
|
|
140
155
|
messageIconLabel={args.messageIconLabel}
|
|
156
|
+
messageLoading={args.messageLoading}
|
|
141
157
|
>
|
|
142
158
|
<Input value={value} onChange={({ target }) => setValue(target.value)} />
|
|
143
159
|
</Field>
|
|
@@ -148,6 +164,7 @@ export const WithStatusMessages = (args: FieldProps) => {
|
|
|
148
164
|
hint="This is a helpful message"
|
|
149
165
|
error="Validation error, please take a look"
|
|
150
166
|
messageIconLabel={args.messageIconLabel}
|
|
167
|
+
messageLoading={args.messageLoading}
|
|
151
168
|
>
|
|
152
169
|
<Input value={value} onChange={({ target }) => setValue(target.value)} />
|
|
153
170
|
</Field>
|
|
@@ -157,6 +174,7 @@ export const WithStatusMessages = (args: FieldProps) => {
|
|
|
157
174
|
label="Text Input with Info under the field"
|
|
158
175
|
message="This is a helpful message"
|
|
159
176
|
messageIconLabel={args.messageIconLabel}
|
|
177
|
+
messageLoading={args.messageLoading}
|
|
160
178
|
>
|
|
161
179
|
<Input value={value} onChange={({ target }) => setValue(target.value)} />
|
|
162
180
|
</Field>
|
package/src/field/Field.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import { clsx } from 'clsx';
|
|
|
2
2
|
import { useId, useRef } from 'react';
|
|
3
3
|
|
|
4
4
|
import { Sentiment } from '../common';
|
|
5
|
-
import
|
|
5
|
+
import { InlinePrompt, type InlinePromptProps } from '../prompt';
|
|
6
6
|
import {
|
|
7
7
|
FieldLabelContextProvider,
|
|
8
8
|
InputDescribedByProvider,
|
|
@@ -21,14 +21,18 @@ export type FieldProps = {
|
|
|
21
21
|
hint?: React.ReactNode;
|
|
22
22
|
message?: React.ReactNode;
|
|
23
23
|
/**
|
|
24
|
-
* Override for the [
|
|
24
|
+
* Override for the [InlinePrompt icon's default, accessible name](/?path=/docs/other-statusicon-accessibility--docs)
|
|
25
25
|
* announced by the screen readers
|
|
26
26
|
* */
|
|
27
27
|
messageIconLabel?: string;
|
|
28
|
+
/**
|
|
29
|
+
* If true, shows a loading spinner in place of the message icon of the InlinePrompt
|
|
30
|
+
*/
|
|
31
|
+
messageLoading?: boolean;
|
|
28
32
|
description?: React.ReactNode;
|
|
29
33
|
/** @deprecated use `message` and `type={Sentiment.NEGATIVE}` prop instead */
|
|
30
34
|
error?: React.ReactNode;
|
|
31
|
-
sentiment?:
|
|
35
|
+
sentiment?: InlinePromptProps['sentiment'];
|
|
32
36
|
className?: string;
|
|
33
37
|
children?: React.ReactNode;
|
|
34
38
|
};
|
|
@@ -39,6 +43,7 @@ export const Field = ({
|
|
|
39
43
|
required = true,
|
|
40
44
|
message: propMessage,
|
|
41
45
|
messageIconLabel,
|
|
46
|
+
messageLoading,
|
|
42
47
|
hint,
|
|
43
48
|
description = hint,
|
|
44
49
|
sentiment: propType = Sentiment.NEUTRAL,
|
|
@@ -104,9 +109,15 @@ export const Field = ({
|
|
|
104
109
|
)}
|
|
105
110
|
|
|
106
111
|
{message && (
|
|
107
|
-
<
|
|
112
|
+
<InlinePrompt
|
|
113
|
+
sentiment={sentiment}
|
|
114
|
+
id={messageId}
|
|
115
|
+
iconLabel={messageIconLabel}
|
|
116
|
+
className="np-field__prompt"
|
|
117
|
+
loading={messageLoading}
|
|
118
|
+
>
|
|
108
119
|
{message}
|
|
109
|
-
</
|
|
120
|
+
</InlinePrompt>
|
|
110
121
|
)}
|
|
111
122
|
</div>
|
|
112
123
|
</InputInvalidProvider>
|
|
@@ -4,9 +4,13 @@ import InlineAlert, { InlineAlertProps } from './InlineAlert';
|
|
|
4
4
|
import { lorem10, lorem40 } from '../test-utils';
|
|
5
5
|
import Link from '../link';
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* > **DEPRECATED** Use [InlinePrompt](?path=/docs/prompts-inlineprompt--docs) or [Field](?path=/docs/forms-field--docs) instead.
|
|
9
|
+
*/
|
|
7
10
|
export default {
|
|
8
11
|
component: InlineAlert,
|
|
9
12
|
title: 'Prompts/InlineAlert',
|
|
13
|
+
tags: ['deprecated'],
|
|
10
14
|
} as Meta<InlineAlertProps>;
|
|
11
15
|
|
|
12
16
|
export const Basic = () => {
|
|
@@ -22,13 +22,7 @@ const iconTypes = new Set<NonNullable<InlineAlertProps['type']>>([
|
|
|
22
22
|
]);
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
26
|
-
* it's for edge cases when `<Field />` isn't suitable for some reasons.
|
|
27
|
-
*
|
|
28
|
-
* Example:
|
|
29
|
-
* ```
|
|
30
|
-
* <Field sentiment={..} message={..}>..</Field>
|
|
31
|
-
* ```
|
|
25
|
+
* @deprecated Use [<InlinePrompt />](https://storybook.wise.design/?path=/docs/prompts-inlineprompt--docs) of [<Field />](https://storybook.wise.design/?path=/docs/forms-field--docs) instead.
|
|
32
26
|
*/
|
|
33
27
|
export default function InlineAlert({
|
|
34
28
|
id,
|
package/src/main.css
CHANGED
|
@@ -3822,10 +3822,14 @@ html:not([dir="rtl"]) .np-flow-navigation--sm .np-flow-navigation__stepper {
|
|
|
3822
3822
|
stroke-dasharray: calc(12px * 0.5) calc(12px * 0.5);
|
|
3823
3823
|
stroke-dasharray: var(--wds-list-item-spotlight-strokeDashSize) var(--wds-list-item-spotlight-strokeDashSize);
|
|
3824
3824
|
}
|
|
3825
|
-
.np-field-control
|
|
3825
|
+
.np-field-control,
|
|
3826
|
+
.np-field__prompt {
|
|
3826
3827
|
margin-top: 4px;
|
|
3827
3828
|
margin-top: var(--size-4);
|
|
3828
3829
|
}
|
|
3830
|
+
.np-field:has(.np-checkbox) label {
|
|
3831
|
+
margin-bottom: 0;
|
|
3832
|
+
}
|
|
3829
3833
|
.np-input-group {
|
|
3830
3834
|
display: inline-grid;
|
|
3831
3835
|
width: 100%;
|
|
@@ -6920,6 +6924,10 @@ html:not([dir="rtl"]) .np-navigation-option {
|
|
|
6920
6924
|
padding: 0;
|
|
6921
6925
|
margin: 0;
|
|
6922
6926
|
}
|
|
6927
|
+
.typeahead--prompt {
|
|
6928
|
+
margin-top: 4px;
|
|
6929
|
+
margin-top: var(--size-4);
|
|
6930
|
+
}
|
|
6923
6931
|
.typeahead-sm.typeahead--multiple .typeahead__input-container {
|
|
6924
6932
|
min-height: 32px;
|
|
6925
6933
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { useTheme } from '@wise/components-theming';
|
|
2
1
|
import { clsx } from 'clsx';
|
|
3
2
|
|
|
4
3
|
import Body from '../body';
|
|
@@ -23,14 +22,10 @@ const ProgressBar = ({
|
|
|
23
22
|
progress,
|
|
24
23
|
textEnd,
|
|
25
24
|
}: ProgressBarProps) => {
|
|
26
|
-
const { isModern } = useTheme();
|
|
27
25
|
return (
|
|
28
26
|
<div className={clsx('np-progress-bar', className)}>
|
|
29
27
|
<label className="np-progress-bar__title m-b-1" htmlFor={id}>
|
|
30
|
-
<Title
|
|
31
|
-
type={Typography.TITLE_BODY}
|
|
32
|
-
className={isModern ? `m-b-1 text-primary` : `text-primary`}
|
|
33
|
-
>
|
|
28
|
+
<Title type={Typography.TITLE_BODY} className="m-b-1 text-primary">
|
|
34
29
|
{title}
|
|
35
30
|
</Title>
|
|
36
31
|
{description && <Body>{description}</Body>}
|
package/src/select/Select.tsx
CHANGED
|
@@ -163,7 +163,6 @@ export default function Select({
|
|
|
163
163
|
const inputAttributes = useInputAttributes();
|
|
164
164
|
|
|
165
165
|
const { formatMessage } = useIntl();
|
|
166
|
-
const { isModern } = useTheme();
|
|
167
166
|
const s = (className: string) => classNamesProp[className] || className;
|
|
168
167
|
const [open, setOpen] = useState(false);
|
|
169
168
|
const [searchValue, setSearchValue] = useState(DEFAULT_SEARCH_VALUE);
|
|
@@ -599,7 +598,7 @@ export default function Select({
|
|
|
599
598
|
</Drawer>
|
|
600
599
|
) : (
|
|
601
600
|
<BottomSheet open={open} onClose={handleCloseOptions}>
|
|
602
|
-
{renderOptionsList(
|
|
601
|
+
{renderOptionsList()}
|
|
603
602
|
</BottomSheet>
|
|
604
603
|
)
|
|
605
604
|
) : (
|
|
@@ -122,6 +122,10 @@
|
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
+
&--prompt {
|
|
126
|
+
margin-top: var(--size-4);
|
|
127
|
+
}
|
|
128
|
+
|
|
125
129
|
// SIZES
|
|
126
130
|
&-sm {
|
|
127
131
|
&.typeahead--multiple {
|
|
@@ -207,7 +211,7 @@
|
|
|
207
211
|
}
|
|
208
212
|
|
|
209
213
|
.np-theme-personal & {
|
|
210
|
-
.input-group:not(.disabled
|
|
214
|
+
.input-group:not(.disabled, :disabled, .input-group--has-error):focus-within .tw-icon-search {
|
|
211
215
|
color: var(--color-interactive-primary);
|
|
212
216
|
}
|
|
213
217
|
.tw-icon-search {
|
|
@@ -102,7 +102,7 @@ describe('Typeahead', () => {
|
|
|
102
102
|
expect(onChange).toHaveBeenCalledWith([]);
|
|
103
103
|
});
|
|
104
104
|
|
|
105
|
-
it('shows
|
|
105
|
+
it('shows InlinePrompt when alert prop is provided', () => {
|
|
106
106
|
render(
|
|
107
107
|
<Typeahead
|
|
108
108
|
id="test"
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { Meta, StoryObj } from '@storybook/react-webpack5';
|
|
2
2
|
import { Search as SearchIcon } from '@transferwise/icons';
|
|
3
3
|
import { userEvent, within, fn } from 'storybook/test';
|
|
4
|
-
|
|
5
|
-
import Typeahead, { type TypeaheadOption } from './Typeahead';
|
|
6
|
-
import { Size } from '../common';
|
|
7
4
|
import { useState } from 'react';
|
|
5
|
+
|
|
6
|
+
import { Sentiment, Size } from '../common';
|
|
8
7
|
import { Input } from '../inputs/Input';
|
|
9
8
|
import { Field } from '../field/Field';
|
|
10
9
|
import Button from '../button';
|
|
11
10
|
import Modal from '../modal';
|
|
11
|
+
import { InlinePromptProps } from '../prompt';
|
|
12
|
+
import Typeahead, { type TypeaheadOption } from './Typeahead';
|
|
12
13
|
|
|
14
|
+
// needed for SB to display correct name in the docs
|
|
15
|
+
(Typeahead as React.FC).displayName = 'Typeahead';
|
|
13
16
|
type Story = StoryObj<typeof Typeahead>;
|
|
14
17
|
|
|
15
18
|
/**
|
|
@@ -37,6 +40,7 @@ const meta: Meta<typeof Typeahead> = {
|
|
|
37
40
|
searchDelay: 200,
|
|
38
41
|
showSuggestions: true,
|
|
39
42
|
showNewEntry: true,
|
|
43
|
+
alert: undefined,
|
|
40
44
|
size: Size.MEDIUM,
|
|
41
45
|
initialValue: [],
|
|
42
46
|
id: 'myTypeahead',
|
|
@@ -54,6 +58,17 @@ const meta: Meta<typeof Typeahead> = {
|
|
|
54
58
|
control: 'inline-radio',
|
|
55
59
|
options: [Size.MEDIUM, Size.LARGE],
|
|
56
60
|
},
|
|
61
|
+
alert: {
|
|
62
|
+
description:
|
|
63
|
+
'Displays an [InlinePrompt](?path=/docs/prompts-inlineprompt--docs) below the input when provided. <blockquote class="m-0">**⚠️ `error`, `info` and `success` are deprecated as alert types and will be soon removed.**</blockquote>',
|
|
64
|
+
control: 'object',
|
|
65
|
+
table: {
|
|
66
|
+
type: {
|
|
67
|
+
summary:
|
|
68
|
+
'{ message: ReactNode; type?: "negative" | "neutral" | "positive" | "warning" | "proposition" }',
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
},
|
|
57
72
|
},
|
|
58
73
|
};
|
|
59
74
|
export default meta;
|
|
@@ -237,6 +252,14 @@ export const Search: Story = {
|
|
|
237
252
|
};
|
|
238
253
|
|
|
239
254
|
export const AutoFocusInModal: Story = {
|
|
255
|
+
parameters: {
|
|
256
|
+
docs: {
|
|
257
|
+
story: {
|
|
258
|
+
inline: false,
|
|
259
|
+
iframeHeight: 500,
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
},
|
|
240
263
|
render: function Render() {
|
|
241
264
|
const [open, setOpen] = useState<boolean>(true);
|
|
242
265
|
return (
|
|
@@ -279,3 +302,57 @@ export const AutoFocusInModal: Story = {
|
|
|
279
302
|
);
|
|
280
303
|
},
|
|
281
304
|
};
|
|
305
|
+
|
|
306
|
+
export const WithPrompt: Story = {
|
|
307
|
+
args: {
|
|
308
|
+
autoFillOnBlur: undefined,
|
|
309
|
+
chipSeparators: undefined,
|
|
310
|
+
clearable: undefined,
|
|
311
|
+
initialValue: undefined,
|
|
312
|
+
inputAutoComplete: undefined,
|
|
313
|
+
minQueryLength: undefined,
|
|
314
|
+
onBlur: undefined,
|
|
315
|
+
onFocus: undefined,
|
|
316
|
+
onInputChange: undefined,
|
|
317
|
+
onSearch: undefined,
|
|
318
|
+
placeholder: undefined,
|
|
319
|
+
searchDelay: undefined,
|
|
320
|
+
showSuggestions: undefined,
|
|
321
|
+
showNewEntry: undefined,
|
|
322
|
+
size: undefined,
|
|
323
|
+
},
|
|
324
|
+
render: function Render(args) {
|
|
325
|
+
const options = [{ label: 'Option 1' }];
|
|
326
|
+
|
|
327
|
+
const alertTypes: InlinePromptProps['sentiment'][] = [
|
|
328
|
+
Sentiment.NEGATIVE,
|
|
329
|
+
Sentiment.WARNING,
|
|
330
|
+
Sentiment.NEUTRAL,
|
|
331
|
+
Sentiment.POSITIVE,
|
|
332
|
+
'proposition',
|
|
333
|
+
];
|
|
334
|
+
|
|
335
|
+
return (
|
|
336
|
+
<>
|
|
337
|
+
{alertTypes.map((sentiment) => (
|
|
338
|
+
<Typeahead
|
|
339
|
+
key={sentiment}
|
|
340
|
+
{...args}
|
|
341
|
+
id={`typeahead-${sentiment}`}
|
|
342
|
+
name={`typeahead-${sentiment}`}
|
|
343
|
+
options={options}
|
|
344
|
+
alert={{
|
|
345
|
+
message: `This is a ${sentiment} message`,
|
|
346
|
+
type: sentiment,
|
|
347
|
+
}}
|
|
348
|
+
/>
|
|
349
|
+
))}
|
|
350
|
+
</>
|
|
351
|
+
);
|
|
352
|
+
},
|
|
353
|
+
decorators: (Story) => (
|
|
354
|
+
<div className="d-flex flex-column">
|
|
355
|
+
<Story />
|
|
356
|
+
</div>
|
|
357
|
+
),
|
|
358
|
+
};
|
|
@@ -16,8 +16,7 @@ import {
|
|
|
16
16
|
removeClickClassFromDocumentOnIos,
|
|
17
17
|
stopPropagation,
|
|
18
18
|
} from '../common';
|
|
19
|
-
import
|
|
20
|
-
import { InlineAlertProps } from '../inlineAlert/InlineAlert';
|
|
19
|
+
import { InlinePrompt, InlinePromptProps } from '../prompt';
|
|
21
20
|
import { withInputAttributes, WithInputAttributesProps } from '../inputs/contexts';
|
|
22
21
|
|
|
23
22
|
import TypeaheadInput from './typeaheadInput/TypeaheadInput';
|
|
@@ -41,8 +40,12 @@ export interface TypeaheadProps<T> extends Partial<WrappedComponentProps> {
|
|
|
41
40
|
name: string;
|
|
42
41
|
addon?: ReactNode;
|
|
43
42
|
alert?: {
|
|
44
|
-
message:
|
|
45
|
-
type?:
|
|
43
|
+
message: InlinePromptProps['children'];
|
|
44
|
+
type?:
|
|
45
|
+
| InlinePromptProps['sentiment']
|
|
46
|
+
| `${Sentiment.ERROR}`
|
|
47
|
+
| `${Sentiment.INFO}`
|
|
48
|
+
| `${Sentiment.SUCCESS}`;
|
|
46
49
|
};
|
|
47
50
|
allowNew?: boolean;
|
|
48
51
|
autoFillOnBlur?: boolean;
|
|
@@ -474,9 +477,20 @@ class Typeahead<T> extends Component<TypeaheadPropsWithInputAttributes<T>, Typea
|
|
|
474
477
|
dropdownOpen,
|
|
475
478
|
});
|
|
476
479
|
|
|
477
|
-
const alertType =
|
|
478
|
-
|
|
479
|
-
|
|
480
|
+
const alertType = (() => {
|
|
481
|
+
if (!alert?.type || alert.type === Sentiment.INFO) {
|
|
482
|
+
return Sentiment.NEUTRAL;
|
|
483
|
+
}
|
|
484
|
+
if (alert.type === Sentiment.ERROR) {
|
|
485
|
+
return Sentiment.NEGATIVE;
|
|
486
|
+
}
|
|
487
|
+
if (alert.type === Sentiment.SUCCESS) {
|
|
488
|
+
return Sentiment.POSITIVE;
|
|
489
|
+
}
|
|
490
|
+
return alert.type;
|
|
491
|
+
})();
|
|
492
|
+
const hasError = errorState || (alert && alertType === Sentiment.NEGATIVE);
|
|
493
|
+
const displayAlert = (!errorState && alert) || (alert && alertType === Sentiment.NEGATIVE);
|
|
480
494
|
const hasWarning = displayAlert && alertType === Sentiment.WARNING;
|
|
481
495
|
const hasInfo = displayAlert && alertType === Sentiment.NEUTRAL;
|
|
482
496
|
return (
|
|
@@ -546,7 +560,13 @@ class Typeahead<T> extends Component<TypeaheadPropsWithInputAttributes<T>, Typea
|
|
|
546
560
|
</div>
|
|
547
561
|
)}
|
|
548
562
|
</div>
|
|
549
|
-
{displayAlert ?
|
|
563
|
+
{displayAlert ? (
|
|
564
|
+
<InlinePrompt sentiment={alertType} className="typeahead--prompt">
|
|
565
|
+
{alert.message}
|
|
566
|
+
</InlinePrompt>
|
|
567
|
+
) : (
|
|
568
|
+
menu
|
|
569
|
+
)}
|
|
550
570
|
</div>
|
|
551
571
|
</div>
|
|
552
572
|
);
|
|
@@ -71,7 +71,7 @@ const meta = {
|
|
|
71
71
|
},
|
|
72
72
|
errorIconLabel: {
|
|
73
73
|
description:
|
|
74
|
-
"Override for the
|
|
74
|
+
"Override for the InlinePrompt icon's default, accessible name announced by the screen readers",
|
|
75
75
|
},
|
|
76
76
|
usHelpImage: {
|
|
77
77
|
control: false,
|