uikit-react-public 0.32.3 → 0.32.4
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/dist/components/Snackbar/Snackbar.d.ts +1 -1
- package/dist/components/Snackbar/Snackbar.stories.d.ts +1 -0
- package/dist/index.js +719 -711
- package/lib/components/Snackbar/Snackbar.stories.tsx +11 -0
- package/lib/components/Snackbar/Snackbar.tsx +14 -9
- package/lib/components/Snackbar/Snackbars.stories.tsx +11 -0
- package/lib/components/Snackbar/__tests__/Snackbar.test.tsx +128 -20
- package/lib/components/Snackbar/__tests__/__snapshots__/Snackbar.test.tsx.snap +15 -11
- package/package.json +1 -1
|
@@ -49,6 +49,17 @@ export const Error: Story = {
|
|
|
49
49
|
},
|
|
50
50
|
};
|
|
51
51
|
|
|
52
|
+
export const Success: Story = {
|
|
53
|
+
name: 'Variant: Success',
|
|
54
|
+
args: {
|
|
55
|
+
action: 'close',
|
|
56
|
+
children: 'This is a success snackbar',
|
|
57
|
+
size: 'small',
|
|
58
|
+
variant: 'success',
|
|
59
|
+
onClose: () => alert('Close action triggered'),
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
|
|
52
63
|
export const LongText: Story = {
|
|
53
64
|
name: 'With long text',
|
|
54
65
|
args: {
|
|
@@ -14,7 +14,7 @@ export interface SnackbarBaseProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
14
14
|
onUndo?: () => void;
|
|
15
15
|
size?: 'small' | 'large';
|
|
16
16
|
testId?: string;
|
|
17
|
-
variant?: 'default' | 'error';
|
|
17
|
+
variant?: 'default' | 'error' | 'success';
|
|
18
18
|
ref?: Ref<HTMLDivElement>;
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -35,8 +35,17 @@ const Snackbar = ({
|
|
|
35
35
|
...props
|
|
36
36
|
}: SnackbarProps) => {
|
|
37
37
|
const [theme] = useTheme();
|
|
38
|
-
const IconComponent =
|
|
39
|
-
|
|
38
|
+
const IconComponent = {
|
|
39
|
+
default: Icon.Info,
|
|
40
|
+
error: Icon.AlertTriangle,
|
|
41
|
+
success: Icon.CheckCircle,
|
|
42
|
+
}[variant];
|
|
43
|
+
// Success token currently differs from Figma (#008E49).
|
|
44
|
+
const backgroundColor = {
|
|
45
|
+
default: theme.colour.fill.brandPrimary,
|
|
46
|
+
error: theme.colour.fill.critical,
|
|
47
|
+
success: theme.colour.fill.success,
|
|
48
|
+
}[variant];
|
|
40
49
|
const role = variant === 'error' ? 'alert' : 'status';
|
|
41
50
|
const iconSize = size === 'small' ? 20 : 32;
|
|
42
51
|
const padding = size === 'small' ? theme.padding.p16 : theme.padding.p24;
|
|
@@ -56,11 +65,7 @@ const Snackbar = ({
|
|
|
56
65
|
z-index: 9999;
|
|
57
66
|
padding: ${padding};
|
|
58
67
|
color: ${theme.colour.text.inverse};
|
|
59
|
-
background-color: ${
|
|
60
|
-
variant === 'error'
|
|
61
|
-
? theme.primitiveColour.red['10'].$value.hex
|
|
62
|
-
: theme.colour.bg.inversePrimary
|
|
63
|
-
};
|
|
68
|
+
background-color: ${backgroundColor};
|
|
64
69
|
`;
|
|
65
70
|
|
|
66
71
|
const style = cx(NAME, baseStyles, marginsStyle(props, theme), className);
|
|
@@ -168,7 +173,7 @@ const Snackbar = ({
|
|
|
168
173
|
level='lg-semibold'
|
|
169
174
|
className={undoButtonTextStyle}
|
|
170
175
|
>
|
|
171
|
-
|
|
176
|
+
Undo
|
|
172
177
|
</Text>
|
|
173
178
|
</button>
|
|
174
179
|
)}
|
|
@@ -116,6 +116,17 @@ export const Interactive: Story = {
|
|
|
116
116
|
>
|
|
117
117
|
Add error snackbar
|
|
118
118
|
</Button>
|
|
119
|
+
<Button
|
|
120
|
+
onClick={() =>
|
|
121
|
+
addSnackbar({
|
|
122
|
+
children: 'Success snackbar',
|
|
123
|
+
size: 'small',
|
|
124
|
+
variant: 'success',
|
|
125
|
+
})
|
|
126
|
+
}
|
|
127
|
+
>
|
|
128
|
+
Add success snackbar
|
|
129
|
+
</Button>
|
|
119
130
|
</div>
|
|
120
131
|
<Snackbars
|
|
121
132
|
{...args}
|
|
@@ -2,18 +2,32 @@ import { describe, expect, test, vi, beforeEach } from 'vitest';
|
|
|
2
2
|
import { render, screen } from '@testing-library/react';
|
|
3
3
|
// import '@testing-library/jest-dom';
|
|
4
4
|
import Snackbar from '../Snackbar';
|
|
5
|
-
import
|
|
5
|
+
import Icon from '../../Icon';
|
|
6
|
+
import { ThemeContextProvider, themes } from '../../../theme/useTheme';
|
|
7
|
+
|
|
8
|
+
const tokenTestTheme = {
|
|
9
|
+
...themes.light,
|
|
10
|
+
colour: {
|
|
11
|
+
...themes.light.colour,
|
|
12
|
+
fill: {
|
|
13
|
+
...themes.light.colour.fill,
|
|
14
|
+
brandPrimary: '#010101',
|
|
15
|
+
critical: '#020202',
|
|
16
|
+
success: '#030303',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
};
|
|
6
20
|
|
|
7
21
|
describe('Snackbar', () => {
|
|
8
22
|
beforeEach(() => {
|
|
9
|
-
vi.
|
|
23
|
+
vi.restoreAllMocks();
|
|
10
24
|
});
|
|
11
25
|
|
|
12
26
|
// Snapshot tests
|
|
13
27
|
|
|
14
28
|
test('snapshot: minimal props', () => {
|
|
15
29
|
const renderResult = render(
|
|
16
|
-
<ThemeContextProvider>
|
|
30
|
+
<ThemeContextProvider theme='light'>
|
|
17
31
|
<Snackbar action='close'>Test snackbar</Snackbar>
|
|
18
32
|
</ThemeContextProvider>
|
|
19
33
|
);
|
|
@@ -22,7 +36,7 @@ describe('Snackbar', () => {
|
|
|
22
36
|
|
|
23
37
|
test('snapshot: custom test id', () => {
|
|
24
38
|
const renderResult = render(
|
|
25
|
-
<ThemeContextProvider>
|
|
39
|
+
<ThemeContextProvider theme='light'>
|
|
26
40
|
<Snackbar
|
|
27
41
|
action='undo'
|
|
28
42
|
testId='custom-test-id'
|
|
@@ -39,7 +53,7 @@ describe('Snackbar', () => {
|
|
|
39
53
|
test('Test ID: Default', () => {
|
|
40
54
|
const defaultTestId = 'ucl-uikit-snackbar';
|
|
41
55
|
render(
|
|
42
|
-
<ThemeContextProvider>
|
|
56
|
+
<ThemeContextProvider theme='light'>
|
|
43
57
|
<Snackbar action='close'>Test snackbar</Snackbar>
|
|
44
58
|
</ThemeContextProvider>
|
|
45
59
|
);
|
|
@@ -49,7 +63,7 @@ describe('Snackbar', () => {
|
|
|
49
63
|
|
|
50
64
|
test('Test ID: Custom', () => {
|
|
51
65
|
render(
|
|
52
|
-
<ThemeContextProvider>
|
|
66
|
+
<ThemeContextProvider theme='light'>
|
|
53
67
|
<Snackbar
|
|
54
68
|
action='undo'
|
|
55
69
|
testId='custom-test-id'
|
|
@@ -66,7 +80,7 @@ describe('Snackbar', () => {
|
|
|
66
80
|
const ref = { current: null as HTMLDivElement | null };
|
|
67
81
|
|
|
68
82
|
render(
|
|
69
|
-
<ThemeContextProvider>
|
|
83
|
+
<ThemeContextProvider theme='light'>
|
|
70
84
|
<Snackbar ref={ref}>Test snackbar</Snackbar>
|
|
71
85
|
</ThemeContextProvider>
|
|
72
86
|
);
|
|
@@ -76,7 +90,7 @@ describe('Snackbar', () => {
|
|
|
76
90
|
|
|
77
91
|
test('Default variant uses polite status semantics', () => {
|
|
78
92
|
render(
|
|
79
|
-
<ThemeContextProvider>
|
|
93
|
+
<ThemeContextProvider theme='light'>
|
|
80
94
|
<Snackbar action='undo'>Test snackbar</Snackbar>
|
|
81
95
|
</ThemeContextProvider>
|
|
82
96
|
);
|
|
@@ -87,7 +101,7 @@ describe('Snackbar', () => {
|
|
|
87
101
|
|
|
88
102
|
test('Error variant uses assertive alert semantics', () => {
|
|
89
103
|
render(
|
|
90
|
-
<ThemeContextProvider>
|
|
104
|
+
<ThemeContextProvider theme='light'>
|
|
91
105
|
<Snackbar
|
|
92
106
|
action='close'
|
|
93
107
|
variant='error'
|
|
@@ -101,9 +115,50 @@ describe('Snackbar', () => {
|
|
|
101
115
|
expect(snackbar.textContent).toBe('Test snackbar');
|
|
102
116
|
});
|
|
103
117
|
|
|
118
|
+
test('Success variant uses polite status semantics', () => {
|
|
119
|
+
render(
|
|
120
|
+
<ThemeContextProvider theme='light'>
|
|
121
|
+
<Snackbar
|
|
122
|
+
action='close'
|
|
123
|
+
variant='success'
|
|
124
|
+
>
|
|
125
|
+
Test snackbar
|
|
126
|
+
</Snackbar>
|
|
127
|
+
</ThemeContextProvider>
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
const snackbar = screen.getByRole('status');
|
|
131
|
+
expect(snackbar.textContent).toBe('Test snackbar');
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test.each([
|
|
135
|
+
['default', 'rgb(1, 1, 1)'],
|
|
136
|
+
['error', 'rgb(2, 2, 2)'],
|
|
137
|
+
['success', 'rgb(3, 3, 3)'],
|
|
138
|
+
] as const)(
|
|
139
|
+
'%s variant uses its semantic background token',
|
|
140
|
+
(variant, colour) => {
|
|
141
|
+
render(
|
|
142
|
+
<ThemeContextProvider theme={tokenTestTheme}>
|
|
143
|
+
<Snackbar
|
|
144
|
+
action='close'
|
|
145
|
+
variant={variant}
|
|
146
|
+
>
|
|
147
|
+
Test snackbar
|
|
148
|
+
</Snackbar>
|
|
149
|
+
</ThemeContextProvider>
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
expect(
|
|
153
|
+
getComputedStyle(screen.getByTestId('ucl-uikit-snackbar'))
|
|
154
|
+
.backgroundColor
|
|
155
|
+
).toBe(colour);
|
|
156
|
+
}
|
|
157
|
+
);
|
|
158
|
+
|
|
104
159
|
test('Close button has a default accessible name', () => {
|
|
105
160
|
render(
|
|
106
|
-
<ThemeContextProvider>
|
|
161
|
+
<ThemeContextProvider theme='light'>
|
|
107
162
|
<Snackbar action='close'>Test snackbar</Snackbar>
|
|
108
163
|
</ThemeContextProvider>
|
|
109
164
|
);
|
|
@@ -117,7 +172,7 @@ describe('Snackbar', () => {
|
|
|
117
172
|
|
|
118
173
|
test('Close button accessible name can be customised', () => {
|
|
119
174
|
render(
|
|
120
|
-
<ThemeContextProvider>
|
|
175
|
+
<ThemeContextProvider theme='light'>
|
|
121
176
|
<Snackbar
|
|
122
177
|
action='close'
|
|
123
178
|
closeButtonAriaLabel='Dismiss saved notification'
|
|
@@ -137,7 +192,7 @@ describe('Snackbar', () => {
|
|
|
137
192
|
test('Close callback is called', () => {
|
|
138
193
|
const onClose = vi.fn();
|
|
139
194
|
render(
|
|
140
|
-
<ThemeContextProvider>
|
|
195
|
+
<ThemeContextProvider theme='light'>
|
|
141
196
|
<Snackbar
|
|
142
197
|
action='close'
|
|
143
198
|
onClose={onClose}
|
|
@@ -154,7 +209,7 @@ describe('Snackbar', () => {
|
|
|
154
209
|
test('Undo callback is called', () => {
|
|
155
210
|
const onUndo = vi.fn();
|
|
156
211
|
render(
|
|
157
|
-
<ThemeContextProvider>
|
|
212
|
+
<ThemeContextProvider theme='light'>
|
|
158
213
|
<Snackbar
|
|
159
214
|
action='undo'
|
|
160
215
|
onUndo={onUndo}
|
|
@@ -168,9 +223,43 @@ describe('Snackbar', () => {
|
|
|
168
223
|
expect(onUndo).toHaveBeenCalled();
|
|
169
224
|
});
|
|
170
225
|
|
|
226
|
+
test('Undo action uses sentence case label', () => {
|
|
227
|
+
render(
|
|
228
|
+
<ThemeContextProvider theme='light'>
|
|
229
|
+
<Snackbar action='undo'>Test snackbar</Snackbar>
|
|
230
|
+
</ThemeContextProvider>
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
expect(screen.getByRole('button', { name: 'Undo' })).toBeDefined();
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
test('Default variant renders info icon', () => {
|
|
237
|
+
vi.spyOn(Icon, 'Info').mockImplementation((props) => (
|
|
238
|
+
<svg
|
|
239
|
+
data-testid='info-icon'
|
|
240
|
+
{...props}
|
|
241
|
+
/>
|
|
242
|
+
));
|
|
243
|
+
|
|
244
|
+
render(
|
|
245
|
+
<ThemeContextProvider theme='light'>
|
|
246
|
+
<Snackbar action='close'>Test snackbar</Snackbar>
|
|
247
|
+
</ThemeContextProvider>
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
expect(screen.getByTestId('info-icon')).toBeDefined();
|
|
251
|
+
});
|
|
252
|
+
|
|
171
253
|
test('Error variant renders warning icon', () => {
|
|
254
|
+
vi.spyOn(Icon, 'AlertTriangle').mockImplementation((props) => (
|
|
255
|
+
<svg
|
|
256
|
+
data-testid='alert-triangle-icon'
|
|
257
|
+
{...props}
|
|
258
|
+
/>
|
|
259
|
+
));
|
|
260
|
+
|
|
172
261
|
render(
|
|
173
|
-
<ThemeContextProvider>
|
|
262
|
+
<ThemeContextProvider theme='light'>
|
|
174
263
|
<Snackbar
|
|
175
264
|
action='close'
|
|
176
265
|
variant='error'
|
|
@@ -180,15 +269,34 @@ describe('Snackbar', () => {
|
|
|
180
269
|
</ThemeContextProvider>
|
|
181
270
|
);
|
|
182
271
|
|
|
183
|
-
|
|
184
|
-
|
|
272
|
+
expect(screen.getByTestId('alert-triangle-icon')).toBeDefined();
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
test('Success variant renders check icon', () => {
|
|
276
|
+
vi.spyOn(Icon, 'CheckCircle').mockImplementation((props) => (
|
|
277
|
+
<svg
|
|
278
|
+
data-testid='check-circle-icon'
|
|
279
|
+
{...props}
|
|
280
|
+
/>
|
|
281
|
+
));
|
|
282
|
+
|
|
283
|
+
render(
|
|
284
|
+
<ThemeContextProvider theme='light'>
|
|
285
|
+
<Snackbar
|
|
286
|
+
action='close'
|
|
287
|
+
variant='success'
|
|
288
|
+
>
|
|
289
|
+
Test snackbar
|
|
290
|
+
</Snackbar>
|
|
291
|
+
</ThemeContextProvider>
|
|
292
|
+
);
|
|
185
293
|
|
|
186
|
-
expect(
|
|
294
|
+
expect(screen.getByTestId('check-circle-icon')).toBeDefined();
|
|
187
295
|
});
|
|
188
296
|
|
|
189
297
|
test('Decorative icons are hidden from assistive technology', () => {
|
|
190
298
|
render(
|
|
191
|
-
<ThemeContextProvider>
|
|
299
|
+
<ThemeContextProvider theme='light'>
|
|
192
300
|
<Snackbar action='close'>Test snackbar</Snackbar>
|
|
193
301
|
</ThemeContextProvider>
|
|
194
302
|
);
|
|
@@ -203,7 +311,7 @@ describe('Snackbar', () => {
|
|
|
203
311
|
test("Close callback cannot be called when action is 'undo'", () => {
|
|
204
312
|
const onClose = vi.fn();
|
|
205
313
|
render(
|
|
206
|
-
<ThemeContextProvider>
|
|
314
|
+
<ThemeContextProvider theme='light'>
|
|
207
315
|
<Snackbar
|
|
208
316
|
action='undo'
|
|
209
317
|
onClose={onClose}
|
|
@@ -221,7 +329,7 @@ describe('Snackbar', () => {
|
|
|
221
329
|
test("Undo callback cannot be called when action is 'close'", () => {
|
|
222
330
|
const onUndo = vi.fn();
|
|
223
331
|
render(
|
|
224
|
-
<ThemeContextProvider>
|
|
332
|
+
<ThemeContextProvider theme='light'>
|
|
225
333
|
<Snackbar
|
|
226
334
|
action='close'
|
|
227
335
|
onUndo={onUndo}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
exports[`Snackbar > snapshot: custom test id 1`] = `
|
|
4
4
|
<div
|
|
5
|
-
class="ucl-uikit-snackbar css-
|
|
5
|
+
class="ucl-uikit-snackbar css-4vd8ej"
|
|
6
6
|
data-testid="custom-test-id"
|
|
7
7
|
>
|
|
8
8
|
<svg
|
|
@@ -20,11 +20,13 @@ exports[`Snackbar > snapshot: custom test id 1`] = `
|
|
|
20
20
|
width="32"
|
|
21
21
|
xmlns="http://www.w3.org/2000/svg"
|
|
22
22
|
>
|
|
23
|
-
<
|
|
24
|
-
|
|
23
|
+
<circle
|
|
24
|
+
cx="12"
|
|
25
|
+
cy="12"
|
|
26
|
+
r="10"
|
|
25
27
|
/>
|
|
26
28
|
<path
|
|
27
|
-
d="
|
|
29
|
+
d="M12 16v-4m0-4h.01"
|
|
28
30
|
/>
|
|
29
31
|
</svg>
|
|
30
32
|
<span
|
|
@@ -38,14 +40,14 @@ exports[`Snackbar > snapshot: custom test id 1`] = `
|
|
|
38
40
|
class="css-1xjm0bq"
|
|
39
41
|
>
|
|
40
42
|
<button
|
|
41
|
-
class="css-
|
|
43
|
+
class="css-1s4q0nw"
|
|
42
44
|
data-testid="custom-test-id-undo-button"
|
|
43
45
|
>
|
|
44
46
|
<span
|
|
45
47
|
class="ucl-uikit-text css-1ccjqc4"
|
|
46
48
|
data-testid="ucl-uikit-text"
|
|
47
49
|
>
|
|
48
|
-
|
|
50
|
+
Undo
|
|
49
51
|
</span>
|
|
50
52
|
</button>
|
|
51
53
|
</span>
|
|
@@ -54,7 +56,7 @@ exports[`Snackbar > snapshot: custom test id 1`] = `
|
|
|
54
56
|
|
|
55
57
|
exports[`Snackbar > snapshot: minimal props 1`] = `
|
|
56
58
|
<div
|
|
57
|
-
class="ucl-uikit-snackbar css-
|
|
59
|
+
class="ucl-uikit-snackbar css-4vd8ej"
|
|
58
60
|
data-testid="ucl-uikit-snackbar"
|
|
59
61
|
>
|
|
60
62
|
<svg
|
|
@@ -72,11 +74,13 @@ exports[`Snackbar > snapshot: minimal props 1`] = `
|
|
|
72
74
|
width="32"
|
|
73
75
|
xmlns="http://www.w3.org/2000/svg"
|
|
74
76
|
>
|
|
75
|
-
<
|
|
76
|
-
|
|
77
|
+
<circle
|
|
78
|
+
cx="12"
|
|
79
|
+
cy="12"
|
|
80
|
+
r="10"
|
|
77
81
|
/>
|
|
78
82
|
<path
|
|
79
|
-
d="
|
|
83
|
+
d="M12 16v-4m0-4h.01"
|
|
80
84
|
/>
|
|
81
85
|
</svg>
|
|
82
86
|
<span
|
|
@@ -91,7 +95,7 @@ exports[`Snackbar > snapshot: minimal props 1`] = `
|
|
|
91
95
|
>
|
|
92
96
|
<button
|
|
93
97
|
aria-label="Dismiss notification"
|
|
94
|
-
class="ucl-uikit-icon-button css-
|
|
98
|
+
class="ucl-uikit-icon-button css-uv5ig"
|
|
95
99
|
data-testid="ucl-uikit-snackbar-close-button"
|
|
96
100
|
>
|
|
97
101
|
<svg
|