@transferwise/components 0.0.0-experimental-6fa7ff3 → 0.0.0-experimental-f341b41
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/avatarView/AvatarView.js +1 -12
- package/build/avatarView/AvatarView.js.map +1 -1
- package/build/avatarView/AvatarView.mjs +1 -12
- package/build/avatarView/AvatarView.mjs.map +1 -1
- package/build/circularButton/CircularButton.js +21 -18
- package/build/circularButton/CircularButton.js.map +1 -1
- package/build/circularButton/CircularButton.mjs +22 -19
- package/build/circularButton/CircularButton.mjs.map +1 -1
- package/build/definitionList/DefinitionList.js.map +1 -1
- package/build/definitionList/DefinitionList.mjs.map +1 -1
- package/build/i18n/de.json +0 -1
- package/build/i18n/de.json.js +0 -1
- package/build/i18n/de.json.js.map +1 -1
- package/build/i18n/de.json.mjs +0 -1
- package/build/i18n/de.json.mjs.map +1 -1
- package/build/i18n/it.json +0 -1
- package/build/i18n/it.json.js +0 -1
- package/build/i18n/it.json.js.map +1 -1
- package/build/i18n/it.json.mjs +0 -1
- package/build/i18n/it.json.mjs.map +1 -1
- package/build/i18n/th.json +0 -1
- package/build/i18n/th.json.js +0 -1
- package/build/i18n/th.json.js.map +1 -1
- package/build/i18n/th.json.mjs +0 -1
- package/build/i18n/th.json.mjs.map +1 -1
- package/build/main.css +180 -47
- package/build/styles/button/Button.css +22 -30
- package/build/styles/button/Button.vars.css +1 -18
- package/build/styles/circularButton/CircularButton.css +158 -17
- package/build/styles/main.css +180 -47
- package/build/types/avatarView/AvatarView.d.ts.map +1 -1
- package/build/types/circularButton/CircularButton.d.ts +4 -11
- package/build/types/circularButton/CircularButton.d.ts.map +1 -1
- package/build/types/definitionList/DefinitionList.d.ts +2 -1
- package/build/types/definitionList/DefinitionList.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/avatarView/AvatarView.tsx +1 -15
- package/src/button/Button.css +22 -30
- package/src/button/Button.less +30 -6
- package/src/button/Button.vars.css +1 -18
- package/src/button/Button.vars.less +1 -24
- package/src/circularButton/CircularButton.css +158 -17
- package/src/circularButton/CircularButton.less +91 -22
- package/src/circularButton/CircularButton.story.tsx +24 -45
- package/src/circularButton/CircularButton.tsx +25 -38
- package/src/circularButton/_button-label-states.less +34 -0
- package/src/dateInput/DateInput.spec.tsx +26 -45
- package/src/definitionList/DefinitionList.spec.js +91 -0
- package/src/definitionList/DefinitionList.story.tsx +57 -57
- package/src/definitionList/DefinitionList.tsx +1 -1
- package/src/i18n/de.json +0 -1
- package/src/i18n/it.json +0 -1
- package/src/i18n/th.json +0 -1
- package/src/iconButton/IconButton.story.tsx +6 -6
- package/src/main.css +180 -47
- package/src/slidingPanel/SlidingPanel.spec.js +56 -0
- package/src/slidingPanel/SlidingPanel.spec.tsx +0 -69
|
@@ -5,16 +5,14 @@ import { ControlType, Priority } from '../common';
|
|
|
5
5
|
import { Meta, StoryObj } from '@storybook/react';
|
|
6
6
|
import CircularButton from './CircularButton';
|
|
7
7
|
import { storyConfig } from '../test-utils';
|
|
8
|
-
import Title from '../title';
|
|
9
|
-
import Body from '../body';
|
|
10
8
|
|
|
11
9
|
export default {
|
|
12
10
|
component: CircularButton,
|
|
13
11
|
title: 'Actions/CircularButton',
|
|
14
|
-
tags: ['autodocs'],
|
|
15
12
|
args: {
|
|
16
13
|
children: 'Button text',
|
|
17
|
-
icon
|
|
14
|
+
// Needs to be cast because we're mapping icon names to components
|
|
15
|
+
icon: 'Freeze' as unknown as React.ReactElement,
|
|
18
16
|
},
|
|
19
17
|
argTypes: {
|
|
20
18
|
icon: {
|
|
@@ -30,8 +28,8 @@ type Story = StoryObj<typeof CircularButton>;
|
|
|
30
28
|
|
|
31
29
|
export const Basic: Story = {
|
|
32
30
|
args: {
|
|
33
|
-
priority:
|
|
34
|
-
type:
|
|
31
|
+
priority: Priority.PRIMARY,
|
|
32
|
+
type: ControlType.ACCENT,
|
|
35
33
|
disabled: false,
|
|
36
34
|
},
|
|
37
35
|
};
|
|
@@ -43,45 +41,26 @@ export const All: Story = {
|
|
|
43
41
|
render: (props) => {
|
|
44
42
|
return (
|
|
45
43
|
<>
|
|
46
|
-
<
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
<
|
|
53
|
-
<CircularButton {...props} priority=
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
<
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
<
|
|
63
|
-
<CircularButton {...props}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
<Title type="title-body" className="m-y-2">
|
|
67
|
-
Accent (Deprecated)
|
|
68
|
-
</Title>
|
|
69
|
-
<Body>
|
|
70
|
-
<CircularButton {...props} priority="primary" type="accent" />
|
|
71
|
-
<CircularButton {...props} priority="secondary" type="accent" />
|
|
72
|
-
<CircularButton {...props} priority="primary" type="accent" disabled />
|
|
73
|
-
<CircularButton {...props} priority="secondary" type="accent" disabled />
|
|
74
|
-
</Body>
|
|
75
|
-
|
|
76
|
-
<Title type="title-body" className="m-y-2">
|
|
77
|
-
Positive (Deprecated)
|
|
78
|
-
</Title>
|
|
79
|
-
<Body>
|
|
80
|
-
<CircularButton {...props} priority="primary" type="positive" />
|
|
81
|
-
<CircularButton {...props} priority="secondary" type="positive" />
|
|
82
|
-
<CircularButton {...props} priority="primary" type="positive" disabled />
|
|
83
|
-
<CircularButton {...props} priority="secondary" type="positive" disabled />
|
|
84
|
-
</Body>
|
|
44
|
+
<div className="m-b-2">
|
|
45
|
+
<div className="title-4 m-b-1">Accent</div>
|
|
46
|
+
<CircularButton {...props} priority={Priority.PRIMARY} type={ControlType.ACCENT} />
|
|
47
|
+
<CircularButton {...props} priority={Priority.SECONDARY} type={ControlType.ACCENT} />
|
|
48
|
+
</div>
|
|
49
|
+
<div className="m-b-2">
|
|
50
|
+
<div className="title-4 m-b-1">Positive</div>
|
|
51
|
+
<CircularButton {...props} priority={Priority.PRIMARY} type={ControlType.POSITIVE} />
|
|
52
|
+
<CircularButton {...props} priority={Priority.SECONDARY} type={ControlType.POSITIVE} />
|
|
53
|
+
</div>
|
|
54
|
+
<div className="m-b-2">
|
|
55
|
+
<div className="title-4 m-b-1">Negative</div>
|
|
56
|
+
<CircularButton {...props} priority={Priority.PRIMARY} type={ControlType.NEGATIVE} />
|
|
57
|
+
<CircularButton {...props} priority={Priority.SECONDARY} type={ControlType.NEGATIVE} />
|
|
58
|
+
</div>
|
|
59
|
+
<div className="m-b-2">
|
|
60
|
+
<div className="title-4 m-b-1">Disabled</div>
|
|
61
|
+
<CircularButton {...props} disabled />
|
|
62
|
+
<CircularButton {...props} priority={Priority.SECONDARY} disabled />
|
|
63
|
+
</div>
|
|
85
64
|
</>
|
|
86
65
|
);
|
|
87
66
|
},
|
|
@@ -1,28 +1,20 @@
|
|
|
1
1
|
import { clsx } from 'clsx';
|
|
2
|
+
import { cloneElement } from 'react';
|
|
2
3
|
|
|
3
4
|
import Body from '../body/Body';
|
|
5
|
+
import { typeClassMap, priorityClassMap } from '../button/classMap';
|
|
4
6
|
import { Breakpoint, ControlType, Priority, Typography } from '../common';
|
|
5
|
-
import
|
|
7
|
+
import Circle from '../common/circle';
|
|
6
8
|
import { useMedia } from '../common/hooks/useMedia';
|
|
7
9
|
|
|
8
|
-
/**
|
|
9
|
-
* @deprecated use `'default'` instead
|
|
10
|
-
*/
|
|
11
|
-
type DeprecatedTypes = `${ControlType.ACCENT | ControlType.POSITIVE}`;
|
|
12
|
-
|
|
13
10
|
export interface CircularButtonProps {
|
|
14
11
|
className?: string;
|
|
15
12
|
children: string;
|
|
16
13
|
disabled?: boolean;
|
|
17
|
-
icon: React.ReactElement<{ size?: unknown }
|
|
18
|
-
onClick?: React.MouseEventHandler<HTMLInputElement
|
|
19
|
-
React.MouseEventHandler<HTMLButtonElement> &
|
|
20
|
-
React.MouseEventHandler<HTMLAnchorElement>;
|
|
14
|
+
icon: React.ReactElement<{ size?: unknown }>;
|
|
15
|
+
onClick?: React.MouseEventHandler<HTMLInputElement>;
|
|
21
16
|
priority?: `${Priority.PRIMARY | Priority.SECONDARY}`;
|
|
22
|
-
|
|
23
|
-
* `"accent"` and `"positive"` values are **deprecated**, please use `"default"` instead
|
|
24
|
-
*/
|
|
25
|
-
type?: DeprecatedTypes | 'default' | `${ControlType.NEGATIVE}`;
|
|
17
|
+
type?: `${ControlType.ACCENT | ControlType.POSITIVE | ControlType.NEGATIVE}`;
|
|
26
18
|
}
|
|
27
19
|
|
|
28
20
|
const CircularButton = ({
|
|
@@ -30,35 +22,30 @@ const CircularButton = ({
|
|
|
30
22
|
children,
|
|
31
23
|
disabled,
|
|
32
24
|
icon,
|
|
33
|
-
onClick,
|
|
34
25
|
priority = Priority.PRIMARY,
|
|
35
|
-
type =
|
|
26
|
+
type = ControlType.ACCENT,
|
|
27
|
+
...rest
|
|
36
28
|
}: CircularButtonProps) => {
|
|
29
|
+
const classes = clsx('btn np-btn', 'm-b-1', typeClassMap[type], priorityClassMap[priority]);
|
|
30
|
+
|
|
31
|
+
const iconElement = Number(icon.props.size) !== 24 ? cloneElement(icon, { size: 24 }) : icon;
|
|
32
|
+
|
|
37
33
|
const isTinyViewport = useMedia(`(max-width: ${Breakpoint.ZOOM_400}px)`);
|
|
34
|
+
|
|
38
35
|
return (
|
|
39
|
-
<label
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
<IconButton
|
|
48
|
-
size={isTinyViewport ? 32 : 56}
|
|
49
|
-
priority={priority}
|
|
50
|
-
type={['accent', 'positive'].includes(type) ? 'default' : (type as IconButtonProps['type'])}
|
|
51
|
-
className={clsx('m-b-1')}
|
|
36
|
+
<label className={clsx('np-circular-btn', priority, type, disabled && 'disabled', className)}>
|
|
37
|
+
<Circle
|
|
38
|
+
as="input"
|
|
39
|
+
// @ts-expect-error it's input[type=button] element
|
|
40
|
+
type="button"
|
|
41
|
+
size={isTinyViewport ? 72 : 56}
|
|
42
|
+
aria-label={children}
|
|
43
|
+
className={classes}
|
|
52
44
|
disabled={disabled}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
<Body
|
|
58
|
-
as="span"
|
|
59
|
-
className={clsx('np-circular-btn-label', { disabled })}
|
|
60
|
-
type={Typography.BODY_DEFAULT_BOLD}
|
|
61
|
-
>
|
|
45
|
+
{...rest}
|
|
46
|
+
/>
|
|
47
|
+
{iconElement}
|
|
48
|
+
<Body as="span" className="np-circular-btn__label" type={Typography.BODY_DEFAULT_BOLD}>
|
|
62
49
|
{children}
|
|
63
50
|
</Body>
|
|
64
51
|
</label>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
.button-label-states(@prefix, @type, @normal, @hover, @active, @isModernTheme: false) {
|
|
2
|
+
.@{prefix}.@{type} {
|
|
3
|
+
.@{prefix}__label {
|
|
4
|
+
color: @normal;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
&:not(.disabled, :disabled):hover .@{prefix}__label {
|
|
8
|
+
color: @hover;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
&:active .@{prefix}__label,
|
|
12
|
+
input[type="button"]:active ~ .@{prefix}__label {
|
|
13
|
+
color: @active;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
&.secondary {
|
|
17
|
+
.tw-icon {
|
|
18
|
+
color: @normal;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
&:not(.disabled, :disabled):hover .tw-icon,
|
|
22
|
+
input[type="button"]:active + .tw-icon {
|
|
23
|
+
color: white;
|
|
24
|
+
& when (@isModernTheme = true) {
|
|
25
|
+
color: var(--color-interactive-control);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
&:active input[type="button"] + .tw-icon when (@isModernTheme = true) {
|
|
30
|
+
color: var(--color-interactive-control);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
+
import { screen, fireEvent } from '@testing-library/react';
|
|
2
|
+
import userEvent from '@testing-library/user-event';
|
|
1
3
|
import { DateInput, DateInputProps, Field } from '..';
|
|
2
|
-
import { mockMatchMedia, mockResizeObserver, render
|
|
3
|
-
|
|
4
|
-
mockMatchMedia();
|
|
5
|
-
mockResizeObserver();
|
|
4
|
+
import { mockMatchMedia, mockResizeObserver, render } from '../test-utils';
|
|
6
5
|
|
|
7
6
|
describe('Date Input Component', () => {
|
|
8
|
-
const props: DateInputProps = {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
const props: DateInputProps = { onChange: jest.fn() };
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
mockMatchMedia();
|
|
11
|
+
mockResizeObserver();
|
|
12
|
+
});
|
|
13
13
|
|
|
14
|
-
afterEach(
|
|
14
|
+
afterEach(() => {
|
|
15
|
+
jest.resetAllMocks();
|
|
16
|
+
});
|
|
15
17
|
|
|
16
18
|
describe('when initialised without a model', () => {
|
|
17
19
|
it('sets day field to empty', () => {
|
|
@@ -102,7 +104,7 @@ describe('Date Input Component', () => {
|
|
|
102
104
|
await userEvent.click(monthSelect);
|
|
103
105
|
await userEvent.click(screen.getByRole('option', { name: /January/ }));
|
|
104
106
|
expect(props.onChange).toHaveBeenCalledWith(null);
|
|
105
|
-
}
|
|
107
|
+
});
|
|
106
108
|
|
|
107
109
|
it('calls the onChange callback with null when changing the year but nothing else is filled out', async () => {
|
|
108
110
|
render(<DateInput {...props} />);
|
|
@@ -124,7 +126,7 @@ describe('Date Input Component', () => {
|
|
|
124
126
|
await userEvent.click(monthSelect);
|
|
125
127
|
await userEvent.click(screen.getByRole('option', { name: /January/ }));
|
|
126
128
|
expect(props.onChange).toHaveBeenCalledWith('2022-01-01');
|
|
127
|
-
}
|
|
129
|
+
});
|
|
128
130
|
|
|
129
131
|
it('calls the onChange callback with the correct value when changing the year', async () => {
|
|
130
132
|
render(<DateInput {...props} value="0122-12-1" />);
|
|
@@ -176,40 +178,19 @@ describe('Date Input Component', () => {
|
|
|
176
178
|
});
|
|
177
179
|
});
|
|
178
180
|
|
|
179
|
-
describe('
|
|
180
|
-
it('
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
<button type="button">starting point</button>
|
|
184
|
-
<DateInput {...props} />
|
|
185
|
-
</>,
|
|
186
|
-
);
|
|
187
|
-
await userEvent.tab();
|
|
188
|
-
await userEvent.tab();
|
|
189
|
-
await userEvent.tab({ shift: true });
|
|
190
|
-
expect(props.onFocus).toHaveBeenCalledTimes(1);
|
|
191
|
-
expect(props.onBlur).toHaveBeenCalledTimes(1);
|
|
192
|
-
});
|
|
181
|
+
describe('when switching from day input to year input', () => {
|
|
182
|
+
it('does not call onBlur nor onFocus', () => {
|
|
183
|
+
const onFocus = jest.fn();
|
|
184
|
+
const onBlur = jest.fn();
|
|
193
185
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
);
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
await userEvent.click(externalButton);
|
|
204
|
-
await userEvent.click(screen.getByRole('textbox', { name: /day/i }));
|
|
205
|
-
await userEvent.click(screen.getByRole('textbox', { name: /year/i }));
|
|
206
|
-
await userEvent.click(externalButton);
|
|
207
|
-
|
|
208
|
-
// 1 call is caused by the initial switch to the component,
|
|
209
|
-
// as reflected in `should propagate if focusing from or
|
|
210
|
-
// blurring to external component` test
|
|
211
|
-
expect(props.onFocus).toHaveBeenCalledTimes(1);
|
|
212
|
-
expect(props.onBlur).toHaveBeenCalledTimes(1);
|
|
186
|
+
render(<DateInput {...props} />);
|
|
187
|
+
const dayInput = screen.getByRole('textbox', { name: /day/i });
|
|
188
|
+
const yearInput = screen.getByRole('textbox', { name: /year/i });
|
|
189
|
+
fireEvent.focus(dayInput);
|
|
190
|
+
fireEvent.blur(dayInput);
|
|
191
|
+
fireEvent.focus(yearInput);
|
|
192
|
+
expect(onFocus).not.toHaveBeenCalled();
|
|
193
|
+
expect(onBlur).not.toHaveBeenCalled();
|
|
213
194
|
});
|
|
214
195
|
});
|
|
215
196
|
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { shallow, mount } from 'enzyme';
|
|
2
|
+
|
|
3
|
+
import { DefinitionList } from '..';
|
|
4
|
+
import { Layout } from '../common';
|
|
5
|
+
|
|
6
|
+
const {
|
|
7
|
+
VERTICAL_TWO_COLUMN,
|
|
8
|
+
VERTICAL_ONE_COLUMN,
|
|
9
|
+
HORIZONTAL_LEFT_ALIGNED,
|
|
10
|
+
HORIZONTAL_RIGHT_ALIGNED,
|
|
11
|
+
HORIZONTAL_JUSTIFIED,
|
|
12
|
+
} = Layout;
|
|
13
|
+
|
|
14
|
+
describe('DefinitionList', () => {
|
|
15
|
+
const someDefinitions = () => [{ title: 'First', value: 'first value', key: 'first' }, null];
|
|
16
|
+
|
|
17
|
+
const withLayout = (layout) =>
|
|
18
|
+
shallow(<DefinitionList layout={layout} definitions={someDefinitions()} />);
|
|
19
|
+
|
|
20
|
+
const listHasClass = (layout, className) =>
|
|
21
|
+
withLayout(layout).find('dl.tw-definition-list').hasClass(className);
|
|
22
|
+
|
|
23
|
+
const valueHasClass = (layout, className) =>
|
|
24
|
+
withLayout(layout).find('dl.tw-definition-list dd').hasClass(className);
|
|
25
|
+
|
|
26
|
+
it('applies correct flex class', () => {
|
|
27
|
+
const colClass = 'flex-column';
|
|
28
|
+
|
|
29
|
+
expect(listHasClass(VERTICAL_ONE_COLUMN, colClass)).toBe(true);
|
|
30
|
+
expect(listHasClass(VERTICAL_TWO_COLUMN, colClass)).toBe(true);
|
|
31
|
+
expect(listHasClass(HORIZONTAL_LEFT_ALIGNED, colClass)).toBe(true);
|
|
32
|
+
expect(listHasClass(HORIZONTAL_RIGHT_ALIGNED, colClass)).toBe(true);
|
|
33
|
+
expect(listHasClass(HORIZONTAL_JUSTIFIED, colClass)).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('applies correct class for vertical two-column layout', () => {
|
|
37
|
+
const colClass = 'tw-definition-list--columns flex-column flex-row--sm';
|
|
38
|
+
|
|
39
|
+
expect(listHasClass(VERTICAL_TWO_COLUMN, colClass)).toBe(true);
|
|
40
|
+
expect(listHasClass(VERTICAL_ONE_COLUMN, colClass)).toBe(false);
|
|
41
|
+
expect(listHasClass(HORIZONTAL_LEFT_ALIGNED, colClass)).toBe(false);
|
|
42
|
+
expect(listHasClass(HORIZONTAL_RIGHT_ALIGNED, colClass)).toBe(false);
|
|
43
|
+
expect(listHasClass(HORIZONTAL_JUSTIFIED, colClass)).toBe(false);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('applies correct class for horiztonal layouts', () => {
|
|
47
|
+
const rowClass = 'tw-definition-list--horizontal flex-column';
|
|
48
|
+
|
|
49
|
+
expect(listHasClass(VERTICAL_TWO_COLUMN, rowClass)).toBe(false);
|
|
50
|
+
expect(listHasClass(VERTICAL_ONE_COLUMN, rowClass)).toBe(false);
|
|
51
|
+
expect(listHasClass(HORIZONTAL_LEFT_ALIGNED, rowClass)).toBe(true);
|
|
52
|
+
expect(listHasClass(HORIZONTAL_RIGHT_ALIGNED, rowClass)).toBe(true);
|
|
53
|
+
expect(listHasClass(HORIZONTAL_JUSTIFIED, rowClass)).toBe(true);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('applies correct class for alignment', () => {
|
|
57
|
+
expect(valueHasClass(VERTICAL_TWO_COLUMN, 'd-flex justify-content-between')).toBe(true);
|
|
58
|
+
expect(valueHasClass(VERTICAL_ONE_COLUMN, 'd-flex justify-content-between')).toBe(true);
|
|
59
|
+
expect(valueHasClass(HORIZONTAL_LEFT_ALIGNED, 'd-flex justify-content-between')).toBe(true);
|
|
60
|
+
expect(valueHasClass(HORIZONTAL_RIGHT_ALIGNED, 'text-sm-right')).toBe(true);
|
|
61
|
+
expect(valueHasClass(HORIZONTAL_JUSTIFIED, 'text-sm-justify')).toBe(true);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('has muted text class on title and value when muted flag is passed', () => {
|
|
65
|
+
const muted = shallow(<DefinitionList muted definitions={someDefinitions()} />);
|
|
66
|
+
const notMuted = shallow(<DefinitionList definitions={someDefinitions()} />);
|
|
67
|
+
|
|
68
|
+
expect(muted.find('dl.tw-definition-list').hasClass('text-muted')).toBe(true);
|
|
69
|
+
expect(notMuted.find('dl.tw-definition-list').hasClass('text-muted')).toBe(false);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('shows action button when one is passed in', () => {
|
|
73
|
+
const buttonSpy = jest.fn();
|
|
74
|
+
|
|
75
|
+
const definitionList = mount(
|
|
76
|
+
<DefinitionList
|
|
77
|
+
definitions={[
|
|
78
|
+
{
|
|
79
|
+
title: 'Name',
|
|
80
|
+
value: 'Jenkins',
|
|
81
|
+
key: '1',
|
|
82
|
+
action: { label: 'A button', onClick: buttonSpy },
|
|
83
|
+
},
|
|
84
|
+
]}
|
|
85
|
+
/>,
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
definitionList.find('button').simulate('click');
|
|
89
|
+
expect(buttonSpy).toHaveBeenCalledTimes(1);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
@@ -1,29 +1,19 @@
|
|
|
1
1
|
import { action } from '@storybook/addon-actions';
|
|
2
|
+
import { select, text, boolean } from '@storybook/addon-knobs';
|
|
2
3
|
|
|
3
4
|
import { Layout } from '../common';
|
|
4
5
|
|
|
5
|
-
import DefinitionList
|
|
6
|
-
import { lorem10 } from '../test-utils';
|
|
7
|
-
import Section from '../section';
|
|
8
|
-
import Header from '../header';
|
|
6
|
+
import DefinitionList from './DefinitionList';
|
|
9
7
|
|
|
10
8
|
export default {
|
|
11
9
|
component: DefinitionList,
|
|
12
10
|
title: 'Typography/DefinitionList',
|
|
13
11
|
};
|
|
14
12
|
|
|
15
|
-
const layouts: DefinitionListLayout[] = [
|
|
16
|
-
Layout.VERTICAL_TWO_COLUMN,
|
|
17
|
-
Layout.VERTICAL_ONE_COLUMN,
|
|
18
|
-
Layout.HORIZONTAL_JUSTIFIED,
|
|
19
|
-
Layout.HORIZONTAL_LEFT_ALIGNED,
|
|
20
|
-
Layout.HORIZONTAL_RIGHT_ALIGNED,
|
|
21
|
-
];
|
|
22
|
-
|
|
23
13
|
const definitions = [
|
|
24
14
|
{
|
|
25
|
-
title: '
|
|
26
|
-
value: '
|
|
15
|
+
title: text('title', 'Editable title'),
|
|
16
|
+
value: text('value', 'Editable value'),
|
|
27
17
|
key: 'first',
|
|
28
18
|
},
|
|
29
19
|
{
|
|
@@ -33,57 +23,67 @@ const definitions = [
|
|
|
33
23
|
},
|
|
34
24
|
{
|
|
35
25
|
title: 'Long strings will wrap',
|
|
36
|
-
value:
|
|
26
|
+
value: 'And values with long words will eventuallybreakontothenextline',
|
|
37
27
|
key: 'third',
|
|
38
28
|
},
|
|
39
29
|
];
|
|
40
30
|
|
|
41
31
|
export const Basic = () => {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
32
|
+
const muted = boolean('muted', false);
|
|
33
|
+
const layout = select(
|
|
34
|
+
'layout',
|
|
35
|
+
[
|
|
36
|
+
Layout.VERTICAL_TWO_COLUMN,
|
|
37
|
+
Layout.VERTICAL_ONE_COLUMN,
|
|
38
|
+
Layout.HORIZONTAL_JUSTIFIED,
|
|
39
|
+
Layout.HORIZONTAL_LEFT_ALIGNED,
|
|
40
|
+
Layout.HORIZONTAL_RIGHT_ALIGNED,
|
|
41
|
+
],
|
|
42
|
+
Layout.HORIZONTAL_LEFT_ALIGNED,
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
return <DefinitionList layout={layout} muted={muted} definitions={definitions} />;
|
|
48
46
|
};
|
|
49
47
|
|
|
50
48
|
export const WithActionButtons = () => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
title: 'Action buttons are useful',
|
|
63
|
-
value: lorem10,
|
|
64
|
-
key: 'fourth',
|
|
65
|
-
action: {
|
|
66
|
-
label: 'Epic button',
|
|
67
|
-
onClick: action(lorem10),
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
title: 'tiny',
|
|
72
|
-
value: 'tiny',
|
|
73
|
-
key: 'fifth',
|
|
74
|
-
action: {
|
|
75
|
-
label: 'Epic button',
|
|
76
|
-
onClick: action(lorem10),
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
]}
|
|
80
|
-
/>
|
|
81
|
-
</Section>
|
|
82
|
-
))}
|
|
83
|
-
</>
|
|
49
|
+
const muted = boolean('muted', false);
|
|
50
|
+
const layout = select(
|
|
51
|
+
'layout',
|
|
52
|
+
[
|
|
53
|
+
Layout.VERTICAL_TWO_COLUMN,
|
|
54
|
+
Layout.VERTICAL_ONE_COLUMN,
|
|
55
|
+
Layout.HORIZONTAL_JUSTIFIED,
|
|
56
|
+
Layout.HORIZONTAL_LEFT_ALIGNED,
|
|
57
|
+
Layout.HORIZONTAL_RIGHT_ALIGNED,
|
|
58
|
+
],
|
|
59
|
+
Layout.HORIZONTAL_LEFT_ALIGNED,
|
|
84
60
|
);
|
|
85
|
-
};
|
|
86
61
|
|
|
87
|
-
|
|
88
|
-
|
|
62
|
+
return (
|
|
63
|
+
<DefinitionList
|
|
64
|
+
layout={layout}
|
|
65
|
+
muted={muted}
|
|
66
|
+
definitions={[
|
|
67
|
+
...definitions,
|
|
68
|
+
{
|
|
69
|
+
title: 'Action buttons are useful',
|
|
70
|
+
value: 'You can do all kinds of neat things with actions buttons!',
|
|
71
|
+
key: 'fourth',
|
|
72
|
+
action: {
|
|
73
|
+
label: 'Epic button',
|
|
74
|
+
onClick: action('Probably the best action event you have ever seen, in the world!'),
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
title: 'tiny',
|
|
79
|
+
value: 'tiny',
|
|
80
|
+
key: 'fifth',
|
|
81
|
+
action: {
|
|
82
|
+
label: 'Epic button',
|
|
83
|
+
onClick: action('Hello from the Tiny Button :)'),
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
]}
|
|
87
|
+
/>
|
|
88
|
+
);
|
|
89
89
|
};
|
|
@@ -13,7 +13,7 @@ export interface DefinitionListDefinition {
|
|
|
13
13
|
key: string;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
type DefinitionListLayout =
|
|
17
17
|
`${Layout.VERTICAL_TWO_COLUMN | Layout.VERTICAL_ONE_COLUMN | Layout.HORIZONTAL_JUSTIFIED | Layout.HORIZONTAL_LEFT_ALIGNED | Layout.HORIZONTAL_RIGHT_ALIGNED}`;
|
|
18
18
|
|
|
19
19
|
export interface DefinitionListProps {
|
package/src/i18n/de.json
CHANGED
|
@@ -54,7 +54,6 @@
|
|
|
54
54
|
"neptune.UploadButton.allFileTypes": "Alle Dateiformate",
|
|
55
55
|
"neptune.UploadButton.dropFiles": "Datei zum Hochladen in dieses Feld ziehen",
|
|
56
56
|
"neptune.UploadButton.instructions": "{fileTypes}, kleiner als {size} MB",
|
|
57
|
-
"neptune.UploadButton.maximumFiles": "Maximal {maxFiles} Dateien.",
|
|
58
57
|
"neptune.UploadButton.uploadFile": "Datei hochladen",
|
|
59
58
|
"neptune.UploadButton.uploadFiles": "Dateien hochladen",
|
|
60
59
|
"neptune.UploadInput.deleteModalBody": "Wenn du diese Datei entfernst, wird sie aus unserem System gelöscht werden.",
|
package/src/i18n/it.json
CHANGED
|
@@ -54,7 +54,6 @@
|
|
|
54
54
|
"neptune.UploadButton.allFileTypes": "Tutti i tipi di file",
|
|
55
55
|
"neptune.UploadButton.dropFiles": "Rilascia file per iniziare a caricare",
|
|
56
56
|
"neptune.UploadButton.instructions": "{fileTypes}, minore di {size}MB",
|
|
57
|
-
"neptune.UploadButton.maximumFiles": "Max {maxFiles} file.",
|
|
58
57
|
"neptune.UploadButton.uploadFile": "Carica un file",
|
|
59
58
|
"neptune.UploadButton.uploadFiles": "Carica i file",
|
|
60
59
|
"neptune.UploadInput.deleteModalBody": "Rimuovere questo file lo cancellerà dal nostro sistema.",
|
package/src/i18n/th.json
CHANGED
|
@@ -54,7 +54,6 @@
|
|
|
54
54
|
"neptune.UploadButton.allFileTypes": "ไฟล์ทุกประเภท",
|
|
55
55
|
"neptune.UploadButton.dropFiles": "วางไฟล์เพื่อเริ่มการอัปโหลด",
|
|
56
56
|
"neptune.UploadButton.instructions": "{fileTypes} น้อยกว่า {size} MB",
|
|
57
|
-
"neptune.UploadButton.maximumFiles": "สูงสุด {maxFiles} ไฟล์",
|
|
58
57
|
"neptune.UploadButton.uploadFile": "อัปโหลดไฟล์",
|
|
59
58
|
"neptune.UploadButton.uploadFiles": "อัปโหลดไฟล์",
|
|
60
59
|
"neptune.UploadInput.deleteModalBody": "การลบไฟล์นี้จะลบออกจากระบบของเรา",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable react/jsx-key */
|
|
2
2
|
import { Meta, StoryObj } from '@storybook/react';
|
|
3
|
-
import { ArrowLeft
|
|
3
|
+
import { ArrowLeft } from '@transferwise/icons';
|
|
4
4
|
import IconButton, { Props } from './IconButton';
|
|
5
5
|
import { action } from '@storybook/addon-actions';
|
|
6
6
|
import Body from '../body';
|
|
@@ -24,7 +24,7 @@ const Template = ({ size, disabled }: Props) => {
|
|
|
24
24
|
type="default"
|
|
25
25
|
onClick={action('button click')}
|
|
26
26
|
>
|
|
27
|
-
<
|
|
27
|
+
<ArrowLeft />
|
|
28
28
|
</IconButton>
|
|
29
29
|
<IconButton
|
|
30
30
|
size={size}
|
|
@@ -34,7 +34,7 @@ const Template = ({ size, disabled }: Props) => {
|
|
|
34
34
|
type="default"
|
|
35
35
|
onClick={action('button click')}
|
|
36
36
|
>
|
|
37
|
-
<
|
|
37
|
+
<ArrowLeft />
|
|
38
38
|
</IconButton>
|
|
39
39
|
<IconButton
|
|
40
40
|
size={size}
|
|
@@ -54,7 +54,7 @@ const Template = ({ size, disabled }: Props) => {
|
|
|
54
54
|
type="default"
|
|
55
55
|
onClick={action('button click')}
|
|
56
56
|
>
|
|
57
|
-
<
|
|
57
|
+
<ArrowLeft />
|
|
58
58
|
</IconButton>
|
|
59
59
|
<IconButton
|
|
60
60
|
size={size}
|
|
@@ -64,7 +64,7 @@ const Template = ({ size, disabled }: Props) => {
|
|
|
64
64
|
type="negative"
|
|
65
65
|
onClick={action('button click')}
|
|
66
66
|
>
|
|
67
|
-
<
|
|
67
|
+
<ArrowLeft />
|
|
68
68
|
</IconButton>
|
|
69
69
|
<IconButton
|
|
70
70
|
size={size}
|
|
@@ -74,7 +74,7 @@ const Template = ({ size, disabled }: Props) => {
|
|
|
74
74
|
type="negative"
|
|
75
75
|
onClick={action('button click')}
|
|
76
76
|
>
|
|
77
|
-
<
|
|
77
|
+
<ArrowLeft />
|
|
78
78
|
</IconButton>
|
|
79
79
|
</>
|
|
80
80
|
);
|