@khanacademy/wonder-blocks-banner 1.0.0 → 1.1.0
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/CHANGELOG.md +22 -0
- package/dist/es/index.js +9 -6
- package/dist/index.js +292 -5740
- package/package.json +7 -6
- package/src/components/__docs__/banner.argtypes.js +9 -0
- package/src/components/__docs__/banner.stories.js +1 -0
- package/src/components/__tests__/banner.test.js +51 -20
- package/src/components/banner.js +26 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khanacademy/wonder-blocks-banner",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"design": "v1",
|
|
5
5
|
"description": "Banner components for Wonder Blocks.",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -16,13 +16,14 @@
|
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@babel/runtime": "^7.18.6",
|
|
19
|
-
"@khanacademy/wonder-blocks-button": "^3.0.
|
|
19
|
+
"@khanacademy/wonder-blocks-button": "^3.0.6",
|
|
20
20
|
"@khanacademy/wonder-blocks-color": "^1.2.0",
|
|
21
|
-
"@khanacademy/wonder-blocks-core": "^4.
|
|
22
|
-
"@khanacademy/wonder-blocks-icon": "^1.2.
|
|
23
|
-
"@khanacademy/wonder-blocks-icon-button": "^3.4.
|
|
21
|
+
"@khanacademy/wonder-blocks-core": "^4.5.0",
|
|
22
|
+
"@khanacademy/wonder-blocks-icon": "^1.2.32",
|
|
23
|
+
"@khanacademy/wonder-blocks-icon-button": "^3.4.14",
|
|
24
|
+
"@khanacademy/wonder-blocks-link": "^3.8.12",
|
|
24
25
|
"@khanacademy/wonder-blocks-spacing": "^3.0.5",
|
|
25
|
-
"@khanacademy/wonder-blocks-typography": "^1.1.
|
|
26
|
+
"@khanacademy/wonder-blocks-typography": "^1.1.34"
|
|
26
27
|
},
|
|
27
28
|
"peerDependencies": {
|
|
28
29
|
"aphrodite": "^1.2.5",
|
|
@@ -86,4 +86,13 @@ export default {
|
|
|
86
86
|
},
|
|
87
87
|
type: {required: false},
|
|
88
88
|
},
|
|
89
|
+
"aria-label": {
|
|
90
|
+
control: {type: "text"},
|
|
91
|
+
description:
|
|
92
|
+
"Accessible label for the banner. This is read out before the other contents of the banner.",
|
|
93
|
+
table: {
|
|
94
|
+
type: {summary: "string"},
|
|
95
|
+
},
|
|
96
|
+
type: {required: false},
|
|
97
|
+
},
|
|
89
98
|
};
|
|
@@ -9,7 +9,7 @@ describe("Banner", () => {
|
|
|
9
9
|
// Arrange
|
|
10
10
|
|
|
11
11
|
// Act
|
|
12
|
-
render(<Banner text="" layout="floating" />);
|
|
12
|
+
render(<Banner text="test text" layout="floating" />);
|
|
13
13
|
|
|
14
14
|
// Assert
|
|
15
15
|
const button = screen.queryByRole("button");
|
|
@@ -20,7 +20,9 @@ describe("Banner", () => {
|
|
|
20
20
|
// Arrange
|
|
21
21
|
|
|
22
22
|
// Act
|
|
23
|
-
render(
|
|
23
|
+
render(
|
|
24
|
+
<Banner text="test text" onDismiss={() => {}} layout="floating" />,
|
|
25
|
+
);
|
|
24
26
|
|
|
25
27
|
// Assert
|
|
26
28
|
const button = screen.queryByRole("button");
|
|
@@ -30,7 +32,13 @@ describe("Banner", () => {
|
|
|
30
32
|
test("clicking the dismiss button triggers `onDismiss`", () => {
|
|
31
33
|
// Arrange
|
|
32
34
|
const onDismissSpy = jest.fn();
|
|
33
|
-
render(
|
|
35
|
+
render(
|
|
36
|
+
<Banner
|
|
37
|
+
text="test text"
|
|
38
|
+
onDismiss={onDismissSpy}
|
|
39
|
+
layout="floating"
|
|
40
|
+
/>,
|
|
41
|
+
);
|
|
34
42
|
|
|
35
43
|
// Act
|
|
36
44
|
const button = screen.getByRole("button");
|
|
@@ -46,7 +54,7 @@ describe("Banner", () => {
|
|
|
46
54
|
// Act
|
|
47
55
|
render(
|
|
48
56
|
<Banner
|
|
49
|
-
text=""
|
|
57
|
+
text="test text"
|
|
50
58
|
layout="floating"
|
|
51
59
|
actions={[{title: "some link", href: "/", onClick: () => {}}]}
|
|
52
60
|
/>,
|
|
@@ -63,7 +71,7 @@ describe("Banner", () => {
|
|
|
63
71
|
// Act
|
|
64
72
|
render(
|
|
65
73
|
<Banner
|
|
66
|
-
text=""
|
|
74
|
+
text="test text"
|
|
67
75
|
layout="floating"
|
|
68
76
|
actions={[{title: "some button", onClick: () => {}}]}
|
|
69
77
|
/>,
|
|
@@ -80,7 +88,7 @@ describe("Banner", () => {
|
|
|
80
88
|
// Act
|
|
81
89
|
render(
|
|
82
90
|
<Banner
|
|
83
|
-
text=""
|
|
91
|
+
text="test text"
|
|
84
92
|
layout="floating"
|
|
85
93
|
actions={[
|
|
86
94
|
{title: "button 1", onClick: () => {}},
|
|
@@ -101,7 +109,7 @@ describe("Banner", () => {
|
|
|
101
109
|
|
|
102
110
|
render(
|
|
103
111
|
<Banner
|
|
104
|
-
text=""
|
|
112
|
+
text="test text"
|
|
105
113
|
layout="floating"
|
|
106
114
|
actions={[{title: "a button", onClick: actionSpy}]}
|
|
107
115
|
/>,
|
|
@@ -121,7 +129,7 @@ describe("Banner", () => {
|
|
|
121
129
|
|
|
122
130
|
render(
|
|
123
131
|
<Banner
|
|
124
|
-
text=""
|
|
132
|
+
text="test text"
|
|
125
133
|
layout="floating"
|
|
126
134
|
actions={[{title: "a link", onClick: actionSpy, href: "/"}]}
|
|
127
135
|
/>,
|
|
@@ -140,7 +148,7 @@ describe("Banner", () => {
|
|
|
140
148
|
|
|
141
149
|
render(
|
|
142
150
|
<Banner
|
|
143
|
-
text=""
|
|
151
|
+
text="test text"
|
|
144
152
|
layout="floating"
|
|
145
153
|
actions={[{title: "a button", onClick: () => {}, href: "/foo"}]}
|
|
146
154
|
/>,
|
|
@@ -159,7 +167,7 @@ describe("Banner", () => {
|
|
|
159
167
|
// Arrange
|
|
160
168
|
|
|
161
169
|
// Act
|
|
162
|
-
render(<Banner text="" layout="floating" />);
|
|
170
|
+
render(<Banner text="test text" layout="floating" />);
|
|
163
171
|
|
|
164
172
|
// Assert
|
|
165
173
|
const icon = screen.getByTestId("banner-kind-icon");
|
|
@@ -172,7 +180,7 @@ describe("Banner", () => {
|
|
|
172
180
|
// Arrange
|
|
173
181
|
|
|
174
182
|
// Act
|
|
175
|
-
render(<Banner text="" kind={kind} layout="floating" />);
|
|
183
|
+
render(<Banner text="test text" kind={kind} layout="floating" />);
|
|
176
184
|
|
|
177
185
|
// Assert
|
|
178
186
|
const icon = screen.getByTestId("banner-kind-icon");
|
|
@@ -186,7 +194,9 @@ describe("Banner", () => {
|
|
|
186
194
|
// Arrange
|
|
187
195
|
|
|
188
196
|
// Act
|
|
189
|
-
render(
|
|
197
|
+
render(
|
|
198
|
+
<Banner text="test text" layout="floating" onDismiss={() => {}} />,
|
|
199
|
+
);
|
|
190
200
|
|
|
191
201
|
// Assert
|
|
192
202
|
const dismissButton = screen.getByRole("button");
|
|
@@ -199,7 +209,7 @@ describe("Banner", () => {
|
|
|
199
209
|
// Act
|
|
200
210
|
render(
|
|
201
211
|
<Banner
|
|
202
|
-
text=""
|
|
212
|
+
text="test text"
|
|
203
213
|
layout="floating"
|
|
204
214
|
onDismiss={() => {}}
|
|
205
215
|
dismissAriaLabel="Test dismiss aria label"
|
|
@@ -220,7 +230,7 @@ describe("Banner", () => {
|
|
|
220
230
|
// Act
|
|
221
231
|
render(
|
|
222
232
|
<Banner
|
|
223
|
-
text=""
|
|
233
|
+
text="test text"
|
|
224
234
|
layout="floating"
|
|
225
235
|
actions={[{title: "Test button title", onClick: () => {}}]}
|
|
226
236
|
/>,
|
|
@@ -237,7 +247,7 @@ describe("Banner", () => {
|
|
|
237
247
|
// Act
|
|
238
248
|
render(
|
|
239
249
|
<Banner
|
|
240
|
-
text=""
|
|
250
|
+
text="test text"
|
|
241
251
|
layout="floating"
|
|
242
252
|
actions={[{title: "Test link title", href: "/"}]}
|
|
243
253
|
/>,
|
|
@@ -254,7 +264,7 @@ describe("Banner", () => {
|
|
|
254
264
|
// Act
|
|
255
265
|
render(
|
|
256
266
|
<Banner
|
|
257
|
-
text=""
|
|
267
|
+
text="test text"
|
|
258
268
|
layout="floating"
|
|
259
269
|
actions={[
|
|
260
270
|
{
|
|
@@ -280,7 +290,7 @@ describe("Banner", () => {
|
|
|
280
290
|
// Act
|
|
281
291
|
render(
|
|
282
292
|
<Banner
|
|
283
|
-
text=""
|
|
293
|
+
text="test text"
|
|
284
294
|
layout="floating"
|
|
285
295
|
actions={[
|
|
286
296
|
{
|
|
@@ -311,7 +321,7 @@ describe("Banner", () => {
|
|
|
311
321
|
// Act
|
|
312
322
|
render(
|
|
313
323
|
<Banner
|
|
314
|
-
text=""
|
|
324
|
+
text="test text"
|
|
315
325
|
kind={kind}
|
|
316
326
|
layout="floating"
|
|
317
327
|
testId="wonder-blocks-banner-test-id"
|
|
@@ -329,8 +339,8 @@ describe("Banner", () => {
|
|
|
329
339
|
// Act
|
|
330
340
|
render(
|
|
331
341
|
<Banner
|
|
332
|
-
text=""
|
|
333
|
-
kind=
|
|
342
|
+
text="test text"
|
|
343
|
+
kind="warning"
|
|
334
344
|
layout="floating"
|
|
335
345
|
testId="wonder-blocks-banner-test-id"
|
|
336
346
|
/>,
|
|
@@ -340,4 +350,25 @@ describe("Banner", () => {
|
|
|
340
350
|
const banner = screen.getByTestId("wonder-blocks-banner-test-id");
|
|
341
351
|
expect(banner).toHaveAttribute("aria-live", "polite");
|
|
342
352
|
});
|
|
353
|
+
|
|
354
|
+
test("aria-label prop becomes aria-label attribute on the banner", () => {
|
|
355
|
+
// Arrange
|
|
356
|
+
|
|
357
|
+
// Act
|
|
358
|
+
render(
|
|
359
|
+
<Banner
|
|
360
|
+
text="test text"
|
|
361
|
+
layout="full-width"
|
|
362
|
+
testId="wonder-blocks-banner-test-id"
|
|
363
|
+
aria-label="This is a banner aria label."
|
|
364
|
+
/>,
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
// Assert
|
|
368
|
+
const banner = screen.getByTestId("wonder-blocks-banner-test-id");
|
|
369
|
+
expect(banner).toHaveAttribute(
|
|
370
|
+
"aria-label",
|
|
371
|
+
"This is a banner aria label.",
|
|
372
|
+
);
|
|
373
|
+
});
|
|
343
374
|
});
|
package/src/components/banner.js
CHANGED
|
@@ -6,8 +6,8 @@ import Button from "@khanacademy/wonder-blocks-button";
|
|
|
6
6
|
import Color from "@khanacademy/wonder-blocks-color";
|
|
7
7
|
import {View} from "@khanacademy/wonder-blocks-core";
|
|
8
8
|
import Icon, {icons} from "@khanacademy/wonder-blocks-icon";
|
|
9
|
-
import Link from "@khanacademy/wonder-blocks-link";
|
|
10
9
|
import IconButton from "@khanacademy/wonder-blocks-icon-button";
|
|
10
|
+
import Link from "@khanacademy/wonder-blocks-link";
|
|
11
11
|
import Spacing from "@khanacademy/wonder-blocks-spacing";
|
|
12
12
|
import {LabelSmall} from "@khanacademy/wonder-blocks-typography";
|
|
13
13
|
|
|
@@ -68,6 +68,12 @@ type BannerValues = {|
|
|
|
68
68
|
|};
|
|
69
69
|
|
|
70
70
|
type Props = {|
|
|
71
|
+
/**
|
|
72
|
+
* Accessible label for the banner.
|
|
73
|
+
* This is read out before the other contents of the banner.
|
|
74
|
+
*/
|
|
75
|
+
"aria-label"?: string,
|
|
76
|
+
|
|
71
77
|
/**
|
|
72
78
|
* Determines the color and icon of the banner.
|
|
73
79
|
*/
|
|
@@ -160,11 +166,19 @@ const valuesForKind = (kind: BannerKind): BannerValues => {
|
|
|
160
166
|
* ```
|
|
161
167
|
*/
|
|
162
168
|
const Banner = (props: Props): React.Node => {
|
|
163
|
-
const {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
169
|
+
const {
|
|
170
|
+
actions,
|
|
171
|
+
// Suppressing lint on the next line because it's saying `aria-label`
|
|
172
|
+
// is missing in props validation when it's not.
|
|
173
|
+
// eslint-disable-next-line react/prop-types
|
|
174
|
+
"aria-label": ariaLabel,
|
|
175
|
+
dismissAriaLabel,
|
|
176
|
+
onDismiss,
|
|
177
|
+
kind,
|
|
178
|
+
layout,
|
|
179
|
+
text,
|
|
180
|
+
testId,
|
|
181
|
+
} = props;
|
|
168
182
|
|
|
169
183
|
const renderActions = () => {
|
|
170
184
|
return actions?.filter(Boolean).map((action) => {
|
|
@@ -204,17 +218,17 @@ const Banner = (props: Props): React.Node => {
|
|
|
204
218
|
<View
|
|
205
219
|
style={[
|
|
206
220
|
styles.containerOuter,
|
|
207
|
-
|
|
221
|
+
layout === "floating" && styles.floatingBorder,
|
|
208
222
|
{borderInlineStartColor: valuesForKind(kind).color},
|
|
209
223
|
]}
|
|
210
224
|
role={valuesForKind(kind).role}
|
|
225
|
+
aria-label={ariaLabel}
|
|
211
226
|
aria-live={valuesForKind(kind).ariaLive}
|
|
212
227
|
testId={testId}
|
|
213
228
|
>
|
|
214
229
|
<View
|
|
215
230
|
style={[
|
|
216
231
|
styles.backgroundColor,
|
|
217
|
-
layoutStyle,
|
|
218
232
|
{backgroundColor: valuesForKind(kind).color},
|
|
219
233
|
]}
|
|
220
234
|
/>
|
|
@@ -336,6 +350,10 @@ const styles = StyleSheet.create({
|
|
|
336
350
|
marginLeft: Spacing.xSmall_8,
|
|
337
351
|
marginRight: Spacing.xSmall_8,
|
|
338
352
|
},
|
|
353
|
+
floatingBorder: {
|
|
354
|
+
borderRadius: 4,
|
|
355
|
+
overflow: "hidden",
|
|
356
|
+
},
|
|
339
357
|
});
|
|
340
358
|
|
|
341
359
|
export default Banner;
|