@transferwise/components 0.0.0-experimental-131773e → 0.0.0-experimental-1bec623

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.
Files changed (35) hide show
  1. package/build/listItem/Button/ListItemButton.js +2 -2
  2. package/build/listItem/Button/ListItemButton.js.map +1 -1
  3. package/build/listItem/Button/ListItemButton.mjs +2 -2
  4. package/build/listItem/Button/ListItemButton.mjs.map +1 -1
  5. package/build/listItem/ListItem.js +1 -1
  6. package/build/listItem/ListItem.js.map +1 -1
  7. package/build/listItem/ListItem.mjs +1 -1
  8. package/build/listItem/ListItem.mjs.map +1 -1
  9. package/build/main.css +5 -0
  10. package/build/styles/listItem/ListItem.css +5 -0
  11. package/build/styles/main.css +5 -0
  12. package/build/types/listItem/Button/ListItemButton.d.ts.map +1 -1
  13. package/build/types/listItem/ListItem.d.ts.map +1 -1
  14. package/package.json +1 -1
  15. package/src/listItem/AdditionalInfo/ListItemAdditionalInfo.spec.tsx +56 -0
  16. package/src/listItem/AvatarLayout/ListItemAvatarLayout.spec.tsx +59 -0
  17. package/src/listItem/AvatarView/ListItemAvatarView.spec.tsx +75 -0
  18. package/src/listItem/AvatarView/ListItemAvatarView.story.tsx +2 -2
  19. package/src/listItem/Button/ListItemButton.tsx +2 -2
  20. package/src/listItem/Checkbox/ListItemCheckbox.spec.tsx +82 -0
  21. package/src/listItem/IconButton/ListItemIconButton.spec.tsx +119 -0
  22. package/src/listItem/Image/ListItemImage.spec.tsx +27 -0
  23. package/src/listItem/ListItem.css +5 -0
  24. package/src/listItem/ListItem.less +8 -1
  25. package/src/listItem/ListItem.spec.tsx +1406 -7
  26. package/src/listItem/ListItem.tsx +2 -1
  27. package/src/listItem/Navigation/ListItemNavigation.spec.tsx +59 -0
  28. package/src/listItem/Prompt/ListItemPrompt.spec.tsx +14 -27
  29. package/src/listItem/Prompt/ListItemPrompt.story.tsx +5 -3
  30. package/src/listItem/Radio/ListItemRadio.spec.tsx +66 -0
  31. package/src/listItem/Switch/ListItemSwitch.spec.tsx +47 -0
  32. package/src/listItem/_stories/ListItem.layout.test.story.tsx +21 -1
  33. package/src/listItem/_stories/ListItem.variants.test.story.tsx +1 -1
  34. package/src/main.css +5 -0
  35. package/src/test-utils/Parameters.d.ts +0 -77
@@ -0,0 +1,82 @@
1
+ import { render, screen } from '../../test-utils';
2
+ import userEvent from '@testing-library/user-event';
3
+ import { ListItem, type Props as ListItemProps } from '../ListItem';
4
+
5
+ describe('ListItem.Checkbox', () => {
6
+ const renderWith = (overrides: Partial<ListItemProps> = {}) =>
7
+ render(<ListItem title="Test title" {...overrides} />);
8
+
9
+ it('renders checkbox', () => {
10
+ renderWith({ control: <ListItem.Checkbox /> });
11
+ expect(screen.getByRole('checkbox')).toBeInTheDocument();
12
+ });
13
+
14
+ describe('checked state', () => {
15
+ it('reflects checked state', () => {
16
+ renderWith({ control: <ListItem.Checkbox checked onChange={jest.fn()} /> });
17
+ expect(screen.getByRole('checkbox')).toBeChecked();
18
+ });
19
+
20
+ it('reflects unchecked state', () => {
21
+ renderWith({ control: <ListItem.Checkbox checked={false} onChange={jest.fn()} /> });
22
+ expect(screen.getByRole('checkbox')).not.toBeChecked();
23
+ });
24
+
25
+ it('supports indeterminate state', () => {
26
+ renderWith({ control: <ListItem.Checkbox indeterminate /> });
27
+ expect(screen.getByRole('checkbox')).toHaveProperty('indeterminate', true);
28
+ });
29
+ });
30
+
31
+ describe('interactivity', () => {
32
+ it('handles onChange events', async () => {
33
+ const handleChange = jest.fn();
34
+ renderWith({ control: <ListItem.Checkbox checked={false} onChange={handleChange} /> });
35
+
36
+ await userEvent.click(screen.getByRole('checkbox'));
37
+ expect(handleChange).toHaveBeenCalledTimes(1);
38
+ });
39
+
40
+ it('is disabled when ListItem is disabled', () => {
41
+ renderWith({
42
+ disabled: true,
43
+ control: <ListItem.Checkbox checked={false} onChange={jest.fn()} />,
44
+ });
45
+
46
+ expect(screen.getByRole('checkbox')).toBeDisabled();
47
+ });
48
+
49
+ it('handles onFocus events', async () => {
50
+ const handleFocus = jest.fn();
51
+ renderWith({
52
+ control: <ListItem.Checkbox checked={false} onFocus={handleFocus} onChange={() => {}} />,
53
+ });
54
+
55
+ await userEvent.tab();
56
+ expect(handleFocus).toHaveBeenCalledTimes(1);
57
+ });
58
+
59
+ it('handles onBlur events', async () => {
60
+ const handleBlur = jest.fn();
61
+ renderWith({
62
+ control: <ListItem.Checkbox checked={false} onBlur={handleBlur} onChange={() => {}} />,
63
+ });
64
+
65
+ const checkbox = screen.getByRole('checkbox');
66
+ await userEvent.click(checkbox);
67
+ await userEvent.tab();
68
+ expect(handleBlur).toHaveBeenCalledTimes(1);
69
+ });
70
+ });
71
+
72
+ it('supports name and value attributes', () => {
73
+ const checkboxName = 'test-checkbox';
74
+ const checkboxValue = 'test-value';
75
+ renderWith({ control: <ListItem.Checkbox name={checkboxName} value={checkboxValue} /> });
76
+
77
+ const checkbox = screen.getByRole('checkbox');
78
+ expect(checkbox).toHaveAttribute('name', checkboxName);
79
+ // eslint-disable-next-line jest-dom/prefer-to-have-value
80
+ expect(checkbox).toHaveAttribute('value', checkboxValue);
81
+ });
82
+ });
@@ -0,0 +1,119 @@
1
+ import { Edit } from '@transferwise/icons';
2
+ import userEvent from '@testing-library/user-event';
3
+ import { mockMatchMedia, render, screen } from '../../test-utils';
4
+ import { ListItem, type Props as ListItemProps } from '../ListItem';
5
+
6
+ mockMatchMedia();
7
+
8
+ describe('ListItem.IconButton', () => {
9
+ const renderWith = (overrides: Partial<ListItemProps> = {}) =>
10
+ render(<ListItem title="Test title" {...overrides} />);
11
+
12
+ describe('as button', () => {
13
+ it('renders as button by default', () => {
14
+ renderWith({
15
+ control: (
16
+ <ListItem.IconButton>
17
+ <Edit />
18
+ </ListItem.IconButton>
19
+ ),
20
+ });
21
+ expect(screen.getByRole('button')).toBeInTheDocument();
22
+ });
23
+
24
+ it('renders as button if onClick is provided', () => {
25
+ renderWith({
26
+ control: (
27
+ <ListItem.IconButton onClick={() => {}}>
28
+ <Edit />
29
+ </ListItem.IconButton>
30
+ ),
31
+ });
32
+
33
+ expect(screen.getByRole('button')).toBeInTheDocument();
34
+ });
35
+
36
+ it('handles onClick events', async () => {
37
+ const handleClick = jest.fn();
38
+ renderWith({
39
+ control: (
40
+ <ListItem.IconButton onClick={handleClick}>
41
+ <Edit />
42
+ </ListItem.IconButton>
43
+ ),
44
+ });
45
+
46
+ await userEvent.click(screen.getByRole('button'));
47
+ expect(handleClick).toHaveBeenCalledTimes(1);
48
+ });
49
+
50
+ it('is disabled when ListItem is disabled', async () => {
51
+ const handleClick = jest.fn();
52
+ renderWith({
53
+ disabled: true,
54
+ control: (
55
+ <ListItem.IconButton onClick={handleClick}>
56
+ <Edit />
57
+ </ListItem.IconButton>
58
+ ),
59
+ });
60
+
61
+ const button = screen.getByRole('button');
62
+ expect(button).toBeDisabled();
63
+ await userEvent.click(button);
64
+ expect(handleClick).not.toHaveBeenCalled();
65
+ });
66
+ });
67
+
68
+ describe('as link', () => {
69
+ it('renders as link when href is provided', () => {
70
+ renderWith({
71
+ control: (
72
+ <ListItem.IconButton href="/test">
73
+ <Edit />
74
+ </ListItem.IconButton>
75
+ ),
76
+ });
77
+
78
+ expect(screen.getByRole('link')).toHaveAttribute('href', '/test');
79
+ });
80
+
81
+ it('supports target attribute for links', () => {
82
+ renderWith({
83
+ control: (
84
+ <ListItem.IconButton href="/test" target="_blank">
85
+ <Edit />
86
+ </ListItem.IconButton>
87
+ ),
88
+ });
89
+
90
+ const link = screen.getByRole('link');
91
+ expect(link).toHaveAttribute('target', '_blank');
92
+ expect(link).toHaveAttribute('rel', 'noopener noreferrer');
93
+ });
94
+
95
+ it('is disabled when ListItem is disabled', async () => {
96
+ renderWith({
97
+ disabled: true,
98
+ control: (
99
+ <ListItem.IconButton href="/test">
100
+ <Edit />
101
+ </ListItem.IconButton>
102
+ ),
103
+ });
104
+ expect(screen.getByRole('link')).toHaveAttribute('aria-disabled', 'true');
105
+ });
106
+ });
107
+
108
+ it('renders children content', () => {
109
+ renderWith({
110
+ control: (
111
+ <ListItem.IconButton>
112
+ <Edit />
113
+ </ListItem.IconButton>
114
+ ),
115
+ });
116
+
117
+ expect(screen.getByTestId('edit-icon')).toBeInTheDocument();
118
+ });
119
+ });
@@ -0,0 +1,27 @@
1
+ import { render, screen } from '../../test-utils';
2
+ import { ListItem } from '../ListItem';
3
+
4
+ describe('ListItem.Image', () => {
5
+ it('renders image with presentation role when no alt text', () => {
6
+ render(<ListItem.Image src="test-image.jpg" />);
7
+ expect(screen.getByRole('presentation')).toHaveAttribute('src', 'test-image.jpg');
8
+ });
9
+
10
+ it('renders image with graphics-symbol role when alt text provided', () => {
11
+ render(<ListItem.Image src="test-image.jpg" alt="Test image description" />);
12
+
13
+ const image = screen.getByRole('graphics-symbol');
14
+ expect(image).toHaveAttribute('alt', 'Test image description');
15
+ expect(image).toHaveAttribute('src', 'test-image.jpg');
16
+ });
17
+
18
+ it('renders image with loading prop', () => {
19
+ render(<ListItem.Image src="test-image.jpg" loading="lazy" />);
20
+ expect(screen.getByRole('presentation')).toHaveAttribute('loading', 'lazy');
21
+ });
22
+
23
+ it('renders image with className prop', () => {
24
+ render(<ListItem.Image src="test-image.jpg" className="custom-image-class" />);
25
+ expect(screen.getByRole('presentation')).toHaveClass('custom-image-class');
26
+ });
27
+ });
@@ -372,6 +372,11 @@
372
372
  padding: var(--size-12);
373
373
  container-type: inline-size;
374
374
  }
375
+ .wds-list-item + .wds-list-item-spotlight,
376
+ .wds-list-item-spotlight + .wds-list-item {
377
+ margin-top: 12px;
378
+ margin-top: var(--size-12);
379
+ }
375
380
  .wds-list-item:focus-within {
376
381
  z-index: 1;
377
382
  }
@@ -10,6 +10,11 @@
10
10
  padding: var(--size-12);
11
11
  container-type: inline-size;
12
12
 
13
+ & + .wds-list-item-spotlight,
14
+ .wds-list-item-spotlight + &{
15
+ margin-top: var(--size-12);
16
+ }
17
+
13
18
  &:focus-within{
14
19
  z-index: 1;
15
20
  }
@@ -136,7 +141,7 @@
136
141
  &-control-wrapper {
137
142
  grid-area: control;
138
143
  }
139
-
144
+
140
145
  &-control {
141
146
  flex: 0 0 auto;
142
147
  }
@@ -154,6 +159,8 @@
154
159
  }
155
160
  }
156
161
 
162
+
163
+
157
164
  &-spotlight {
158
165
  &-active {
159
166
  background-color: var(--color-background-neutral);