@transferwise/components 0.0.0-experimental-266e18f → 0.0.0-experimental-add7cf9
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/image/Image.js +9 -10
- package/build/image/Image.js.map +1 -1
- package/build/image/Image.mjs +11 -11
- package/build/image/Image.mjs.map +1 -1
- package/build/index.js +0 -1
- package/build/index.js.map +1 -1
- package/build/index.mjs +1 -1
- package/build/main.css +0 -188
- package/build/styles/main.css +0 -188
- package/build/types/image/Image.d.ts +0 -1
- package/build/types/image/Image.d.ts.map +1 -1
- package/build/types/index.d.ts +0 -2
- package/build/types/index.d.ts.map +1 -1
- package/build/types/test-utils/fake-data.d.ts +0 -2
- package/build/types/test-utils/fake-data.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/image/Image.spec.tsx +3 -3
- package/src/image/Image.tsx +10 -12
- package/src/index.ts +0 -2
- package/src/legacylistItem/LegacyListItem.story.tsx +5 -5
- package/src/legacylistItem/LegacyListItem.tests.story.tsx +6 -6
- package/src/main.css +0 -188
- package/src/main.less +0 -1
- package/src/promoCard/__snapshots__/PromoCard.spec.tsx.snap +1 -0
- package/src/promoCard/__snapshots__/PromoCardGroup.spec.tsx.snap +2 -0
- package/src/test-utils/fake-data.ts +0 -5
- package/build/styles/listItem/ListItem.css +0 -188
- package/build/test-utils/assets/apple-pay-logo.svg +0 -84
- package/build/types/listItem/ListItem.d.ts +0 -44
- package/build/types/listItem/ListItem.d.ts.map +0 -1
- package/build/types/listItem/ListItemAdditionalInfo.d.ts +0 -9
- package/build/types/listItem/ListItemAdditionalInfo.d.ts.map +0 -1
- package/build/types/listItem/ListItemButton.d.ts +0 -4
- package/build/types/listItem/ListItemButton.d.ts.map +0 -1
- package/build/types/listItem/ListItemCheckbox.d.ts +0 -4
- package/build/types/listItem/ListItemCheckbox.d.ts.map +0 -1
- package/build/types/listItem/ListItemIconButton.d.ts +0 -7
- package/build/types/listItem/ListItemIconButton.d.ts.map +0 -1
- package/build/types/listItem/ListItemMedia.d.ts +0 -19
- package/build/types/listItem/ListItemMedia.d.ts.map +0 -1
- package/build/types/listItem/ListItemNavigation.d.ts +0 -4
- package/build/types/listItem/ListItemNavigation.d.ts.map +0 -1
- package/build/types/listItem/ListItemSwitch.d.ts +0 -3
- package/build/types/listItem/ListItemSwitch.d.ts.map +0 -1
- package/build/types/listItem/index.d.ts +0 -6
- package/build/types/listItem/index.d.ts.map +0 -1
- package/build/types/listItem/prompt/Prompt.d.ts +0 -12
- package/build/types/listItem/prompt/Prompt.d.ts.map +0 -1
- package/build/types/listItem/useItemControl.d.ts +0 -5
- package/build/types/listItem/useItemControl.d.ts.map +0 -1
- package/src/listItem/ListItem.css +0 -188
- package/src/listItem/ListItem.less +0 -180
- package/src/listItem/ListItem.spec.tsx +0 -35
- package/src/listItem/ListItem.story.tsx +0 -296
- package/src/listItem/ListItem.tsx +0 -190
- package/src/listItem/ListItemAdditionalInfo.tsx +0 -31
- package/src/listItem/ListItemButton.spec.tsx +0 -90
- package/src/listItem/ListItemButton.tsx +0 -18
- package/src/listItem/ListItemCheckbox.tsx +0 -14
- package/src/listItem/ListItemIconButton.tsx +0 -13
- package/src/listItem/ListItemMedia.tsx +0 -52
- package/src/listItem/ListItemNavigation.tsx +0 -11
- package/src/listItem/ListItemSwitch.tsx +0 -8
- package/src/listItem/index.ts +0 -10
- package/src/listItem/prompt/Prompt.spec.tsx +0 -77
- package/src/listItem/prompt/Prompt.story.tsx +0 -170
- package/src/listItem/prompt/Prompt.tsx +0 -44
- package/src/listItem/useItemControl.tsx +0 -12
- package/src/test-utils/assets/apple-pay-logo.svg +0 -84
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { render, screen } from '../test-utils';
|
|
2
|
-
import ListItem from './ListItem';
|
|
3
|
-
|
|
4
|
-
describe('ListItem', () => {
|
|
5
|
-
describe('spotlight', () => {
|
|
6
|
-
it('only fully interactive variant can have spotlight:active', () => {
|
|
7
|
-
render(<ListItem title="Test Title" spotlight="active" control={<ListItem.Navigation />} />);
|
|
8
|
-
const listItem = screen.getByRole('listitem');
|
|
9
|
-
expect(listItem).toHaveClass('wds-list-item-interactive');
|
|
10
|
-
expect(listItem).toHaveClass('wds-list-item-spotlight-active');
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it('only fully interactive variant can have spotlight:inactive', () => {
|
|
14
|
-
render(
|
|
15
|
-
<ListItem
|
|
16
|
-
title="Test Title"
|
|
17
|
-
spotlight="inactive"
|
|
18
|
-
control={<ListItem.Switch onClick={() => {}} />}
|
|
19
|
-
/>,
|
|
20
|
-
);
|
|
21
|
-
const listItem = screen.getByRole('listitem');
|
|
22
|
-
expect(listItem).toHaveClass('wds-list-item-interactive');
|
|
23
|
-
expect(listItem).toHaveClass('wds-list-item-spotlight-inactive');
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('non interactive variant can have spotlight', () => {
|
|
27
|
-
render(<ListItem title="Test Title" spotlight="inactive" />);
|
|
28
|
-
const listItem = screen.getByRole('listitem');
|
|
29
|
-
expect(listItem).toHaveClass('wds-list-item-non-interactive');
|
|
30
|
-
expect(listItem).not.toHaveClass('wds-list-item-interactive');
|
|
31
|
-
expect(listItem).not.toHaveClass('wds-list-item-spotlight-inactive');
|
|
32
|
-
expect(listItem).not.toHaveClass('wds-list-item-spotlight-active');
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
});
|
|
@@ -1,296 +0,0 @@
|
|
|
1
|
-
import ListItem, { Props as ItemProps } from './ListItem';
|
|
2
|
-
import { Meta, StoryObj } from '@storybook/react';
|
|
3
|
-
import React, { useState } from 'react';
|
|
4
|
-
import {
|
|
5
|
-
Bank,
|
|
6
|
-
BankTransfer,
|
|
7
|
-
FastFlag,
|
|
8
|
-
MultiCurrency,
|
|
9
|
-
Plus,
|
|
10
|
-
Receipt,
|
|
11
|
-
Savings,
|
|
12
|
-
} from '@transferwise/icons';
|
|
13
|
-
|
|
14
|
-
import { lorem10, lorem20, lorem40, lorem5 } from '../test-utils';
|
|
15
|
-
import { Flag } from '@wise/art';
|
|
16
|
-
import { List } from '../legacylistItem/List';
|
|
17
|
-
import Money from '../money';
|
|
18
|
-
import Section from '../section';
|
|
19
|
-
import Header from '../header';
|
|
20
|
-
|
|
21
|
-
export default {
|
|
22
|
-
component: ListItem,
|
|
23
|
-
title: 'Content/ListItem',
|
|
24
|
-
} satisfies Meta<ItemProps>;
|
|
25
|
-
|
|
26
|
-
type Story = StoryObj<ItemProps>;
|
|
27
|
-
|
|
28
|
-
// TODO: delete this story later when we have more peace of the List Item puzzle
|
|
29
|
-
export const TempPlayground: Story = {
|
|
30
|
-
render: () => {
|
|
31
|
-
const [checked, setChecked] = useState(false);
|
|
32
|
-
|
|
33
|
-
return (
|
|
34
|
-
<div>
|
|
35
|
-
<ListItem
|
|
36
|
-
media={
|
|
37
|
-
<ListItem.AvatarView badge={{ type: 'action' }}>
|
|
38
|
-
<Flag code="BBD" />
|
|
39
|
-
</ListItem.AvatarView>
|
|
40
|
-
}
|
|
41
|
-
title="Test title"
|
|
42
|
-
subtitle="Test subtitle"
|
|
43
|
-
additionalInfo={<ListItem.AdditionalInfo>{lorem10}</ListItem.AdditionalInfo>}
|
|
44
|
-
/>
|
|
45
|
-
<ListItem
|
|
46
|
-
media={
|
|
47
|
-
<ListItem.AvatarLayout
|
|
48
|
-
avatars={[{ asset: <Flag code="BBD" /> }, { asset: <Flag code="MXN" /> }]}
|
|
49
|
-
/>
|
|
50
|
-
}
|
|
51
|
-
title="Test title"
|
|
52
|
-
subtitle={lorem10}
|
|
53
|
-
additionalInfo={<ListItem.AdditionalInfo>{lorem20}</ListItem.AdditionalInfo>}
|
|
54
|
-
/>
|
|
55
|
-
<ListItem
|
|
56
|
-
media={
|
|
57
|
-
<ListItem.AvatarLayout
|
|
58
|
-
size={72}
|
|
59
|
-
orientation="diagonal"
|
|
60
|
-
avatars={[{ asset: <Flag code="BBD" /> }, { asset: <Flag code="MXN" /> }]}
|
|
61
|
-
/>
|
|
62
|
-
}
|
|
63
|
-
title="Test title"
|
|
64
|
-
subtitle={lorem10}
|
|
65
|
-
valueTitle="100 GBP"
|
|
66
|
-
valueSubtitle="100 USD"
|
|
67
|
-
additionalInfo={<ListItem.AdditionalInfo>{lorem20}</ListItem.AdditionalInfo>}
|
|
68
|
-
/>
|
|
69
|
-
<ListItem
|
|
70
|
-
media={<ListItem.AvatarView profileType="BUSINESS" notification />}
|
|
71
|
-
title="Test title"
|
|
72
|
-
subtitle="Test subtitle"
|
|
73
|
-
additionalInfo={
|
|
74
|
-
<ListItem.AdditionalInfo
|
|
75
|
-
action={{ label: 'Learn more', href: 'https://wise.com', target: '_blank' }}
|
|
76
|
-
>
|
|
77
|
-
{lorem10}
|
|
78
|
-
</ListItem.AdditionalInfo>
|
|
79
|
-
}
|
|
80
|
-
prompt={<ListItem.Prompt type="negative">You have done something wrong</ListItem.Prompt>}
|
|
81
|
-
/>
|
|
82
|
-
<ListItem
|
|
83
|
-
media={<ListItem.AvatarView imgSrc="../avatar-square-dude.webp" selected />}
|
|
84
|
-
title="Test title"
|
|
85
|
-
additionalInfo={<ListItem.AdditionalInfo>{lorem10}</ListItem.AdditionalInfo>}
|
|
86
|
-
prompt={
|
|
87
|
-
<ListItem.Prompt
|
|
88
|
-
type="discount"
|
|
89
|
-
action={{
|
|
90
|
-
href: 'https://wise.com',
|
|
91
|
-
target: '_blank',
|
|
92
|
-
'aria-label': 'clickable prompt',
|
|
93
|
-
}}
|
|
94
|
-
>
|
|
95
|
-
The whole prompt is secretly clickable
|
|
96
|
-
</ListItem.Prompt>
|
|
97
|
-
}
|
|
98
|
-
/>
|
|
99
|
-
|
|
100
|
-
<ListItem
|
|
101
|
-
media={<ListItem.Image src="../apple-pay-logo.svg" />}
|
|
102
|
-
title="Accepting Apple Pay"
|
|
103
|
-
subtitle={lorem10}
|
|
104
|
-
/>
|
|
105
|
-
|
|
106
|
-
<ListItem
|
|
107
|
-
media={<ListItem.Image src="../wise-card.svg" />}
|
|
108
|
-
title="Wise Business Card"
|
|
109
|
-
subtitle={lorem5}
|
|
110
|
-
/>
|
|
111
|
-
|
|
112
|
-
<ListItem
|
|
113
|
-
title="Test title"
|
|
114
|
-
disabled
|
|
115
|
-
subtitle={lorem10}
|
|
116
|
-
additionalInfo={<ListItem.AdditionalInfo>{lorem20}</ListItem.AdditionalInfo>}
|
|
117
|
-
control={<ListItem.Button priority="secondary-neutral">as Button</ListItem.Button>}
|
|
118
|
-
/>
|
|
119
|
-
<ListItem
|
|
120
|
-
title="Test title"
|
|
121
|
-
disabled
|
|
122
|
-
subtitle={lorem10}
|
|
123
|
-
additionalInfo={<ListItem.AdditionalInfo>{lorem20}</ListItem.AdditionalInfo>}
|
|
124
|
-
control={
|
|
125
|
-
<ListItem.IconButton>
|
|
126
|
-
<Plus />
|
|
127
|
-
</ListItem.IconButton>
|
|
128
|
-
}
|
|
129
|
-
/>
|
|
130
|
-
|
|
131
|
-
<ListItem
|
|
132
|
-
title="Test title"
|
|
133
|
-
subtitle={lorem10}
|
|
134
|
-
additionalInfo={<ListItem.AdditionalInfo>{lorem20}</ListItem.AdditionalInfo>}
|
|
135
|
-
control={
|
|
136
|
-
<ListItem.Button
|
|
137
|
-
priority="secondary-neutral"
|
|
138
|
-
as="a"
|
|
139
|
-
target="dfdf"
|
|
140
|
-
aria-label="adsfasfd"
|
|
141
|
-
href="wise.com"
|
|
142
|
-
>
|
|
143
|
-
as Link
|
|
144
|
-
</ListItem.Button>
|
|
145
|
-
}
|
|
146
|
-
/>
|
|
147
|
-
|
|
148
|
-
<ListItem
|
|
149
|
-
media={
|
|
150
|
-
<ListItem.AvatarView>
|
|
151
|
-
<Bank />
|
|
152
|
-
</ListItem.AvatarView>
|
|
153
|
-
}
|
|
154
|
-
spotlight="inactive"
|
|
155
|
-
title="Test title"
|
|
156
|
-
subtitle={lorem5}
|
|
157
|
-
additionalInfo={<ListItem.AdditionalInfo>{lorem10}</ListItem.AdditionalInfo>}
|
|
158
|
-
control={<ListItem.Checkbox indeterminate />}
|
|
159
|
-
className="m-t-2"
|
|
160
|
-
/>
|
|
161
|
-
|
|
162
|
-
<ListItem
|
|
163
|
-
media={
|
|
164
|
-
<ListItem.AvatarLayout
|
|
165
|
-
orientation="diagonal"
|
|
166
|
-
avatars={[{ asset: <BankTransfer /> }, { asset: <Bank /> }]}
|
|
167
|
-
/>
|
|
168
|
-
}
|
|
169
|
-
spotlight="active"
|
|
170
|
-
title="Test title"
|
|
171
|
-
subtitle={lorem5}
|
|
172
|
-
additionalInfo={<ListItem.AdditionalInfo>{lorem10}</ListItem.AdditionalInfo>}
|
|
173
|
-
control={
|
|
174
|
-
<ListItem.Switch
|
|
175
|
-
checked={checked}
|
|
176
|
-
onClick={() => {
|
|
177
|
-
setChecked(!checked);
|
|
178
|
-
}}
|
|
179
|
-
/>
|
|
180
|
-
}
|
|
181
|
-
className="m-t-2 m-b-4"
|
|
182
|
-
/>
|
|
183
|
-
</div>
|
|
184
|
-
);
|
|
185
|
-
},
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
export const Radio: Story = {
|
|
189
|
-
render: () => (
|
|
190
|
-
<div>
|
|
191
|
-
{/* Basic */}
|
|
192
|
-
{/* with additional info */}
|
|
193
|
-
{/* with prompt */}
|
|
194
|
-
{/* Disabled */}
|
|
195
|
-
{/* Spotlight */}
|
|
196
|
-
{/* Active */}
|
|
197
|
-
</div>
|
|
198
|
-
),
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
export const Button: Story = {
|
|
202
|
-
render: () => (
|
|
203
|
-
<div>
|
|
204
|
-
{/* Basic */}
|
|
205
|
-
{/* with additional info */}
|
|
206
|
-
{/* with prompt */}
|
|
207
|
-
{/* partially interactive */}
|
|
208
|
-
{/* Disabled */}
|
|
209
|
-
{/* Spotlight */}
|
|
210
|
-
{/* Active */}
|
|
211
|
-
</div>
|
|
212
|
-
),
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
export const NonInteractive: Story = {
|
|
216
|
-
render: () => (
|
|
217
|
-
<div>
|
|
218
|
-
<Section>
|
|
219
|
-
<Header title="Transcation Details" />
|
|
220
|
-
<List>
|
|
221
|
-
<ListItem
|
|
222
|
-
media={
|
|
223
|
-
<ListItem.AvatarView>
|
|
224
|
-
<MultiCurrency />
|
|
225
|
-
</ListItem.AvatarView>
|
|
226
|
-
}
|
|
227
|
-
title="Estimated costs"
|
|
228
|
-
subtitle="Other providers"
|
|
229
|
-
valueTitle={<Money amount={100} currency="GBP" />}
|
|
230
|
-
/>
|
|
231
|
-
<ListItem
|
|
232
|
-
media={
|
|
233
|
-
<ListItem.AvatarView>
|
|
234
|
-
<FastFlag />
|
|
235
|
-
</ListItem.AvatarView>
|
|
236
|
-
}
|
|
237
|
-
title="Total paid"
|
|
238
|
-
subtitle="Wise"
|
|
239
|
-
valueTitle={<Money amount={12.15} currency="GBP" />}
|
|
240
|
-
valueSubtitle={<Money amount={100.9} currency="GBP" />}
|
|
241
|
-
/>
|
|
242
|
-
<ListItem
|
|
243
|
-
media={
|
|
244
|
-
<ListItem.AvatarView>
|
|
245
|
-
<Receipt />
|
|
246
|
-
</ListItem.AvatarView>
|
|
247
|
-
}
|
|
248
|
-
title="Total fees"
|
|
249
|
-
subtitle={lorem5}
|
|
250
|
-
valueSubtitle={<Money amount={5.5} currency="GBP" />}
|
|
251
|
-
/>
|
|
252
|
-
<ListItem
|
|
253
|
-
media={
|
|
254
|
-
<ListItem.AvatarView>
|
|
255
|
-
<Savings />
|
|
256
|
-
</ListItem.AvatarView>
|
|
257
|
-
}
|
|
258
|
-
title="You saved"
|
|
259
|
-
valueSubtitle={<Money amount={1000} currency="GBP" />}
|
|
260
|
-
/>
|
|
261
|
-
</List>
|
|
262
|
-
</Section>
|
|
263
|
-
|
|
264
|
-
<ListItem
|
|
265
|
-
as="div"
|
|
266
|
-
title="Bank name and address"
|
|
267
|
-
subtitle="Bank Ltd, 2 Street Boulevard, Singapore, 1213423"
|
|
268
|
-
additionalInfo={
|
|
269
|
-
<ListItem.AdditionalInfo
|
|
270
|
-
action={{ label: 'Learn more', href: 'https://wise.com', target: '_blank' }}
|
|
271
|
-
>
|
|
272
|
-
This is our partner bank in Singapore.
|
|
273
|
-
</ListItem.AdditionalInfo>
|
|
274
|
-
}
|
|
275
|
-
/>
|
|
276
|
-
<ListItem
|
|
277
|
-
as="div"
|
|
278
|
-
title="Bank name and address"
|
|
279
|
-
subtitle="Capital Ltd, 2 Canal Street, London, E14 111"
|
|
280
|
-
additionalInfo={
|
|
281
|
-
<ListItem.AdditionalInfo
|
|
282
|
-
action={{ label: 'Learn more', href: 'https://wise.com', target: '_blank' }}
|
|
283
|
-
/>
|
|
284
|
-
}
|
|
285
|
-
/>
|
|
286
|
-
{/* Basic */}
|
|
287
|
-
{/* with additional info */}
|
|
288
|
-
{/* with prompt */}
|
|
289
|
-
{/* Disabled */}
|
|
290
|
-
{/* Spotlight */}
|
|
291
|
-
{/* Active */}
|
|
292
|
-
</div>
|
|
293
|
-
),
|
|
294
|
-
};
|
|
295
|
-
|
|
296
|
-
// add intaces with dark mode
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
import { createContext, ReactNode, useId, useMemo, useState } from 'react';
|
|
2
|
-
import { Typography } from '../common';
|
|
3
|
-
import Body from '../body';
|
|
4
|
-
import { AdditionalInfo } from './ListItemAdditionalInfo';
|
|
5
|
-
import { IconButton } from './ListItemIconButton';
|
|
6
|
-
import { Checkbox } from './ListItemCheckbox';
|
|
7
|
-
import { Navigation } from './ListItemNavigation';
|
|
8
|
-
import { clsx } from 'clsx';
|
|
9
|
-
import { Button } from './ListItemButton';
|
|
10
|
-
import { Switch } from './ListItemSwitch';
|
|
11
|
-
import { AvatarLayout, AvatarView, Image } from './ListItemMedia';
|
|
12
|
-
import Prompt from './prompt/Prompt';
|
|
13
|
-
|
|
14
|
-
export type ListItemTypes =
|
|
15
|
-
| 'non-interactive'
|
|
16
|
-
| 'navigation'
|
|
17
|
-
| 'radio'
|
|
18
|
-
| 'checkbox'
|
|
19
|
-
| 'switch'
|
|
20
|
-
| 'button'
|
|
21
|
-
| 'icon-button';
|
|
22
|
-
|
|
23
|
-
export type Props = {
|
|
24
|
-
as?: 'li' | 'div' | 'span';
|
|
25
|
-
inverted?: boolean;
|
|
26
|
-
disabled?: boolean;
|
|
27
|
-
spotlight?: 'active' | 'inactive';
|
|
28
|
-
title: ReactNode;
|
|
29
|
-
subtitle?: ReactNode;
|
|
30
|
-
additionalInfo?: ReactNode;
|
|
31
|
-
valueTitle?: ReactNode;
|
|
32
|
-
valueSubtitle?: ReactNode;
|
|
33
|
-
media?: ReactNode;
|
|
34
|
-
control?: ReactNode;
|
|
35
|
-
prompt?: ReactNode;
|
|
36
|
-
className?: string;
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
export type ListItemContextData = {
|
|
40
|
-
setControlType: (type: ListItemTypes) => void;
|
|
41
|
-
ids: {
|
|
42
|
-
label: string;
|
|
43
|
-
additionalInfo: string;
|
|
44
|
-
value: string;
|
|
45
|
-
control: string;
|
|
46
|
-
prompt: string;
|
|
47
|
-
};
|
|
48
|
-
props: Pick<Props, 'as' | 'disabled' | 'inverted'>;
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
// @ts-expect-error for now let's mock it with `null` value
|
|
52
|
-
// but actually by default we should specify `setControlType('none')`
|
|
53
|
-
export const ListItemContext = createContext<ListItemContextData>(null);
|
|
54
|
-
|
|
55
|
-
export const ListItem = ({
|
|
56
|
-
as: View = 'li',
|
|
57
|
-
title,
|
|
58
|
-
subtitle,
|
|
59
|
-
additionalInfo,
|
|
60
|
-
prompt,
|
|
61
|
-
inverted,
|
|
62
|
-
media,
|
|
63
|
-
spotlight = undefined,
|
|
64
|
-
valueTitle,
|
|
65
|
-
valueSubtitle,
|
|
66
|
-
control = null,
|
|
67
|
-
disabled,
|
|
68
|
-
className,
|
|
69
|
-
}: Props) => {
|
|
70
|
-
/*
|
|
71
|
-
const returnType = (): ReactNode => {
|
|
72
|
-
switch (type) {
|
|
73
|
-
case 'Navigation':
|
|
74
|
-
return <Chevron orientation={Position.RIGHT} disabled />;
|
|
75
|
-
case 'Radio':
|
|
76
|
-
return <RadioButton name="Hello" checked />;
|
|
77
|
-
case 'Checkbox':
|
|
78
|
-
return <CheckboxButton name="Hello" checked />;
|
|
79
|
-
case 'Switch':
|
|
80
|
-
return <Switch onClick={() => console.log('clicked')} />;
|
|
81
|
-
case 'Button':
|
|
82
|
-
return <Button v2>Hello</Button>;
|
|
83
|
-
case 'IconButton':
|
|
84
|
-
return (
|
|
85
|
-
<IconButton size={40} priority="minimal">
|
|
86
|
-
<InfoCircle />
|
|
87
|
-
</IconButton>
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
*/
|
|
92
|
-
const idPrefix = useId();
|
|
93
|
-
|
|
94
|
-
const [controlType, setControlType] = useState<ListItemTypes>('non-interactive');
|
|
95
|
-
const ids = {
|
|
96
|
-
label: `${idPrefix}_label`,
|
|
97
|
-
value: `${idPrefix}_value`,
|
|
98
|
-
control: `${idPrefix}_control`,
|
|
99
|
-
prompt: `${idPrefix}_prompt`,
|
|
100
|
-
additionalInfo: `${idPrefix}_additional-info`,
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
// TODO: add partially interactive check from Button and IconButtons
|
|
104
|
-
// (https://transferwise.atlassian.net/browse/DS-7562)
|
|
105
|
-
const isFullyInteractive = controlType !== 'non-interactive';
|
|
106
|
-
|
|
107
|
-
const listItemContext = useMemo(
|
|
108
|
-
() => ({ setControlType, ids, props: { as: View, disabled, inverted } }),
|
|
109
|
-
[],
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
return (
|
|
113
|
-
<ListItemContext.Provider value={listItemContext}>
|
|
114
|
-
<View
|
|
115
|
-
className={clsx(
|
|
116
|
-
'wds-list-item',
|
|
117
|
-
{ 'wds-list-item-interactive': controlType !== 'non-interactive' },
|
|
118
|
-
`wds-list-item-${controlType}`,
|
|
119
|
-
'd-flex flex-row',
|
|
120
|
-
{ 'align-items-center': !subtitle },
|
|
121
|
-
{
|
|
122
|
-
[`wds-list-item-spotlight-${spotlight}`]: isFullyInteractive && !!spotlight,
|
|
123
|
-
},
|
|
124
|
-
className,
|
|
125
|
-
)}
|
|
126
|
-
aria-describedby={[ids.additionalInfo].join(' ')}
|
|
127
|
-
>
|
|
128
|
-
{media && <div className="wds-list-item-media">{media}</div>}
|
|
129
|
-
|
|
130
|
-
{/* Title + Subtitle + Values + Additional Info - Group */}
|
|
131
|
-
<div className="wds-list-item-body">
|
|
132
|
-
{/* Title + Subtitle + Values - Group */}
|
|
133
|
-
<div className="d-flex justify-content-between">
|
|
134
|
-
<span>
|
|
135
|
-
{/* @ts-expect-error div can have role and aria-lavel props */}
|
|
136
|
-
<Body
|
|
137
|
-
type={Typography.BODY_LARGE_BOLD}
|
|
138
|
-
className="wds-list-item-title"
|
|
139
|
-
// for a11y this needs to be a header but for SEO it shouldn't be `h*` tag
|
|
140
|
-
// so we enable header semantics via `role` and `aria-level` attrs
|
|
141
|
-
role="heading"
|
|
142
|
-
aria-level="4"
|
|
143
|
-
>
|
|
144
|
-
{title}
|
|
145
|
-
</Body>
|
|
146
|
-
<Body className="wds-list-item-subtitle">{subtitle}</Body>
|
|
147
|
-
</span>
|
|
148
|
-
{(valueTitle || valueSubtitle) && (
|
|
149
|
-
<span
|
|
150
|
-
id={ids.value}
|
|
151
|
-
className={clsx('wds-list-item-value', 'd-flex align-items-center', {
|
|
152
|
-
'flex-column': valueTitle !== undefined && valueSubtitle !== undefined,
|
|
153
|
-
})}
|
|
154
|
-
>
|
|
155
|
-
{valueTitle && (
|
|
156
|
-
<Body type={Typography.BODY_LARGE_BOLD} className="wds-list-item-title-value">
|
|
157
|
-
{valueTitle}
|
|
158
|
-
</Body>
|
|
159
|
-
)}
|
|
160
|
-
{valueSubtitle && (
|
|
161
|
-
<Body className="wds-list-item-subtitle-value">{valueSubtitle}</Body>
|
|
162
|
-
)}
|
|
163
|
-
</span>
|
|
164
|
-
)}
|
|
165
|
-
</div>
|
|
166
|
-
|
|
167
|
-
{/* Additional Info and Prompt here */}
|
|
168
|
-
{Boolean(subtitle) && additionalInfo}
|
|
169
|
-
</div>
|
|
170
|
-
{control === null ? null : <Body className="wds-list-item-control">{control}</Body>}
|
|
171
|
-
{prompt}
|
|
172
|
-
</View>
|
|
173
|
-
</ListItemContext.Provider>
|
|
174
|
-
);
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
/* eslint-disable functional/immutable-data */
|
|
178
|
-
ListItem.Image = Image;
|
|
179
|
-
ListItem.AvatarView = AvatarView;
|
|
180
|
-
ListItem.AvatarLayout = AvatarLayout;
|
|
181
|
-
ListItem.AdditionalInfo = AdditionalInfo;
|
|
182
|
-
ListItem.Checkbox = Checkbox;
|
|
183
|
-
ListItem.IconButton = IconButton;
|
|
184
|
-
ListItem.Navigation = Navigation;
|
|
185
|
-
ListItem.Button = Button;
|
|
186
|
-
ListItem.Switch = Switch;
|
|
187
|
-
ListItem.Prompt = Prompt;
|
|
188
|
-
/* eslint-enable functional/immutable-data */
|
|
189
|
-
|
|
190
|
-
export default ListItem;
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { PropsWithChildren, useContext } from 'react';
|
|
2
|
-
import { ListItemContext, ListItemContextData } from './ListItem';
|
|
3
|
-
import Body from '../body';
|
|
4
|
-
import Link, { LinkProps } from '../link';
|
|
5
|
-
import { Typography } from '../common';
|
|
6
|
-
|
|
7
|
-
export type ListItemAdditionalInfoProps = PropsWithChildren<{
|
|
8
|
-
action?: Pick<LinkProps, 'href' | 'onClick' | 'target'> & { label?: string };
|
|
9
|
-
}>;
|
|
10
|
-
|
|
11
|
-
export const AdditionalInfo = function ({ children, action }: ListItemAdditionalInfoProps) {
|
|
12
|
-
const { ids } = useContext<ListItemContextData>(ListItemContext);
|
|
13
|
-
|
|
14
|
-
return (
|
|
15
|
-
<Body
|
|
16
|
-
type={Typography.BODY_DEFAULT}
|
|
17
|
-
id={ids.additionalInfo}
|
|
18
|
-
className="wds-list-item-additional-info"
|
|
19
|
-
>
|
|
20
|
-
{children}
|
|
21
|
-
{action ? (
|
|
22
|
-
<>
|
|
23
|
-
{' '}
|
|
24
|
-
<Link href={action.href} target={action.target} onClick={action.onClick}>
|
|
25
|
-
{action.label}
|
|
26
|
-
</Link>
|
|
27
|
-
</>
|
|
28
|
-
) : null}
|
|
29
|
-
</Body>
|
|
30
|
-
);
|
|
31
|
-
};
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { render, screen, mockMatchMedia } from '../test-utils';
|
|
2
|
-
import { Button as ItemButton } from './ListItemButton';
|
|
3
|
-
import { ButtonPriority } from '../button/Button.types';
|
|
4
|
-
import { ListItemContext } from './ListItem';
|
|
5
|
-
|
|
6
|
-
mockMatchMedia();
|
|
7
|
-
|
|
8
|
-
describe('ItemButton', () => {
|
|
9
|
-
const mockSetControlType = jest.fn();
|
|
10
|
-
|
|
11
|
-
const renderWithItemContext = (ui: React.ReactNode) => {
|
|
12
|
-
return render(
|
|
13
|
-
<ListItemContext.Provider
|
|
14
|
-
value={{
|
|
15
|
-
setControlType: mockSetControlType,
|
|
16
|
-
ids: {
|
|
17
|
-
label: 'label',
|
|
18
|
-
additionalInfo: 'additional Info',
|
|
19
|
-
value: 'value',
|
|
20
|
-
control: 'control',
|
|
21
|
-
prompt: 'prompt',
|
|
22
|
-
},
|
|
23
|
-
props: {},
|
|
24
|
-
}}
|
|
25
|
-
>
|
|
26
|
-
{ui}
|
|
27
|
-
</ListItemContext.Provider>,
|
|
28
|
-
);
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
beforeEach(() => {
|
|
32
|
-
jest.clearAllMocks();
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it('always sets v2 to true', () => {
|
|
36
|
-
renderWithItemContext(<ItemButton priority="primary">Test Button</ItemButton>);
|
|
37
|
-
const button = screen.getByRole('button');
|
|
38
|
-
expect(button).toBeInTheDocument();
|
|
39
|
-
expect(mockSetControlType).toHaveBeenCalledWith('button');
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('always sets size to "md"', () => {
|
|
43
|
-
renderWithItemContext(<ItemButton priority="primary">Test Button</ItemButton>);
|
|
44
|
-
const button = screen.getByRole('button');
|
|
45
|
-
expect(button).toHaveClass('wds-Button--medium');
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it('supports all priorities', () => {
|
|
49
|
-
const priorities: ButtonPriority[] = ['primary', 'secondary', 'tertiary'];
|
|
50
|
-
priorities.forEach((priority) => {
|
|
51
|
-
renderWithItemContext(<ItemButton priority={priority}>Test {priority}</ItemButton>);
|
|
52
|
-
const button = screen.getByRole('button', { name: `Test ${priority}` });
|
|
53
|
-
expect(button).toBeInTheDocument();
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('renders as a button by default', () => {
|
|
58
|
-
renderWithItemContext(<ItemButton>Click me</ItemButton>);
|
|
59
|
-
const button = screen.getByRole('button');
|
|
60
|
-
expect(button).toBeInTheDocument();
|
|
61
|
-
expect(button.tagName).toBe('BUTTON');
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('renders as an anchor when href is provided', () => {
|
|
65
|
-
renderWithItemContext(<ItemButton href="https://example.com">Go to Example</ItemButton>);
|
|
66
|
-
const link = screen.getByRole('link', { name: 'Go to Example' });
|
|
67
|
-
expect(link).toBeInTheDocument();
|
|
68
|
-
expect(link.tagName).toBe('A');
|
|
69
|
-
expect(link).toHaveAttribute('href', 'https://example.com');
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('spreads additional props to the button', () => {
|
|
73
|
-
renderWithItemContext(<ItemButton aria-label="Custom Button">Custom</ItemButton>);
|
|
74
|
-
const button = screen.getByRole('button', { name: 'Custom Button' });
|
|
75
|
-
expect(button).toBeInTheDocument();
|
|
76
|
-
expect(button).toHaveAttribute('aria-label', 'Custom Button');
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('spreads additional props to the anchor', () => {
|
|
80
|
-
renderWithItemContext(
|
|
81
|
-
<ItemButton href="https://example.com" target="_blank" aria-label="Custom Link">
|
|
82
|
-
Custom Link
|
|
83
|
-
</ItemButton>,
|
|
84
|
-
);
|
|
85
|
-
const link = screen.getByRole('link', { name: 'Custom Link' });
|
|
86
|
-
expect(link).toBeInTheDocument();
|
|
87
|
-
expect(link).toHaveAttribute('href', 'https://example.com');
|
|
88
|
-
expect(link).toHaveAttribute('target', '_blank');
|
|
89
|
-
});
|
|
90
|
-
});
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { default as ButtonComp, NewButtonProps } from '../button';
|
|
2
|
-
import { useItemControl } from './useItemControl';
|
|
3
|
-
|
|
4
|
-
export type ListItemButtonProps = Omit<NewButtonProps, 'v2' | 'size' | 'disabled'>;
|
|
5
|
-
|
|
6
|
-
export const Button = ({ priority = 'secondary', ...props }: ListItemButtonProps) => {
|
|
7
|
-
const { baseItemProps } = useItemControl('button');
|
|
8
|
-
|
|
9
|
-
const commonProps = {
|
|
10
|
-
...props,
|
|
11
|
-
priority,
|
|
12
|
-
v2: true,
|
|
13
|
-
size: 'md',
|
|
14
|
-
disabled: baseItemProps.disabled,
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
return <ButtonComp {...(commonProps as NewButtonProps)} />;
|
|
18
|
-
};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import CheckboxButton from '../checkboxButton';
|
|
2
|
-
import { CheckboxButtonProps } from '../checkboxButton/CheckboxButton';
|
|
3
|
-
import { useItemControl } from './useItemControl';
|
|
4
|
-
|
|
5
|
-
export type ListItemCheckboxProps = Pick<
|
|
6
|
-
CheckboxButtonProps,
|
|
7
|
-
'checked' | 'indeterminate' | 'onChange'
|
|
8
|
-
>;
|
|
9
|
-
|
|
10
|
-
export const Checkbox = function (props: ListItemCheckboxProps) {
|
|
11
|
-
const { baseItemProps } = useItemControl('checkbox');
|
|
12
|
-
|
|
13
|
-
return <CheckboxButton disabled={baseItemProps.disabled} {...props} />;
|
|
14
|
-
};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { default as IconButtonComp, IconButtonProps } from '../iconButton';
|
|
2
|
-
import { useItemControl } from './useItemControl';
|
|
3
|
-
import { ReactNode } from 'react';
|
|
4
|
-
|
|
5
|
-
export type ListItemIconButtonProps = Pick<IconButtonProps, 'onClick' | 'href' | 'target'> & {
|
|
6
|
-
children: ReactNode;
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export const IconButton = function (props: ListItemIconButtonProps) {
|
|
10
|
-
const { baseItemProps } = useItemControl('icon-button');
|
|
11
|
-
|
|
12
|
-
return <IconButtonComp {...props} size={32} disabled={baseItemProps.disabled} />;
|
|
13
|
-
};
|