@transferwise/components 0.0.0-experimental-75fc27b → 0.0.0-experimental-8a932bb
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/avatarLayout/AvatarLayout.js +10 -2
- package/build/avatarLayout/AvatarLayout.js.map +1 -1
- package/build/avatarLayout/AvatarLayout.mjs +10 -2
- package/build/avatarLayout/AvatarLayout.mjs.map +1 -1
- package/build/button/Button/src/Button.js +93 -0
- package/build/button/Button/src/Button.js.map +1 -0
- package/build/button/Button/src/Button.mjs +91 -0
- package/build/button/Button/src/Button.mjs.map +1 -0
- package/build/button/{Button.js → LegacyButton/Button.js} +25 -24
- package/build/button/LegacyButton/Button.js.map +1 -0
- package/build/button/{Button.mjs → LegacyButton/Button.mjs} +25 -24
- package/build/button/LegacyButton/Button.mjs.map +1 -0
- package/build/button/LegacyButton/classMap.js +42 -0
- package/build/button/LegacyButton/classMap.js.map +1 -0
- package/build/button/LegacyButton/classMap.mjs +39 -0
- package/build/button/LegacyButton/classMap.mjs.map +1 -0
- package/build/button/{legacyUtils → LegacyButton/legacyUtils}/legacyUtils.js +21 -21
- package/build/button/LegacyButton/legacyUtils/legacyUtils.js.map +1 -0
- package/build/button/{legacyUtils → LegacyButton/legacyUtils}/legacyUtils.mjs +21 -21
- package/build/button/LegacyButton/legacyUtils/legacyUtils.mjs.map +1 -0
- package/build/button/src/Button.js +76 -0
- package/build/button/src/Button.js.map +1 -0
- package/build/button/src/Button.mjs +74 -0
- package/build/button/src/Button.mjs.map +1 -0
- package/build/circularButton/CircularButton.js +1 -1
- package/build/circularButton/CircularButton.js.map +1 -1
- package/build/circularButton/CircularButton.mjs +1 -1
- package/build/circularButton/CircularButton.mjs.map +1 -1
- package/build/common/action/Action.js +1 -1
- package/build/common/action/Action.js.map +1 -1
- package/build/common/action/Action.mjs +1 -1
- package/build/common/action/Action.mjs.map +1 -1
- package/build/criticalBanner/CriticalCommsBanner.js +1 -1
- package/build/criticalBanner/CriticalCommsBanner.mjs +1 -1
- package/build/header/Header.js +1 -1
- package/build/header/Header.mjs +1 -1
- package/build/index.js +1 -1
- package/build/index.mjs +1 -1
- package/build/link/Link.js +8 -3
- package/build/link/Link.js.map +1 -1
- package/build/link/Link.mjs +8 -3
- package/build/link/Link.mjs.map +1 -1
- package/build/main.css +288 -29
- package/build/nudge/Nudge.js +1 -1
- package/build/nudge/Nudge.js.map +1 -1
- package/build/nudge/Nudge.mjs +1 -1
- package/build/nudge/Nudge.mjs.map +1 -1
- package/build/select/Select.js +4 -2
- package/build/select/Select.js.map +1 -1
- package/build/select/Select.mjs +4 -2
- package/build/select/Select.mjs.map +1 -1
- package/build/styles/avatarLayout/AvatarLayout.css +11 -0
- package/build/styles/button/Button/less/Button.css +253 -0
- package/build/styles/button/Button/less/Button.vars.css +57 -0
- package/build/styles/iconButton/IconButton.css +24 -29
- package/build/styles/main.css +288 -29
- package/build/types/avatarLayout/AvatarLayout.d.ts +1 -2
- package/build/types/avatarLayout/AvatarLayout.d.ts.map +1 -1
- package/build/types/avatarLayout/index.d.ts +1 -0
- package/build/types/avatarLayout/index.d.ts.map +1 -1
- package/build/types/button/Button/index.d.ts +3 -0
- package/build/types/button/Button/index.d.ts.map +1 -0
- package/build/types/button/Button/src/Button.d.ts +4 -0
- package/build/types/button/Button/src/Button.d.ts.map +1 -0
- package/build/types/button/Button/src/Button.types.d.ts +50 -0
- package/build/types/button/Button/src/Button.types.d.ts.map +1 -0
- package/build/types/button/Button/src/index.d.ts +2 -0
- package/build/types/button/Button/src/index.d.ts.map +1 -0
- package/build/types/button/{Button.d.ts → LegacyButton/Button.d.ts} +6 -4
- package/build/types/button/LegacyButton/Button.d.ts.map +1 -0
- package/build/types/button/LegacyButton/classMap.d.ts.map +1 -0
- package/build/types/button/LegacyButton/index.d.ts +3 -0
- package/build/types/button/LegacyButton/index.d.ts.map +1 -0
- package/build/types/button/LegacyButton/legacyUtils/index.d.ts.map +1 -0
- package/build/types/button/{legacyUtils → LegacyButton/legacyUtils}/legacyUtils.d.ts +1 -1
- package/build/types/button/LegacyButton/legacyUtils/legacyUtils.d.ts.map +1 -0
- package/build/types/button/index.d.ts +2 -2
- package/build/types/button/index.d.ts.map +1 -1
- package/build/types/button/src/Button.d.ts +30 -0
- package/build/types/button/src/Button.d.ts.map +1 -0
- package/build/types/button/src/index.d.ts +3 -0
- package/build/types/button/src/index.d.ts.map +1 -0
- package/build/types/link/Link.d.ts +2 -2
- package/build/types/link/Link.d.ts.map +1 -1
- package/build/types/select/Select.d.ts.map +1 -1
- package/build/types/test-utils/index.d.ts.map +1 -1
- package/build/upload/steps/completeStep/completeStep.js +1 -1
- package/build/upload/steps/completeStep/completeStep.mjs +1 -1
- package/build/upload/steps/processingStep/processingStep.js +1 -1
- package/build/upload/steps/processingStep/processingStep.mjs +1 -1
- package/build/uploadInput/UploadInput.js +1 -1
- package/build/uploadInput/UploadInput.mjs +1 -1
- package/package.json +5 -5
- package/src/avatarLayout/AvatarLayout.css +11 -0
- package/src/avatarLayout/AvatarLayout.less +18 -1
- package/src/avatarLayout/AvatarLayout.story.tsx +2 -0
- package/src/avatarLayout/AvatarLayout.tsx +14 -4
- package/src/avatarLayout/index.ts +1 -0
- package/src/avatarWrapper/AvatarWrapper.story.tsx +2 -0
- package/src/button/Button/index.ts +2 -0
- package/src/button/Button/less/Button.css +253 -0
- package/src/button/Button/less/Button.less +221 -0
- package/src/button/Button/less/Button.vars.css +57 -0
- package/src/button/Button/less/Button.vars.less +65 -0
- package/src/button/Button/src/Button.tsx +116 -0
- package/src/button/Button/src/Button.types.ts +70 -0
- package/src/button/Button/src/index.ts +1 -0
- package/src/button/Button/stories/Button.story.tsx +314 -0
- package/src/button/Button/stories/Button.tests.story.tsx +288 -0
- package/src/button/Button/test/Button.spec.tsx +328 -0
- package/src/button/{Button.less → LegacyButton/Button.less} +1 -1
- package/src/button/{Button.spec.tsx → LegacyButton/Button.spec.tsx} +3 -3
- package/src/button/LegacyButton/Button.story.tsx +224 -0
- package/src/button/{Button.tsx → LegacyButton/Button.tsx} +12 -8
- package/src/button/{classMap.ts → LegacyButton/classMap.ts} +1 -1
- package/src/button/LegacyButton/index.ts +3 -0
- package/src/button/{legacyUtils → LegacyButton/legacyUtils}/legacyUtils.spec.tsx +2 -2
- package/src/button/{legacyUtils → LegacyButton/legacyUtils}/legacyUtils.ts +2 -2
- package/src/button/index.ts +2 -3
- package/src/button/src/Button.tsx +118 -0
- package/src/button/src/index.ts +2 -0
- package/src/button/test/Button.spec.tsx +66 -0
- package/src/circularButton/CircularButton.tsx +1 -1
- package/src/common/action/Action.tsx +1 -1
- package/src/iconButton/IconButton.css +24 -29
- package/src/iconButton/IconButton.less +4 -4
- package/src/link/Link.tsx +15 -6
- package/src/main.css +288 -29
- package/src/main.less +2 -1
- package/src/nudge/Nudge.tsx +1 -1
- package/src/primitives/PrimitiveAnchor/stories/PrimitiveAnchor.story.tsx +1 -1
- package/src/primitives/PrimitiveAnchor/test/PrimitiveAnchor.spec.tsx +1 -1
- package/src/primitives/PrimitiveButton/stories/PrimitiveButton.story.tsx +1 -1
- package/src/primitives/PrimitiveButton/test/PrimitiveButton.spec.tsx +2 -3
- package/src/select/Select.tsx +1 -0
- package/src/test-utils/index.tsx +0 -1
- package/build/button/Button.js.map +0 -1
- package/build/button/Button.mjs.map +0 -1
- package/build/button/classMap.js +0 -42
- package/build/button/classMap.js.map +0 -1
- package/build/button/classMap.mjs +0 -39
- package/build/button/classMap.mjs.map +0 -1
- package/build/button/legacyUtils/legacyUtils.js.map +0 -1
- package/build/button/legacyUtils/legacyUtils.mjs.map +0 -1
- package/build/types/button/Button.d.ts.map +0 -1
- package/build/types/button/classMap.d.ts.map +0 -1
- package/build/types/button/legacyUtils/index.d.ts.map +0 -1
- package/build/types/button/legacyUtils/legacyUtils.d.ts.map +0 -1
- package/src/button/Button.story.tsx +0 -163
- /package/build/styles/button/{Button.css → LegacyButton/Button.css} +0 -0
- /package/build/types/button/{classMap.d.ts → LegacyButton/classMap.d.ts} +0 -0
- /package/build/types/button/{legacyUtils → LegacyButton/legacyUtils}/index.d.ts +0 -0
- /package/src/button/{Button.css → LegacyButton/Button.css} +0 -0
- /package/src/button/{__snapshots__ → LegacyButton/__snapshots__}/Button.spec.tsx.snap +0 -0
- /package/src/button/{legacyUtils → LegacyButton/legacyUtils}/index.ts +0 -0
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import { fireEvent, screen } from '@testing-library/react';
|
|
2
|
+
import { userEvent } from '@testing-library/user-event';
|
|
3
|
+
import Button from '..';
|
|
4
|
+
import messages from '../../../i18n/commonMessages/Button.messages';
|
|
5
|
+
import { render } from '../../../test-utils';
|
|
6
|
+
import { Freeze, ArrowRight } from '@transferwise/icons';
|
|
7
|
+
|
|
8
|
+
beforeAll(() => {
|
|
9
|
+
Object.defineProperty(window, 'matchMedia', {
|
|
10
|
+
writable: true,
|
|
11
|
+
value: jest.fn().mockImplementation((query: string) => ({
|
|
12
|
+
matches: false,
|
|
13
|
+
media: query,
|
|
14
|
+
onchange: null,
|
|
15
|
+
addListener: jest.fn(), // deprecated
|
|
16
|
+
removeListener: jest.fn(), // deprecated
|
|
17
|
+
addEventListener: jest.fn(),
|
|
18
|
+
removeEventListener: jest.fn(),
|
|
19
|
+
dispatchEvent: jest.fn(),
|
|
20
|
+
})),
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe('Button', () => {
|
|
25
|
+
const defaultProps = {
|
|
26
|
+
children: 'Click me',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const renderButton = (
|
|
30
|
+
props?: Partial<typeof defaultProps>,
|
|
31
|
+
locale = 'en',
|
|
32
|
+
localeMessages = messages,
|
|
33
|
+
) => {
|
|
34
|
+
return render(
|
|
35
|
+
<Button {...defaultProps} {...props} />,
|
|
36
|
+
// @ts-expect-error: props be missing properties from type
|
|
37
|
+
{ locale, messages: localeMessages },
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
it('renders a button by default', () => {
|
|
42
|
+
renderButton();
|
|
43
|
+
expect(screen.getByRole('button')).toBeInTheDocument();
|
|
44
|
+
expect(screen.getByRole('button')).toHaveTextContent('Click me');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('applies the correct classes based on props', () => {
|
|
48
|
+
const props = {
|
|
49
|
+
...defaultProps,
|
|
50
|
+
className: 'custom-class',
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
renderButton(props);
|
|
54
|
+
|
|
55
|
+
const button = screen.getByRole('button');
|
|
56
|
+
expect(button).toHaveClass('wds-Button');
|
|
57
|
+
expect(button).toHaveClass('custom-class');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('disables the button when disabled is true', () => {
|
|
61
|
+
const props = {
|
|
62
|
+
...defaultProps,
|
|
63
|
+
disabled: true,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
renderButton(props);
|
|
67
|
+
|
|
68
|
+
const button = screen.getByRole('button');
|
|
69
|
+
expect(button).toHaveClass('wds-Button--disabled');
|
|
70
|
+
expect(button).toBeDisabled();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('calls onClick when button is clicked', async () => {
|
|
74
|
+
const handleClick = jest.fn();
|
|
75
|
+
const props = {
|
|
76
|
+
...defaultProps,
|
|
77
|
+
onClick: handleClick,
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
renderButton(props);
|
|
81
|
+
|
|
82
|
+
const button = screen.getByRole('button');
|
|
83
|
+
await userEvent.click(button);
|
|
84
|
+
expect(handleClick).toHaveBeenCalledTimes(1);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('calls onFocus when button is focused', () => {
|
|
88
|
+
const handleFocus = jest.fn();
|
|
89
|
+
const props = {
|
|
90
|
+
...defaultProps,
|
|
91
|
+
onFocus: handleFocus,
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
renderButton(props);
|
|
95
|
+
|
|
96
|
+
const button = screen.getByRole('button');
|
|
97
|
+
fireEvent.focus(button);
|
|
98
|
+
expect(handleFocus).toHaveBeenCalledTimes(1);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('calls onKeyDown when a key is pressed', async () => {
|
|
102
|
+
const handleKeyDown = jest.fn();
|
|
103
|
+
const props = {
|
|
104
|
+
...defaultProps,
|
|
105
|
+
onKeyDown: handleKeyDown,
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
renderButton(props);
|
|
109
|
+
|
|
110
|
+
const button = screen.getByRole('button');
|
|
111
|
+
await userEvent.type(button, '{enter}');
|
|
112
|
+
expect(handleKeyDown).toHaveBeenCalledTimes(1);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('calls onBlur when button loses focus', () => {
|
|
116
|
+
const handleBlur = jest.fn();
|
|
117
|
+
const props = {
|
|
118
|
+
...defaultProps,
|
|
119
|
+
onBlur: handleBlur,
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
renderButton(props);
|
|
123
|
+
|
|
124
|
+
const button = screen.getByRole('button');
|
|
125
|
+
fireEvent.blur(button);
|
|
126
|
+
expect(handleBlur).toHaveBeenCalledTimes(1);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('calls onMouseEnter when mouse enters', async () => {
|
|
130
|
+
const handleMouseEnter = jest.fn();
|
|
131
|
+
const props = {
|
|
132
|
+
...defaultProps,
|
|
133
|
+
onMouseEnter: handleMouseEnter,
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
renderButton(props);
|
|
137
|
+
|
|
138
|
+
const button = screen.getByRole('button');
|
|
139
|
+
await userEvent.hover(button);
|
|
140
|
+
expect(handleMouseEnter).toHaveBeenCalledTimes(1);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('calls onMouseLeave when mouse leaves', async () => {
|
|
144
|
+
const handleMouseLeave = jest.fn();
|
|
145
|
+
const props = {
|
|
146
|
+
...defaultProps,
|
|
147
|
+
onMouseLeave: handleMouseLeave,
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
renderButton(props);
|
|
151
|
+
|
|
152
|
+
const button = screen.getByRole('button');
|
|
153
|
+
await userEvent.unhover(button);
|
|
154
|
+
expect(handleMouseLeave).toHaveBeenCalledTimes(1);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('sets data-testid attribute', () => {
|
|
158
|
+
const props = {
|
|
159
|
+
...defaultProps,
|
|
160
|
+
testId: 'custom-id',
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
renderButton(props);
|
|
164
|
+
|
|
165
|
+
const button = screen.getByTestId('custom-id');
|
|
166
|
+
expect(button).toBeInTheDocument();
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('sets the type attribute to submit', () => {
|
|
170
|
+
const props = {
|
|
171
|
+
...defaultProps,
|
|
172
|
+
type: 'submit',
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
renderButton(props);
|
|
176
|
+
|
|
177
|
+
const button = screen.getByRole('button');
|
|
178
|
+
expect(button).toHaveAttribute('type', 'submit');
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('sets the type attribute to reset', () => {
|
|
182
|
+
const props = {
|
|
183
|
+
...defaultProps,
|
|
184
|
+
type: 'reset',
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
renderButton(props);
|
|
188
|
+
|
|
189
|
+
const button = screen.getByRole('button');
|
|
190
|
+
expect(button).toHaveAttribute('type', 'reset');
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('sets the type attribute to button by default', () => {
|
|
194
|
+
renderButton();
|
|
195
|
+
const button = screen.getByRole('button');
|
|
196
|
+
expect(button).toHaveAttribute('type', 'button');
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('displays the aria-label in Spanish when loading', () => {
|
|
200
|
+
const props = {
|
|
201
|
+
...defaultProps,
|
|
202
|
+
loading: true,
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
const spanishMessages = {
|
|
206
|
+
...messages,
|
|
207
|
+
'neptune.Button.loadingAriaLabel': 'cargando',
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
renderButton(props, 'es', spanishMessages);
|
|
211
|
+
|
|
212
|
+
const button = screen.getByRole('button');
|
|
213
|
+
expect(button).toHaveAttribute('aria-label', 'cargando');
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('displays with one avatar', () => {
|
|
217
|
+
const props = {
|
|
218
|
+
...defaultProps,
|
|
219
|
+
avatars: [{ asset: <Freeze /> }],
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
renderButton(props);
|
|
223
|
+
|
|
224
|
+
const avatar = screen.getByTestId('freeze-icon');
|
|
225
|
+
expect(avatar).toBeInTheDocument();
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it('displays with one avatar and no left icon', () => {
|
|
229
|
+
const props = {
|
|
230
|
+
...defaultProps,
|
|
231
|
+
avatars: [{ asset: <Freeze /> }],
|
|
232
|
+
iconLeft: ArrowRight,
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
renderButton(props);
|
|
236
|
+
|
|
237
|
+
const avatar = screen.getByTestId('freeze-icon');
|
|
238
|
+
|
|
239
|
+
expect(avatar).toBeInTheDocument();
|
|
240
|
+
expect(screen.queryByTestId('arrow-left-icon')).not.toBeInTheDocument();
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it('displays with two avatars', () => {
|
|
244
|
+
const props = {
|
|
245
|
+
...defaultProps,
|
|
246
|
+
avatars: [{ asset: <Freeze /> }, { asset: <Freeze /> }],
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
renderButton(props);
|
|
250
|
+
|
|
251
|
+
const avatars = screen.getAllByTestId('freeze-icon');
|
|
252
|
+
avatars.forEach((avatar) => {
|
|
253
|
+
expect(avatar).toBeInTheDocument();
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it('displays with avatar and icon', () => {
|
|
258
|
+
const props = {
|
|
259
|
+
...defaultProps,
|
|
260
|
+
avatars: [{ asset: <Freeze /> }],
|
|
261
|
+
iconRight: ArrowRight,
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
renderButton(props);
|
|
265
|
+
|
|
266
|
+
const iconRight = screen.getByTestId('arrow-right-icon');
|
|
267
|
+
const avatar = screen.getByTestId('freeze-icon');
|
|
268
|
+
|
|
269
|
+
expect(avatar).toBeInTheDocument();
|
|
270
|
+
expect(iconRight).toHaveClass('wds-Button-icon');
|
|
271
|
+
expect(iconRight).toHaveClass('wds-Button-icon--right');
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it('displays with a profile name', () => {
|
|
275
|
+
const props = {
|
|
276
|
+
...defaultProps,
|
|
277
|
+
avatars: [{ profileName: 'John Doe' }],
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
renderButton(props);
|
|
281
|
+
|
|
282
|
+
const avatar = screen.getByText('JD');
|
|
283
|
+
expect(avatar).toBeInTheDocument();
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it('displays with a profile image', () => {
|
|
287
|
+
const props = {
|
|
288
|
+
...defaultProps,
|
|
289
|
+
avatars: [{ imgSrc: '../avatar-rectangle-fox.webp' }],
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
renderButton(props);
|
|
293
|
+
|
|
294
|
+
const avatar = screen.getByRole('presentation');
|
|
295
|
+
expect(avatar).toHaveAttribute('src', '../avatar-rectangle-fox.webp');
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it('displays with one icon', () => {
|
|
299
|
+
const props = {
|
|
300
|
+
...defaultProps,
|
|
301
|
+
iconRight: ArrowRight,
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
renderButton(props);
|
|
305
|
+
|
|
306
|
+
const iconRight = screen.getByTestId('arrow-right-icon');
|
|
307
|
+
expect(iconRight).toHaveClass('wds-Button-icon');
|
|
308
|
+
expect(iconRight).toHaveClass('wds-Button-icon--right');
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
it('displays with two icons', () => {
|
|
312
|
+
const props = {
|
|
313
|
+
...defaultProps,
|
|
314
|
+
iconRight: ArrowRight,
|
|
315
|
+
iconLeft: Freeze,
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
renderButton(props);
|
|
319
|
+
|
|
320
|
+
const iconRight = screen.getByTestId('arrow-right-icon');
|
|
321
|
+
const iconLeft = screen.getByTestId('freeze-icon');
|
|
322
|
+
|
|
323
|
+
expect(iconRight).toHaveClass('wds-Button-icon');
|
|
324
|
+
expect(iconRight).toHaveClass('wds-Button-icon--right');
|
|
325
|
+
expect(iconLeft).toHaveClass('wds-Button-icon');
|
|
326
|
+
expect(iconLeft).toHaveClass('wds-Button-icon--left');
|
|
327
|
+
});
|
|
328
|
+
});
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { createRef } from 'react';
|
|
2
2
|
|
|
3
|
-
import { ControlType, Type, Priority, Size } from '
|
|
4
|
-
import { render, screen, userEvent } from '
|
|
3
|
+
import { ControlType, Type, Priority, Size } from '../../common';
|
|
4
|
+
import { render, screen, userEvent } from '../../test-utils';
|
|
5
5
|
|
|
6
6
|
import Button from '.';
|
|
7
|
-
import messages from '
|
|
7
|
+
import messages from '../../i18n/commonMessages/Button.messages';
|
|
8
8
|
import { ButtonReferenceType } from './Button';
|
|
9
9
|
|
|
10
10
|
const { ACCENT, POSITIVE, NEGATIVE } = ControlType;
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { userEvent, within, fn, expect } from '@storybook/test';
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
|
|
5
|
+
import Button from '..';
|
|
6
|
+
|
|
7
|
+
const withContainer = (Story: any) => (
|
|
8
|
+
<div
|
|
9
|
+
style={{
|
|
10
|
+
display: 'flex',
|
|
11
|
+
flexDirection: 'initial',
|
|
12
|
+
justifyContent: 'center',
|
|
13
|
+
flexFlow: 'column',
|
|
14
|
+
alignItems: 'center',
|
|
15
|
+
}}
|
|
16
|
+
>
|
|
17
|
+
<Story />
|
|
18
|
+
</div>
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
const meta: Meta<typeof Button> = {
|
|
22
|
+
component: Button,
|
|
23
|
+
title: 'Actions/Button/Legacy',
|
|
24
|
+
args: {
|
|
25
|
+
children: 'Button text',
|
|
26
|
+
loading: false,
|
|
27
|
+
type: undefined,
|
|
28
|
+
onClick: fn(),
|
|
29
|
+
onBlur: fn(),
|
|
30
|
+
onFocus: fn(),
|
|
31
|
+
href: 'https://example.com',
|
|
32
|
+
},
|
|
33
|
+
argTypes: {
|
|
34
|
+
as: {
|
|
35
|
+
control: {
|
|
36
|
+
type: 'select',
|
|
37
|
+
options: ['button', 'a'],
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
type: {
|
|
41
|
+
type: {
|
|
42
|
+
name: 'enum',
|
|
43
|
+
value: ['accent', 'positive', 'negative'],
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
size: {
|
|
47
|
+
type: {
|
|
48
|
+
name: 'enum',
|
|
49
|
+
value: ['xs', 'sm', 'md', 'lg'],
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
priority: {
|
|
53
|
+
type: {
|
|
54
|
+
name: 'enum',
|
|
55
|
+
value: ['primary', 'secondary', 'tertiary'],
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
appearance: {
|
|
59
|
+
table: {
|
|
60
|
+
disable: true,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
iconLeft: {
|
|
64
|
+
table: {
|
|
65
|
+
disable: true,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
iconRight: {
|
|
69
|
+
table: {
|
|
70
|
+
disable: true,
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
avatars: {
|
|
74
|
+
table: {
|
|
75
|
+
disable: true,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
'data-testid': {
|
|
79
|
+
table: {
|
|
80
|
+
disable: true,
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
tags: ['autodocs'],
|
|
85
|
+
decorators: [withContainer],
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export default meta;
|
|
89
|
+
|
|
90
|
+
type Story = StoryObj<typeof Button>;
|
|
91
|
+
|
|
92
|
+
export const Basic: Story = {};
|
|
93
|
+
|
|
94
|
+
export const Secondary: Story = {
|
|
95
|
+
args: {
|
|
96
|
+
type: 'accent',
|
|
97
|
+
priority: 'secondary',
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export const Tertiary: Story = {
|
|
102
|
+
args: {
|
|
103
|
+
type: 'accent',
|
|
104
|
+
priority: 'tertiary',
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export const Negative: Story = {
|
|
109
|
+
args: {
|
|
110
|
+
type: 'negative',
|
|
111
|
+
priority: 'primary',
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export const Loading: Story = {
|
|
116
|
+
args: {
|
|
117
|
+
loading: true,
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export const Variants: Story = {
|
|
122
|
+
render: () => {
|
|
123
|
+
return (
|
|
124
|
+
<div className="d-flex flex-column p-b-2 align-items-start">
|
|
125
|
+
<div className="d-flex flex-row p-b-2" style={{ gap: 'var(--size-16)' }}>
|
|
126
|
+
<Button type="accent" priority="primary">
|
|
127
|
+
Primary Accent
|
|
128
|
+
</Button>
|
|
129
|
+
<Button type="accent" priority="secondary">
|
|
130
|
+
Secondary Accent
|
|
131
|
+
</Button>
|
|
132
|
+
<Button type="accent" priority="tertiary">
|
|
133
|
+
Tertiary Accent
|
|
134
|
+
</Button>
|
|
135
|
+
</div>
|
|
136
|
+
<div className="d-flex flex-row p-b-2" style={{ gap: 'var(--size-16)' }}>
|
|
137
|
+
<Button type="positive" priority="primary">
|
|
138
|
+
Primary Positive
|
|
139
|
+
</Button>
|
|
140
|
+
<Button type="positive" priority="secondary">
|
|
141
|
+
Secondary Accent
|
|
142
|
+
</Button>
|
|
143
|
+
</div>
|
|
144
|
+
<div className="d-flex flex-row flex- p-b-2" style={{ gap: 'var(--size-16)' }}>
|
|
145
|
+
<Button type="negative" priority="primary">
|
|
146
|
+
Primary Negative
|
|
147
|
+
</Button>
|
|
148
|
+
<Button type="negative" priority="secondary">
|
|
149
|
+
Secondary Negative
|
|
150
|
+
</Button>
|
|
151
|
+
</div>
|
|
152
|
+
<div className="d-flex flex-row p-b-1" style={{ gap: 'var(--size-16)' }}>
|
|
153
|
+
<Button type="accent" priority="primary" disabled>
|
|
154
|
+
Button Disabled
|
|
155
|
+
</Button>
|
|
156
|
+
<Button type="accent" priority="secondary" disabled>
|
|
157
|
+
Button Disabled
|
|
158
|
+
</Button>
|
|
159
|
+
<Button type="accent" priority="tertiary" disabled>
|
|
160
|
+
Button Disabled
|
|
161
|
+
</Button>
|
|
162
|
+
</div>
|
|
163
|
+
</div>
|
|
164
|
+
);
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const wait = async (duration = 500) =>
|
|
169
|
+
new Promise<void>((resolve) => {
|
|
170
|
+
setTimeout(resolve, duration);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
export const Focused: Story = {
|
|
174
|
+
play: async ({ canvasElement }: { canvasElement: HTMLElement }) => {
|
|
175
|
+
const canvas = within(canvasElement);
|
|
176
|
+
const button = canvas.getByRole('button');
|
|
177
|
+
await userEvent.tab();
|
|
178
|
+
await expect(button).toHaveFocus();
|
|
179
|
+
await expect(button).toHaveTextContent('Focused!');
|
|
180
|
+
},
|
|
181
|
+
render: function Render(args: React.ComponentProps<typeof Button>) {
|
|
182
|
+
const [focused, setFocused] = useState(false);
|
|
183
|
+
|
|
184
|
+
return (
|
|
185
|
+
<Button {...args} onFocus={() => setFocused(true)}>
|
|
186
|
+
{focused ? 'Focused!' : 'Button text'}
|
|
187
|
+
</Button>
|
|
188
|
+
);
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
export const SocialMedia: Story = {
|
|
193
|
+
render: () => {
|
|
194
|
+
return (
|
|
195
|
+
<>
|
|
196
|
+
<div className="m-b-2">
|
|
197
|
+
<button type="button" className="btn btn-google">
|
|
198
|
+
Login with Google
|
|
199
|
+
</button>
|
|
200
|
+
</div>
|
|
201
|
+
<div className="m-b-2">
|
|
202
|
+
<button type="button" className="btn btn-facebook">
|
|
203
|
+
Login with Facebook
|
|
204
|
+
</button>
|
|
205
|
+
</div>
|
|
206
|
+
<div className="m-b-2">
|
|
207
|
+
<button type="button" className="btn btn-lg btn-facebook">
|
|
208
|
+
Large Button
|
|
209
|
+
</button>
|
|
210
|
+
</div>
|
|
211
|
+
<div className="m-b-2">
|
|
212
|
+
<button type="button" className="btn btn-block btn-facebook">
|
|
213
|
+
Block Button
|
|
214
|
+
</button>
|
|
215
|
+
</div>
|
|
216
|
+
<div className="m-b-2">
|
|
217
|
+
<button type="button" className="btn btn-lg btn-block btn-facebook">
|
|
218
|
+
Large Block Button
|
|
219
|
+
</button>
|
|
220
|
+
</div>
|
|
221
|
+
</>
|
|
222
|
+
);
|
|
223
|
+
},
|
|
224
|
+
};
|
|
@@ -16,10 +16,10 @@ import {
|
|
|
16
16
|
SizeSmall,
|
|
17
17
|
SizeMedium,
|
|
18
18
|
SizeLarge,
|
|
19
|
-
} from '
|
|
20
|
-
import ProcessIndicator from '
|
|
19
|
+
} from '../../common';
|
|
20
|
+
import ProcessIndicator from '../../processIndicator';
|
|
21
21
|
|
|
22
|
-
import messages from '
|
|
22
|
+
import messages from '../../i18n/commonMessages/Button.messages';
|
|
23
23
|
import { typeClassMap, priorityClassMap } from './classMap';
|
|
24
24
|
import { establishNewPriority, establishNewType, logDeprecationNotices } from './legacyUtils';
|
|
25
25
|
|
|
@@ -33,20 +33,22 @@ type CommonProps = {
|
|
|
33
33
|
block?: boolean;
|
|
34
34
|
disabled?: boolean;
|
|
35
35
|
loading?: boolean;
|
|
36
|
+
/** @deprecated */
|
|
36
37
|
type?: ControlTypeAccent | ControlTypeNegative | ControlTypePositive | DeprecatedTypes | null;
|
|
37
38
|
priority?: PriorityPrimary | PrioritySecondary | PriorityTertiary | null;
|
|
38
39
|
size?: SizeSmall | SizeMedium | SizeLarge | DeprecatedSizes;
|
|
40
|
+
htmlType?: 'submit' | 'reset' | 'button'; // Add this line
|
|
39
41
|
};
|
|
40
42
|
|
|
41
|
-
type ButtonProps = CommonProps &
|
|
43
|
+
export type ButtonProps = CommonProps &
|
|
42
44
|
Omit<React.ComponentPropsWithRef<'button'>, 'type'> & {
|
|
43
45
|
as?: 'button';
|
|
44
|
-
htmlType?: 'submit' | 'reset' | 'button';
|
|
45
46
|
};
|
|
46
47
|
|
|
47
|
-
type AnchorProps = CommonProps &
|
|
48
|
+
export type AnchorProps = CommonProps &
|
|
48
49
|
Omit<React.ComponentPropsWithRef<'a'>, 'type'> & {
|
|
49
50
|
as?: 'a';
|
|
51
|
+
href?: string;
|
|
50
52
|
};
|
|
51
53
|
|
|
52
54
|
export type Props = ButtonProps | AnchorProps;
|
|
@@ -68,7 +70,7 @@ const Button = forwardRef<ButtonReferenceType, Props>(
|
|
|
68
70
|
onClick,
|
|
69
71
|
...rest
|
|
70
72
|
}: Props,
|
|
71
|
-
|
|
73
|
+
ref,
|
|
72
74
|
) => {
|
|
73
75
|
const intl = useIntl();
|
|
74
76
|
|
|
@@ -132,7 +134,7 @@ const Button = forwardRef<ButtonReferenceType, Props>(
|
|
|
132
134
|
|
|
133
135
|
return (
|
|
134
136
|
<Element
|
|
135
|
-
ref={
|
|
137
|
+
ref={ref as React.Ref<ButtonReferenceType>}
|
|
136
138
|
className={classes}
|
|
137
139
|
onClick={handleClick(onClick)}
|
|
138
140
|
{...props}
|
|
@@ -153,4 +155,6 @@ const Button = forwardRef<ButtonReferenceType, Props>(
|
|
|
153
155
|
},
|
|
154
156
|
);
|
|
155
157
|
|
|
158
|
+
Button.displayName = 'Button';
|
|
159
|
+
|
|
156
160
|
export default Button;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
|
-
import { ControlType, Priority, Size, Type } from '
|
|
3
|
-
import { cleanup } from '
|
|
2
|
+
import { ControlType, Priority, Size, Type } from '../../../common';
|
|
3
|
+
import { cleanup } from '../../../test-utils';
|
|
4
4
|
|
|
5
5
|
import { establishNewPriority, establishNewType, logDeprecationNotices } from '.';
|
|
6
6
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ControlType, Priority, Size, Type } from '
|
|
2
|
-
import { logActionRequired, logActionRequiredIf } from '
|
|
1
|
+
import { ControlType, Priority, Size, Type } from '../../../common';
|
|
2
|
+
import { logActionRequired, logActionRequiredIf } from '../../../utilities';
|
|
3
3
|
|
|
4
4
|
const deprecatedTypeMap: Record<Type, ControlType> = {
|
|
5
5
|
[Type.PRIMARY]: ControlType.ACCENT,
|
package/src/button/index.ts
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
export { default } from './
|
|
2
|
-
|
|
3
|
-
export type { Props as ButtonProps } from './Button';
|
|
1
|
+
export { default } from './src';
|
|
2
|
+
export * from './src';
|