@transferwise/components 46.119.5 → 46.120.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 +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/checkbox/Checkbox.js +1 -1
- package/build/checkbox/Checkbox.js.map +1 -1
- package/build/checkbox/Checkbox.mjs +1 -1
- package/build/checkbox/Checkbox.mjs.map +1 -1
- package/build/common/initials.js +17 -7
- package/build/common/initials.js.map +1 -1
- package/build/common/initials.mjs +17 -7
- package/build/common/initials.mjs.map +1 -1
- package/build/field/Field.js +8 -4
- package/build/field/Field.js.map +1 -1
- package/build/field/Field.mjs +8 -4
- 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 +20 -1
- package/build/prompt/InlinePrompt/InlinePrompt.js +2 -0
- package/build/prompt/InlinePrompt/InlinePrompt.js.map +1 -1
- package/build/prompt/InlinePrompt/InlinePrompt.mjs +2 -0
- package/build/prompt/InlinePrompt/InlinePrompt.mjs.map +1 -1
- package/build/radioGroup/RadioGroup.js +1 -0
- package/build/radioGroup/RadioGroup.js.map +1 -1
- package/build/radioGroup/RadioGroup.mjs +1 -0
- package/build/radioGroup/RadioGroup.mjs.map +1 -1
- package/build/styles/field/Field.css +10 -1
- package/build/styles/main.css +20 -1
- package/build/styles/prompt/InlinePrompt/InlinePrompt.css +3 -0
- package/build/styles/radioGroup/RadioGroup.css +3 -0
- package/build/styles/typeahead/Typeahead.css +4 -0
- package/build/typeahead/Typeahead.js +20 -7
- package/build/typeahead/Typeahead.js.map +1 -1
- package/build/typeahead/Typeahead.mjs +20 -7
- 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/common/initials.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/listItem/_stories/variants/helpers.d.ts +7 -4
- package/build/types/listItem/_stories/variants/helpers.d.ts.map +1 -1
- package/build/types/prompt/InlinePrompt/InlinePrompt.d.ts +6 -1
- package/build/types/prompt/InlinePrompt/InlinePrompt.d.ts.map +1 -1
- package/build/types/radioGroup/RadioGroup.d.ts.map +1 -1
- package/build/types/test-utils/index.d.ts +0 -1
- package/build/types/test-utils/index.d.ts.map +1 -1
- package/build/types/typeahead/Typeahead.d.ts +8 -4
- package/build/types/typeahead/Typeahead.d.ts.map +1 -1
- package/build/types/upload/Upload.d.ts +1 -1
- package/build/types/upload/steps/uploadImageStep/uploadImageStep.d.ts.map +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 +5 -4
- package/build/upload/steps/uploadImageStep/uploadImageStep.js.map +1 -1
- package/build/upload/steps/uploadImageStep/uploadImageStep.mjs +5 -4
- package/build/upload/steps/uploadImageStep/uploadImageStep.mjs.map +1 -1
- package/package.json +9 -8
- package/src/DisabledComponents.story.tsx +1 -3
- package/src/actionButton/ActionButton.story.tsx +42 -45
- package/src/alert/Alert.spec.tsx +1 -1
- package/src/alert/Alert.tsx +2 -2
- package/src/avatar/Avatar.story.tsx +192 -188
- package/src/button/_stories/Button.tests.story.tsx +122 -119
- package/src/carousel/Carousel.story.tsx +4 -7
- package/src/checkbox/Checkbox.story.tsx +42 -21
- package/src/checkbox/Checkbox.tsx +1 -1
- package/src/checkbox/__snapshots__/Checkbox.spec.tsx.snap +1 -1
- package/src/circularButton/CircularButton.story.tsx +10 -2
- package/src/common/bottomSheet/BottomSheet.story.tsx +48 -14
- package/src/common/circle/Circle.story.tsx +62 -55
- package/src/common/initials.spec.tsx +31 -0
- package/src/common/initials.ts +19 -8
- package/src/criticalBanner/CriticalCommsBanner.story.tsx +30 -19
- package/src/dateInput/DateInput.tests.story.tsx +101 -74
- package/src/dateLookup/DateLookup.story.tsx +69 -59
- package/src/field/Field.css +10 -1
- package/src/field/Field.less +13 -2
- package/src/field/Field.spec.tsx +19 -3
- package/src/field/Field.story.tsx +18 -0
- package/src/field/Field.tsx +17 -5
- package/src/header/Header.story.tsx +5 -16
- package/src/header/Header.tests.story.tsx +95 -69
- package/src/info/Info.story.tsx +27 -11
- package/src/inlineAlert/InlineAlert.story.tsx +4 -0
- package/src/inlineAlert/InlineAlert.tsx +1 -7
- package/src/instructionsList/InstructionsList.story.tsx +0 -1
- package/src/listItem/_stories/ListItem.layout.test.story.tsx +1 -3
- package/src/listItem/_stories/variants/ListItem.brightGreen.test.story.tsx +77 -35
- package/src/listItem/_stories/variants/ListItem.dark.test.story.tsx +65 -29
- package/src/listItem/_stories/variants/ListItem.forestGreen.test.story.tsx +77 -35
- package/src/listItem/_stories/variants/ListItem.medium.test.story.tsx +38 -18
- package/src/listItem/_stories/variants/ListItem.neutral.test.story.tsx +0 -1
- package/src/listItem/_stories/variants/ListItem.personal.test.story.tsx +38 -18
- package/src/listItem/_stories/variants/ListItem.rtl.test.story.tsx +77 -29
- package/src/listItem/_stories/variants/ListItem.small.test.story.tsx +65 -18
- package/src/listItem/_stories/variants/helpers.tsx +136 -133
- package/src/main.css +20 -1
- package/src/main.less +1 -0
- package/src/modal/Modal.story.tsx +47 -8
- package/src/moneyInput/MoneyInput.story.tsx +2 -2
- package/src/primitives/PrimitiveAnchor/stories/PrimitiveAnchor.story.tsx +1 -0
- package/src/primitives/PrimitiveAnchor/stories/PrimitiveAnchor.tests.story.tsx +1 -0
- package/src/primitives/PrimitiveButton/stories/PrimitiveButton.story.tsx +1 -0
- package/src/primitives/PrimitiveButton/stories/PrimitiveButton.tests.story.tsx +1 -0
- package/src/prompt/InlinePrompt/InlinePrompt.css +3 -0
- package/src/prompt/InlinePrompt/InlinePrompt.less +5 -1
- package/src/prompt/InlinePrompt/InlinePrompt.spec.tsx +17 -0
- package/src/prompt/InlinePrompt/InlinePrompt.story.tsx +35 -0
- package/src/prompt/InlinePrompt/InlinePrompt.tsx +7 -0
- package/src/provider/theme/ThemeProvider.story.tsx +1 -0
- package/src/radioGroup/RadioGroup.css +3 -0
- package/src/radioGroup/RadioGroup.less +3 -0
- package/src/radioGroup/RadioGroup.story.tsx +2 -0
- package/src/radioGroup/RadioGroup.test.story.tsx +62 -0
- package/src/radioGroup/RadioGroup.tsx +6 -1
- package/src/segmentedControl/SegmentedControl.story.tsx +71 -67
- package/src/snackbar/Snackbar.tests.story.tsx +116 -114
- package/src/statusIcon/StatusIcon.story.tsx +41 -38
- package/src/test-utils/index.tsx +0 -2
- package/src/tokens/tokens.story.tsx +1 -1
- package/src/tooltip/Tooltip.story.tsx +10 -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 +151 -3
- package/src/typeahead/Typeahead.tsx +33 -9
- 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 +7 -3
- package/src/withId/withId.story.tsx +1 -1
- package/build/types/test-utils/story-config.d.ts +0 -64
- package/build/types/test-utils/story-config.d.ts.map +0 -1
- package/src/test-utils/story-config.ts +0 -95
|
@@ -2,10 +2,11 @@ import { Meta, StoryObj } from '@storybook/react-webpack5';
|
|
|
2
2
|
import { userEvent, within, fn } from 'storybook/test';
|
|
3
3
|
|
|
4
4
|
import { DateInput, Field } from '..';
|
|
5
|
-
import { lorem10
|
|
5
|
+
import { lorem10 } from '../test-utils';
|
|
6
6
|
|
|
7
7
|
import Provider from '../provider/Provider';
|
|
8
8
|
import translations from '../i18n';
|
|
9
|
+
import { allModes } from '../../.storybook/modes';
|
|
9
10
|
|
|
10
11
|
const meta: Meta<typeof DateInput> = {
|
|
11
12
|
component: DateInput,
|
|
@@ -78,64 +79,72 @@ export const CustomPlaceholders: Story = {
|
|
|
78
79
|
},
|
|
79
80
|
};
|
|
80
81
|
|
|
81
|
-
export const SingleZero =
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
await
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
await
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const
|
|
136
|
-
await
|
|
137
|
-
|
|
138
|
-
|
|
82
|
+
export const SingleZero: Story = {
|
|
83
|
+
...Basic,
|
|
84
|
+
play: async ({ canvasElement, step }) => {
|
|
85
|
+
const canvas = within(canvasElement);
|
|
86
|
+
await step('can enter leading zero on day field', async () => {
|
|
87
|
+
const dayInput = await canvas.findByRole('textbox', { name: /day/i });
|
|
88
|
+
await userEvent.click(dayInput);
|
|
89
|
+
await userEvent.type(dayInput, '0');
|
|
90
|
+
});
|
|
91
|
+
await step('can enter 1 leading zero on year field', async () => {
|
|
92
|
+
const yearInput = await canvas.findByRole('textbox', { name: /year/i });
|
|
93
|
+
await userEvent.click(yearInput);
|
|
94
|
+
await userEvent.type(yearInput, '0');
|
|
95
|
+
});
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export const ZeroesAsValue: Story = {
|
|
100
|
+
...Basic,
|
|
101
|
+
play: async ({ canvasElement, step }) => {
|
|
102
|
+
const canvas = within(canvasElement);
|
|
103
|
+
await step('can enter 2 leading zeroes on day field', async () => {
|
|
104
|
+
const dayInput = await canvas.findByRole('textbox', { name: /day/i });
|
|
105
|
+
await userEvent.click(dayInput);
|
|
106
|
+
await userEvent.type(dayInput, '00');
|
|
107
|
+
});
|
|
108
|
+
await step('can enter 4 leading zeroes on year field', async () => {
|
|
109
|
+
const yearInput = await canvas.findByRole('textbox', { name: /year/i });
|
|
110
|
+
await userEvent.click(yearInput);
|
|
111
|
+
await userEvent.type(yearInput, '0000');
|
|
112
|
+
});
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export const ZeroesBeforeValue: Story = {
|
|
117
|
+
...Basic,
|
|
118
|
+
play: async ({ canvasElement, step }) => {
|
|
119
|
+
const canvas = within(canvasElement);
|
|
120
|
+
await step('can enter leading zeroes on day followed by day', async () => {
|
|
121
|
+
const dayInput = await canvas.findByRole('textbox', { name: /day/i });
|
|
122
|
+
await userEvent.click(dayInput);
|
|
123
|
+
await userEvent.type(dayInput, '01');
|
|
124
|
+
});
|
|
125
|
+
await step('can enter leading zeroes on year followed by year', async () => {
|
|
126
|
+
const yearInput = await canvas.findByRole('textbox', { name: /year/i });
|
|
127
|
+
await userEvent.click(yearInput);
|
|
128
|
+
await userEvent.type(yearInput, '0001');
|
|
129
|
+
});
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export const MaxLengthRespected: Story = {
|
|
134
|
+
...Basic,
|
|
135
|
+
play: async ({ canvasElement, step }) => {
|
|
136
|
+
const canvas = within(canvasElement);
|
|
137
|
+
await step('can only enter 4 digits in the year field', async () => {
|
|
138
|
+
const yearInput = await canvas.findByRole('textbox', { name: /year/i });
|
|
139
|
+
await userEvent.click(yearInput);
|
|
140
|
+
await userEvent.type(yearInput, '11111111');
|
|
141
|
+
});
|
|
142
|
+
await step('can only enter 2 digits in the day field', async () => {
|
|
143
|
+
const dayInput = await canvas.findByRole('textbox', { name: /day/i });
|
|
144
|
+
await userEvent.click(dayInput);
|
|
145
|
+
await userEvent.type(dayInput, '11111111');
|
|
146
|
+
});
|
|
147
|
+
},
|
|
139
148
|
};
|
|
140
149
|
|
|
141
150
|
export const LocalizationWorks: Story = {
|
|
@@ -194,21 +203,39 @@ export const DayFirst: Story = {
|
|
|
194
203
|
],
|
|
195
204
|
};
|
|
196
205
|
|
|
197
|
-
export const NoNonDigitsAllowed =
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
206
|
+
export const NoNonDigitsAllowed: Story = {
|
|
207
|
+
...Basic,
|
|
208
|
+
play: async ({ canvasElement, step }) => {
|
|
209
|
+
const canvas = within(canvasElement);
|
|
210
|
+
await step('can only enter digits in the day field', async () => {
|
|
211
|
+
const dayInput = await canvas.findByRole('textbox', { name: /day/i });
|
|
212
|
+
await userEvent.click(dayInput);
|
|
213
|
+
await userEvent.type(dayInput, 'abcd1');
|
|
214
|
+
});
|
|
215
|
+
await step('can only enter digits in the year field', async () => {
|
|
216
|
+
const yearInput = await canvas.findByRole('textbox', { name: /year/i });
|
|
217
|
+
await userEvent.click(yearInput);
|
|
218
|
+
await userEvent.type(yearInput, 'abcd2');
|
|
219
|
+
});
|
|
220
|
+
},
|
|
210
221
|
};
|
|
211
222
|
|
|
212
|
-
export const BasicMobile =
|
|
223
|
+
export const BasicMobile: Story = {
|
|
224
|
+
...Basic,
|
|
225
|
+
parameters: {
|
|
226
|
+
variants: ['mobile'],
|
|
227
|
+
chromatic: {
|
|
228
|
+
mobile: allModes.largeMobile,
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
};
|
|
213
232
|
|
|
214
|
-
export const InputErrorMobile =
|
|
233
|
+
export const InputErrorMobile: Story = {
|
|
234
|
+
...InputError,
|
|
235
|
+
parameters: {
|
|
236
|
+
variants: ['mobile'],
|
|
237
|
+
chromatic: {
|
|
238
|
+
mobile: allModes.largeMobile,
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { useState } from 'react';
|
|
2
2
|
import { userEvent } from 'storybook/test';
|
|
3
|
+
import { StoryObj } from '@storybook/react-webpack5';
|
|
3
4
|
import { Field } from '..';
|
|
4
5
|
import { Size } from '../common';
|
|
5
|
-
import { storyConfig } from '../test-utils';
|
|
6
6
|
import DateLookup, { type DateLookupProps } from './DateLookup';
|
|
7
|
+
import { allModes } from '../../.storybook/modes';
|
|
7
8
|
|
|
8
9
|
export default {
|
|
9
10
|
component: DateLookup,
|
|
@@ -21,53 +22,18 @@ export default {
|
|
|
21
22
|
},
|
|
22
23
|
};
|
|
23
24
|
|
|
25
|
+
type Story = StoryObj<typeof DateLookup>;
|
|
26
|
+
|
|
24
27
|
const epoch = new Date('2011-01-01');
|
|
25
28
|
const theFuture = new Date(epoch);
|
|
26
29
|
theFuture.setUTCDate(epoch.getUTCDate() + 10);
|
|
27
30
|
const thePast = new Date(epoch);
|
|
28
31
|
thePast.setUTCDate(epoch.getUTCDate() - 10);
|
|
29
32
|
|
|
30
|
-
export const Basic
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
{...args}
|
|
35
|
-
min={args.min ? new Date(args.min) : thePast}
|
|
36
|
-
max={args.max ? new Date(args.max) : theFuture}
|
|
37
|
-
value={value}
|
|
38
|
-
onChange={(v) => setValue(v)}
|
|
39
|
-
/>
|
|
40
|
-
);
|
|
41
|
-
};
|
|
42
|
-
Basic.args = {
|
|
43
|
-
size: Size.MEDIUM,
|
|
44
|
-
disabled: false,
|
|
45
|
-
label: 'label',
|
|
46
|
-
monthFormat: 'long',
|
|
47
|
-
placeholder: 'placeholder',
|
|
48
|
-
id: 'date-lookup',
|
|
49
|
-
clearable: true,
|
|
50
|
-
min: thePast,
|
|
51
|
-
max: theFuture,
|
|
52
|
-
};
|
|
53
|
-
Basic.play = async ({ canvasElement }: { canvasElement: HTMLElement }) => {
|
|
54
|
-
await userEvent.tab();
|
|
55
|
-
await userEvent.keyboard(' ');
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
export const Basic400Zoom = storyConfig(
|
|
59
|
-
{
|
|
60
|
-
render: Basic,
|
|
61
|
-
play: Basic.play,
|
|
62
|
-
parameters: { chromatic: { delay: 2000 } },
|
|
63
|
-
},
|
|
64
|
-
{ variants: ['400%'] },
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
export const WithField = (args: DateLookupProps) => {
|
|
68
|
-
const [value, setValue] = useState<Date | null>(epoch);
|
|
69
|
-
return (
|
|
70
|
-
<Field label="Date lookup">
|
|
33
|
+
export const Basic: Story = {
|
|
34
|
+
render: (args: DateLookupProps) => {
|
|
35
|
+
const [value, setValue] = useState<Date | null>(epoch);
|
|
36
|
+
return (
|
|
71
37
|
<DateLookup
|
|
72
38
|
{...args}
|
|
73
39
|
min={args.min ? new Date(args.min) : thePast}
|
|
@@ -75,31 +41,75 @@ export const WithField = (args: DateLookupProps) => {
|
|
|
75
41
|
value={value}
|
|
76
42
|
onChange={(v) => setValue(v)}
|
|
77
43
|
/>
|
|
78
|
-
|
|
79
|
-
|
|
44
|
+
);
|
|
45
|
+
},
|
|
46
|
+
args: {
|
|
47
|
+
size: Size.MEDIUM,
|
|
48
|
+
disabled: false,
|
|
49
|
+
label: 'label',
|
|
50
|
+
monthFormat: 'long',
|
|
51
|
+
placeholder: 'placeholder',
|
|
52
|
+
id: 'date-lookup',
|
|
53
|
+
clearable: true,
|
|
54
|
+
min: thePast,
|
|
55
|
+
max: theFuture,
|
|
56
|
+
},
|
|
57
|
+
play: async () => {
|
|
58
|
+
await userEvent.tab();
|
|
59
|
+
await userEvent.keyboard(' ');
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
export const Basic400Zoom: Story = {
|
|
63
|
+
...Basic,
|
|
64
|
+
parameters: {
|
|
65
|
+
chromatic: {
|
|
66
|
+
delay: 2000,
|
|
67
|
+
zoom400: allModes.zoom400,
|
|
68
|
+
},
|
|
69
|
+
variants: ['400%'],
|
|
70
|
+
},
|
|
80
71
|
};
|
|
81
72
|
|
|
82
|
-
export const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
<
|
|
87
|
-
<p>
|
|
88
|
-
This example demonstrates the automatic right alignment behaviour of the calendar. If,
|
|
89
|
-
when the calendar is opened, it is cut off on the right, the component will align the
|
|
90
|
-
calendar to the rightmost edge of the lookup input.
|
|
91
|
-
</p>
|
|
92
|
-
</div>
|
|
93
|
-
<div className="col-xs-6">
|
|
73
|
+
export const WithField: Story = {
|
|
74
|
+
render: (args: DateLookupProps) => {
|
|
75
|
+
const [value, setValue] = useState<Date | null>(epoch);
|
|
76
|
+
return (
|
|
77
|
+
<Field label="Date lookup">
|
|
94
78
|
<DateLookup
|
|
95
79
|
{...args}
|
|
96
|
-
id="right-aligned"
|
|
97
80
|
min={args.min ? new Date(args.min) : thePast}
|
|
98
81
|
max={args.max ? new Date(args.max) : theFuture}
|
|
99
82
|
value={value}
|
|
100
83
|
onChange={(v) => setValue(v)}
|
|
101
84
|
/>
|
|
85
|
+
</Field>
|
|
86
|
+
);
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const RightAligned: Story = {
|
|
91
|
+
render: (args: DateLookupProps) => {
|
|
92
|
+
const [value, setValue] = useState<Date | null>(epoch);
|
|
93
|
+
return (
|
|
94
|
+
<div className="row">
|
|
95
|
+
<div className="col-xs-6">
|
|
96
|
+
<p>
|
|
97
|
+
This example demonstrates the automatic right alignment behaviour of the calendar. If,
|
|
98
|
+
when the calendar is opened, it is cut off on the right, the component will align the
|
|
99
|
+
calendar to the rightmost edge of the lookup input.
|
|
100
|
+
</p>
|
|
101
|
+
</div>
|
|
102
|
+
<div className="col-xs-6">
|
|
103
|
+
<DateLookup
|
|
104
|
+
{...args}
|
|
105
|
+
id="right-aligned"
|
|
106
|
+
min={args.min ? new Date(args.min) : thePast}
|
|
107
|
+
max={args.max ? new Date(args.max) : theFuture}
|
|
108
|
+
value={value}
|
|
109
|
+
onChange={(v) => setValue(v)}
|
|
110
|
+
/>
|
|
111
|
+
</div>
|
|
102
112
|
</div>
|
|
103
|
-
|
|
104
|
-
|
|
113
|
+
);
|
|
114
|
+
},
|
|
105
115
|
};
|
package/src/field/Field.css
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
.np-field-control
|
|
1
|
+
.np-field-control,
|
|
2
|
+
.np-field__prompt {
|
|
2
3
|
margin-top: 4px;
|
|
3
4
|
margin-top: var(--size-4);
|
|
4
5
|
}
|
|
6
|
+
.np-field .form-group--typeahead[class],
|
|
7
|
+
.np-field .np-checkbox-label[class] {
|
|
8
|
+
margin-bottom: 0;
|
|
9
|
+
}
|
|
10
|
+
.np-field:has(.wds-radio-group) .np-field__prompt {
|
|
11
|
+
margin-top: 12px;
|
|
12
|
+
margin-top: var(--size-12);
|
|
13
|
+
}
|
package/src/field/Field.less
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
.np-field {
|
|
2
|
-
&-control
|
|
3
|
-
|
|
2
|
+
&-control,
|
|
3
|
+
&__prompt {
|
|
4
|
+
margin-top: var(--size-4);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
// @FIXME space between individual fields should be 24px, while some older inputs
|
|
8
|
+
// inject extraneous space.
|
|
9
|
+
.form-group--typeahead[class],
|
|
10
|
+
.np-checkbox-label[class] {
|
|
11
|
+
margin-bottom: 0;
|
|
12
|
+
}
|
|
13
|
+
&:has(.wds-radio-group) &__prompt {
|
|
14
|
+
margin-top: var(--size-12);
|
|
4
15
|
}
|
|
5
16
|
}
|
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,16 @@ export const Field = ({
|
|
|
104
109
|
)}
|
|
105
110
|
|
|
106
111
|
{message && (
|
|
107
|
-
<
|
|
112
|
+
<InlinePrompt
|
|
113
|
+
sentiment={sentiment}
|
|
114
|
+
id={messageId}
|
|
115
|
+
mediaLabel={messageIconLabel}
|
|
116
|
+
className="np-field__prompt"
|
|
117
|
+
loading={messageLoading}
|
|
118
|
+
width="full"
|
|
119
|
+
>
|
|
108
120
|
{message}
|
|
109
|
-
</
|
|
121
|
+
</InlinePrompt>
|
|
110
122
|
)}
|
|
111
123
|
</div>
|
|
112
124
|
</InputInvalidProvider>
|
|
@@ -13,20 +13,6 @@ const withContainer = (Story: any) => (
|
|
|
13
13
|
const hideControls = (args: string[]) =>
|
|
14
14
|
Object.fromEntries(args.map((item) => [item, { table: { disable: true } }]));
|
|
15
15
|
|
|
16
|
-
/**
|
|
17
|
-
* Reusable render logic for wrapping `Header` in a `<fieldset>` if `as` is `legend`.
|
|
18
|
-
*/
|
|
19
|
-
const renderHeader = (args: HeaderProps) => {
|
|
20
|
-
if (args.as === 'legend') {
|
|
21
|
-
return (
|
|
22
|
-
<fieldset style={{ width: '100%' }}>
|
|
23
|
-
<Header {...args} />
|
|
24
|
-
</fieldset>
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
return <Header {...args} />;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
16
|
/**
|
|
31
17
|
* The stories below document the `Header` component, which is used to structure content and convey hierarchy. <br />
|
|
32
18
|
* For more details, refer to the [design documentation](https://wise.design/components/section-header).
|
|
@@ -89,7 +75,6 @@ export default meta;
|
|
|
89
75
|
type Story = StoryObj<typeof Header>;
|
|
90
76
|
|
|
91
77
|
export const Playground: Story = {
|
|
92
|
-
render: renderHeader,
|
|
93
78
|
args: {
|
|
94
79
|
title: 'Playground Header',
|
|
95
80
|
level: 'group',
|
|
@@ -151,7 +136,11 @@ export const DisabledAction: Story = {
|
|
|
151
136
|
* Demonstrates a `Header` rendered as a custom HTML element.
|
|
152
137
|
*/
|
|
153
138
|
export const CustomElement: Story = {
|
|
154
|
-
render:
|
|
139
|
+
render: (args) => (
|
|
140
|
+
<fieldset style={{ width: '100%' }}>
|
|
141
|
+
<Header {...args} />
|
|
142
|
+
</fieldset>
|
|
143
|
+
),
|
|
155
144
|
args: {
|
|
156
145
|
title: 'Legend Header',
|
|
157
146
|
as: 'legend',
|