@khanacademy/wonder-blocks-button 2.10.1 → 2.10.2
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/package.json +11 -11
- package/src/__tests__/__snapshots__/generated-snapshot.test.js.snap +240 -11
- package/src/__tests__/generated-snapshot.test.js +74 -12
- package/src/components/__docs__/button.argtypes.js +3 -6
- package/src/components/__docs__/navigation-callbacks.stories.mdx +68 -0
- package/src/components/button.js +4 -5
- package/src/components/button.md +134 -23
- package/src/components/button.stories.js +69 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khanacademy/wonder-blocks-button",
|
|
3
|
-
"version": "2.10.
|
|
3
|
+
"version": "2.10.2",
|
|
4
4
|
"design": "v1",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -15,14 +15,14 @@
|
|
|
15
15
|
"author": "",
|
|
16
16
|
"license": "MIT",
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@babel/runtime": "^7.
|
|
19
|
-
"@khanacademy/wonder-blocks-clickable": "^2.2.
|
|
20
|
-
"@khanacademy/wonder-blocks-color": "^1.1.
|
|
21
|
-
"@khanacademy/wonder-blocks-core": "^
|
|
22
|
-
"@khanacademy/wonder-blocks-icon": "^1.2.
|
|
23
|
-
"@khanacademy/wonder-blocks-progress-spinner": "^1.1.
|
|
24
|
-
"@khanacademy/wonder-blocks-spacing": "^3.0.
|
|
25
|
-
"@khanacademy/wonder-blocks-typography": "^1.1.
|
|
18
|
+
"@babel/runtime": "^7.16.3",
|
|
19
|
+
"@khanacademy/wonder-blocks-clickable": "^2.2.1",
|
|
20
|
+
"@khanacademy/wonder-blocks-color": "^1.1.20",
|
|
21
|
+
"@khanacademy/wonder-blocks-core": "^4.0.0",
|
|
22
|
+
"@khanacademy/wonder-blocks-icon": "^1.2.24",
|
|
23
|
+
"@khanacademy/wonder-blocks-progress-spinner": "^1.1.28",
|
|
24
|
+
"@khanacademy/wonder-blocks-spacing": "^3.0.5",
|
|
25
|
+
"@khanacademy/wonder-blocks-typography": "^1.1.28"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"aphrodite": "^1.2.5",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"react-router-dom": "5.3.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"wb-dev-build-settings": "^0.
|
|
34
|
+
"wb-dev-build-settings": "^0.2.0"
|
|
35
35
|
},
|
|
36
|
-
"gitHead": "
|
|
36
|
+
"gitHead": "9ebea88533e702011165072f090a377e02fa3f0f"
|
|
37
37
|
}
|
|
@@ -2850,7 +2850,7 @@ exports[`wonder-blocks-button example 9 1`] = `
|
|
|
2850
2850
|
}
|
|
2851
2851
|
}
|
|
2852
2852
|
>
|
|
2853
|
-
|
|
2853
|
+
beforeNav, client-side nav
|
|
2854
2854
|
</span>
|
|
2855
2855
|
</a>
|
|
2856
2856
|
<a
|
|
@@ -2918,7 +2918,7 @@ exports[`wonder-blocks-button example 9 1`] = `
|
|
|
2918
2918
|
}
|
|
2919
2919
|
}
|
|
2920
2920
|
>
|
|
2921
|
-
|
|
2921
|
+
beforeNav, server-side nav
|
|
2922
2922
|
</span>
|
|
2923
2923
|
</a>
|
|
2924
2924
|
<a
|
|
@@ -2987,7 +2987,7 @@ exports[`wonder-blocks-button example 9 1`] = `
|
|
|
2987
2987
|
}
|
|
2988
2988
|
}
|
|
2989
2989
|
>
|
|
2990
|
-
|
|
2990
|
+
beforeNav, open URL in new tab
|
|
2991
2991
|
</span>
|
|
2992
2992
|
</a>
|
|
2993
2993
|
</div>
|
|
@@ -3078,13 +3078,242 @@ exports[`wonder-blocks-button example 10 1`] = `
|
|
|
3078
3078
|
}
|
|
3079
3079
|
}
|
|
3080
3080
|
>
|
|
3081
|
-
|
|
3081
|
+
safeWithNav, client-side nav
|
|
3082
|
+
</span>
|
|
3083
|
+
</a>
|
|
3084
|
+
<a
|
|
3085
|
+
className=""
|
|
3086
|
+
href="/foo"
|
|
3087
|
+
onBlur={[Function]}
|
|
3088
|
+
onClick={[Function]}
|
|
3089
|
+
onDragStart={[Function]}
|
|
3090
|
+
onFocus={[Function]}
|
|
3091
|
+
onKeyDown={[Function]}
|
|
3092
|
+
onKeyUp={[Function]}
|
|
3093
|
+
onMouseDown={[Function]}
|
|
3094
|
+
onMouseEnter={[Function]}
|
|
3095
|
+
onMouseLeave={[Function]}
|
|
3096
|
+
onMouseUp={[Function]}
|
|
3097
|
+
onTouchCancel={[Function]}
|
|
3098
|
+
onTouchEnd={[Function]}
|
|
3099
|
+
onTouchStart={[Function]}
|
|
3100
|
+
role="button"
|
|
3101
|
+
style={
|
|
3102
|
+
Object {
|
|
3103
|
+
":focus": Object {
|
|
3104
|
+
"WebkitTapHighlightColor": "rgba(0,0,0,0)",
|
|
3105
|
+
},
|
|
3106
|
+
"alignItems": "center",
|
|
3107
|
+
"background": "#1865f2",
|
|
3108
|
+
"border": "none",
|
|
3109
|
+
"borderRadius": 4,
|
|
3110
|
+
"boxSizing": "border-box",
|
|
3111
|
+
"color": "#ffffff",
|
|
3112
|
+
"cursor": "pointer",
|
|
3113
|
+
"display": "inline-flex",
|
|
3114
|
+
"height": 40,
|
|
3115
|
+
"justifyContent": "center",
|
|
3116
|
+
"marginRight": 10,
|
|
3117
|
+
"outline": "none",
|
|
3118
|
+
"paddingBottom": 0,
|
|
3119
|
+
"paddingLeft": 16,
|
|
3120
|
+
"paddingRight": 16,
|
|
3121
|
+
"paddingTop": 0,
|
|
3122
|
+
"position": "relative",
|
|
3123
|
+
"textDecoration": "none",
|
|
3124
|
+
"touchAction": "manipulation",
|
|
3125
|
+
"userSelect": "none",
|
|
3126
|
+
}
|
|
3127
|
+
}
|
|
3128
|
+
tabIndex={0}
|
|
3129
|
+
>
|
|
3130
|
+
<span
|
|
3131
|
+
className=""
|
|
3132
|
+
style={
|
|
3133
|
+
Object {
|
|
3134
|
+
"MozOsxFontSmoothing": "grayscale",
|
|
3135
|
+
"WebkitFontSmoothing": "antialiased",
|
|
3136
|
+
"alignItems": "center",
|
|
3137
|
+
"display": "inline-block",
|
|
3138
|
+
"fontFamily": "Lato, \\"Noto Sans\\", sans-serif",
|
|
3139
|
+
"fontSize": 16,
|
|
3140
|
+
"fontWeight": "bold",
|
|
3141
|
+
"lineHeight": "20px",
|
|
3142
|
+
"overflow": "hidden",
|
|
3143
|
+
"pointerEvents": "none",
|
|
3144
|
+
"textOverflow": "ellipsis",
|
|
3145
|
+
"whiteSpace": "nowrap",
|
|
3146
|
+
}
|
|
3147
|
+
}
|
|
3148
|
+
>
|
|
3149
|
+
safeWithNav, server-side nav
|
|
3150
|
+
</span>
|
|
3151
|
+
</a>
|
|
3152
|
+
<a
|
|
3153
|
+
className=""
|
|
3154
|
+
href="https://google.com"
|
|
3155
|
+
onBlur={[Function]}
|
|
3156
|
+
onClick={[Function]}
|
|
3157
|
+
onDragStart={[Function]}
|
|
3158
|
+
onFocus={[Function]}
|
|
3159
|
+
onKeyDown={[Function]}
|
|
3160
|
+
onKeyUp={[Function]}
|
|
3161
|
+
onMouseDown={[Function]}
|
|
3162
|
+
onMouseEnter={[Function]}
|
|
3163
|
+
onMouseLeave={[Function]}
|
|
3164
|
+
onMouseUp={[Function]}
|
|
3165
|
+
onTouchCancel={[Function]}
|
|
3166
|
+
onTouchEnd={[Function]}
|
|
3167
|
+
onTouchStart={[Function]}
|
|
3168
|
+
rel="noopener noreferrer"
|
|
3169
|
+
role="button"
|
|
3170
|
+
style={
|
|
3171
|
+
Object {
|
|
3172
|
+
":focus": Object {
|
|
3173
|
+
"WebkitTapHighlightColor": "rgba(0,0,0,0)",
|
|
3174
|
+
},
|
|
3175
|
+
"alignItems": "center",
|
|
3176
|
+
"background": "#1865f2",
|
|
3177
|
+
"border": "none",
|
|
3178
|
+
"borderRadius": 4,
|
|
3179
|
+
"boxSizing": "border-box",
|
|
3180
|
+
"color": "#ffffff",
|
|
3181
|
+
"cursor": "pointer",
|
|
3182
|
+
"display": "inline-flex",
|
|
3183
|
+
"height": 40,
|
|
3184
|
+
"justifyContent": "center",
|
|
3185
|
+
"marginRight": 10,
|
|
3186
|
+
"outline": "none",
|
|
3187
|
+
"paddingBottom": 0,
|
|
3188
|
+
"paddingLeft": 16,
|
|
3189
|
+
"paddingRight": 16,
|
|
3190
|
+
"paddingTop": 0,
|
|
3191
|
+
"position": "relative",
|
|
3192
|
+
"textDecoration": "none",
|
|
3193
|
+
"touchAction": "manipulation",
|
|
3194
|
+
"userSelect": "none",
|
|
3195
|
+
}
|
|
3196
|
+
}
|
|
3197
|
+
tabIndex={0}
|
|
3198
|
+
target="_blank"
|
|
3199
|
+
>
|
|
3200
|
+
<span
|
|
3201
|
+
className=""
|
|
3202
|
+
style={
|
|
3203
|
+
Object {
|
|
3204
|
+
"MozOsxFontSmoothing": "grayscale",
|
|
3205
|
+
"WebkitFontSmoothing": "antialiased",
|
|
3206
|
+
"alignItems": "center",
|
|
3207
|
+
"display": "inline-block",
|
|
3208
|
+
"fontFamily": "Lato, \\"Noto Sans\\", sans-serif",
|
|
3209
|
+
"fontSize": 16,
|
|
3210
|
+
"fontWeight": "bold",
|
|
3211
|
+
"lineHeight": "20px",
|
|
3212
|
+
"overflow": "hidden",
|
|
3213
|
+
"pointerEvents": "none",
|
|
3214
|
+
"textOverflow": "ellipsis",
|
|
3215
|
+
"whiteSpace": "nowrap",
|
|
3216
|
+
}
|
|
3217
|
+
}
|
|
3218
|
+
>
|
|
3219
|
+
safeWithNav, open URL in new tab
|
|
3082
3220
|
</span>
|
|
3083
3221
|
</a>
|
|
3084
3222
|
</div>
|
|
3085
3223
|
`;
|
|
3086
3224
|
|
|
3087
3225
|
exports[`wonder-blocks-button example 11 1`] = `
|
|
3226
|
+
<div
|
|
3227
|
+
className=""
|
|
3228
|
+
style={
|
|
3229
|
+
Object {
|
|
3230
|
+
"alignItems": "center",
|
|
3231
|
+
"borderStyle": "solid",
|
|
3232
|
+
"borderWidth": 0,
|
|
3233
|
+
"boxSizing": "border-box",
|
|
3234
|
+
"display": "flex",
|
|
3235
|
+
"flexDirection": "row",
|
|
3236
|
+
"margin": 0,
|
|
3237
|
+
"minHeight": 0,
|
|
3238
|
+
"minWidth": 0,
|
|
3239
|
+
"padding": 0,
|
|
3240
|
+
"position": "relative",
|
|
3241
|
+
"zIndex": 0,
|
|
3242
|
+
}
|
|
3243
|
+
}
|
|
3244
|
+
>
|
|
3245
|
+
<a
|
|
3246
|
+
className=""
|
|
3247
|
+
href="/foo"
|
|
3248
|
+
onBlur={[Function]}
|
|
3249
|
+
onClick={[Function]}
|
|
3250
|
+
onDragStart={[Function]}
|
|
3251
|
+
onFocus={[Function]}
|
|
3252
|
+
onKeyDown={[Function]}
|
|
3253
|
+
onKeyUp={[Function]}
|
|
3254
|
+
onMouseDown={[Function]}
|
|
3255
|
+
onMouseEnter={[Function]}
|
|
3256
|
+
onMouseLeave={[Function]}
|
|
3257
|
+
onMouseUp={[Function]}
|
|
3258
|
+
onTouchCancel={[Function]}
|
|
3259
|
+
onTouchEnd={[Function]}
|
|
3260
|
+
onTouchStart={[Function]}
|
|
3261
|
+
role="button"
|
|
3262
|
+
style={
|
|
3263
|
+
Object {
|
|
3264
|
+
":focus": Object {
|
|
3265
|
+
"WebkitTapHighlightColor": "rgba(0,0,0,0)",
|
|
3266
|
+
},
|
|
3267
|
+
"alignItems": "center",
|
|
3268
|
+
"background": "#1865f2",
|
|
3269
|
+
"border": "none",
|
|
3270
|
+
"borderRadius": 4,
|
|
3271
|
+
"boxSizing": "border-box",
|
|
3272
|
+
"color": "#ffffff",
|
|
3273
|
+
"cursor": "pointer",
|
|
3274
|
+
"display": "inline-flex",
|
|
3275
|
+
"height": 40,
|
|
3276
|
+
"justifyContent": "center",
|
|
3277
|
+
"marginRight": 10,
|
|
3278
|
+
"outline": "none",
|
|
3279
|
+
"paddingBottom": 0,
|
|
3280
|
+
"paddingLeft": 16,
|
|
3281
|
+
"paddingRight": 16,
|
|
3282
|
+
"paddingTop": 0,
|
|
3283
|
+
"position": "relative",
|
|
3284
|
+
"textDecoration": "none",
|
|
3285
|
+
"touchAction": "manipulation",
|
|
3286
|
+
"userSelect": "none",
|
|
3287
|
+
}
|
|
3288
|
+
}
|
|
3289
|
+
tabIndex={0}
|
|
3290
|
+
>
|
|
3291
|
+
<span
|
|
3292
|
+
className=""
|
|
3293
|
+
style={
|
|
3294
|
+
Object {
|
|
3295
|
+
"MozOsxFontSmoothing": "grayscale",
|
|
3296
|
+
"WebkitFontSmoothing": "antialiased",
|
|
3297
|
+
"alignItems": "center",
|
|
3298
|
+
"display": "inline-block",
|
|
3299
|
+
"fontFamily": "Lato, \\"Noto Sans\\", sans-serif",
|
|
3300
|
+
"fontSize": 16,
|
|
3301
|
+
"fontWeight": "bold",
|
|
3302
|
+
"lineHeight": "20px",
|
|
3303
|
+
"overflow": "hidden",
|
|
3304
|
+
"pointerEvents": "none",
|
|
3305
|
+
"textOverflow": "ellipsis",
|
|
3306
|
+
"whiteSpace": "nowrap",
|
|
3307
|
+
}
|
|
3308
|
+
}
|
|
3309
|
+
>
|
|
3310
|
+
This button prevents navigation.
|
|
3311
|
+
</span>
|
|
3312
|
+
</a>
|
|
3313
|
+
</div>
|
|
3314
|
+
`;
|
|
3315
|
+
|
|
3316
|
+
exports[`wonder-blocks-button example 12 1`] = `
|
|
3088
3317
|
<div
|
|
3089
3318
|
className=""
|
|
3090
3319
|
style={
|
|
@@ -3718,7 +3947,7 @@ exports[`wonder-blocks-button example 11 1`] = `
|
|
|
3718
3947
|
</div>
|
|
3719
3948
|
`;
|
|
3720
3949
|
|
|
3721
|
-
exports[`wonder-blocks-button example
|
|
3950
|
+
exports[`wonder-blocks-button example 13 1`] = `
|
|
3722
3951
|
<div
|
|
3723
3952
|
className=""
|
|
3724
3953
|
style={
|
|
@@ -3817,7 +4046,7 @@ exports[`wonder-blocks-button example 12 1`] = `
|
|
|
3817
4046
|
</div>
|
|
3818
4047
|
`;
|
|
3819
4048
|
|
|
3820
|
-
exports[`wonder-blocks-button example
|
|
4049
|
+
exports[`wonder-blocks-button example 14 1`] = `
|
|
3821
4050
|
<div
|
|
3822
4051
|
className=""
|
|
3823
4052
|
style={
|
|
@@ -3912,7 +4141,7 @@ exports[`wonder-blocks-button example 13 1`] = `
|
|
|
3912
4141
|
</div>
|
|
3913
4142
|
`;
|
|
3914
4143
|
|
|
3915
|
-
exports[`wonder-blocks-button example
|
|
4144
|
+
exports[`wonder-blocks-button example 15 1`] = `
|
|
3916
4145
|
<div
|
|
3917
4146
|
className=""
|
|
3918
4147
|
style={
|
|
@@ -4139,7 +4368,7 @@ exports[`wonder-blocks-button example 14 1`] = `
|
|
|
4139
4368
|
</div>
|
|
4140
4369
|
`;
|
|
4141
4370
|
|
|
4142
|
-
exports[`wonder-blocks-button example
|
|
4371
|
+
exports[`wonder-blocks-button example 16 1`] = `
|
|
4143
4372
|
<div
|
|
4144
4373
|
className=""
|
|
4145
4374
|
style={
|
|
@@ -4313,7 +4542,7 @@ exports[`wonder-blocks-button example 15 1`] = `
|
|
|
4313
4542
|
</div>
|
|
4314
4543
|
`;
|
|
4315
4544
|
|
|
4316
|
-
exports[`wonder-blocks-button example
|
|
4545
|
+
exports[`wonder-blocks-button example 17 1`] = `
|
|
4317
4546
|
<div
|
|
4318
4547
|
className=""
|
|
4319
4548
|
style={
|
|
@@ -4488,7 +4717,7 @@ exports[`wonder-blocks-button example 16 1`] = `
|
|
|
4488
4717
|
</div>
|
|
4489
4718
|
`;
|
|
4490
4719
|
|
|
4491
|
-
exports[`wonder-blocks-button example
|
|
4720
|
+
exports[`wonder-blocks-button example 18 1`] = `
|
|
4492
4721
|
<div
|
|
4493
4722
|
className=""
|
|
4494
4723
|
style={
|
|
@@ -4677,7 +4906,7 @@ exports[`wonder-blocks-button example 17 1`] = `
|
|
|
4677
4906
|
</div>
|
|
4678
4907
|
`;
|
|
4679
4908
|
|
|
4680
|
-
exports[`wonder-blocks-button example
|
|
4909
|
+
exports[`wonder-blocks-button example 19 1`] = `
|
|
4681
4910
|
<div
|
|
4682
4911
|
className=""
|
|
4683
4912
|
style={
|
|
@@ -426,7 +426,7 @@ describe("wonder-blocks-button", () => {
|
|
|
426
426
|
})
|
|
427
427
|
}
|
|
428
428
|
>
|
|
429
|
-
|
|
429
|
+
beforeNav, client-side nav
|
|
430
430
|
</Button>
|
|
431
431
|
<Button
|
|
432
432
|
href="/foo"
|
|
@@ -438,7 +438,7 @@ describe("wonder-blocks-button", () => {
|
|
|
438
438
|
})
|
|
439
439
|
}
|
|
440
440
|
>
|
|
441
|
-
|
|
441
|
+
beforeNav, server-side nav
|
|
442
442
|
</Button>
|
|
443
443
|
<Button
|
|
444
444
|
href="https://google.com"
|
|
@@ -451,7 +451,7 @@ describe("wonder-blocks-button", () => {
|
|
|
451
451
|
})
|
|
452
452
|
}
|
|
453
453
|
>
|
|
454
|
-
|
|
454
|
+
beforeNav, open URL in new tab
|
|
455
455
|
</Button>
|
|
456
456
|
<Switch>
|
|
457
457
|
<Route path="/foo">
|
|
@@ -482,9 +482,38 @@ describe("wonder-blocks-button", () => {
|
|
|
482
482
|
<Button
|
|
483
483
|
href="/foo"
|
|
484
484
|
style={styles.button}
|
|
485
|
-
|
|
485
|
+
safeWithNav={() =>
|
|
486
|
+
new Promise((resolve, reject) => {
|
|
487
|
+
setTimeout(resolve, 1000);
|
|
488
|
+
})
|
|
489
|
+
}
|
|
490
|
+
>
|
|
491
|
+
safeWithNav, client-side nav
|
|
492
|
+
</Button>
|
|
493
|
+
<Button
|
|
494
|
+
href="/foo"
|
|
495
|
+
style={styles.button}
|
|
496
|
+
skipClientNav={true}
|
|
497
|
+
safeWithNav={() =>
|
|
498
|
+
new Promise((resolve, reject) => {
|
|
499
|
+
setTimeout(resolve, 1000);
|
|
500
|
+
})
|
|
501
|
+
}
|
|
502
|
+
>
|
|
503
|
+
safeWithNav, server-side nav
|
|
504
|
+
</Button>
|
|
505
|
+
<Button
|
|
506
|
+
href="https://google.com"
|
|
507
|
+
target="_blank"
|
|
508
|
+
style={styles.button}
|
|
509
|
+
skipClientNav={true}
|
|
510
|
+
safeWithNav={() =>
|
|
511
|
+
new Promise((resolve, reject) => {
|
|
512
|
+
setTimeout(resolve, 1000);
|
|
513
|
+
})
|
|
514
|
+
}
|
|
486
515
|
>
|
|
487
|
-
|
|
516
|
+
safeWithNav, open URL in new tab
|
|
488
517
|
</Button>
|
|
489
518
|
<Switch>
|
|
490
519
|
<Route path="/foo">
|
|
@@ -499,6 +528,39 @@ describe("wonder-blocks-button", () => {
|
|
|
499
528
|
});
|
|
500
529
|
|
|
501
530
|
it("example 11", () => {
|
|
531
|
+
const styles = StyleSheet.create({
|
|
532
|
+
row: {
|
|
533
|
+
flexDirection: "row",
|
|
534
|
+
alignItems: "center",
|
|
535
|
+
},
|
|
536
|
+
button: {
|
|
537
|
+
marginRight: 10,
|
|
538
|
+
},
|
|
539
|
+
}); // NOTE: In actual code you would use BrowserRouter instead
|
|
540
|
+
|
|
541
|
+
const example = (
|
|
542
|
+
<MemoryRouter>
|
|
543
|
+
<View style={styles.row}>
|
|
544
|
+
<Button
|
|
545
|
+
href="/foo"
|
|
546
|
+
style={styles.button}
|
|
547
|
+
onClick={(e) => e.preventDefault()}
|
|
548
|
+
>
|
|
549
|
+
This button prevents navigation.
|
|
550
|
+
</Button>
|
|
551
|
+
<Switch>
|
|
552
|
+
<Route path="/foo">
|
|
553
|
+
<View id="foo">Hello, world!</View>
|
|
554
|
+
</Route>
|
|
555
|
+
</Switch>
|
|
556
|
+
</View>
|
|
557
|
+
</MemoryRouter>
|
|
558
|
+
);
|
|
559
|
+
const tree = renderer.create(example).toJSON();
|
|
560
|
+
expect(tree).toMatchSnapshot();
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
it("example 12", () => {
|
|
502
564
|
const styles = StyleSheet.create({
|
|
503
565
|
row: {
|
|
504
566
|
flexDirection: "row",
|
|
@@ -542,7 +604,7 @@ describe("wonder-blocks-button", () => {
|
|
|
542
604
|
expect(tree).toMatchSnapshot();
|
|
543
605
|
});
|
|
544
606
|
|
|
545
|
-
it("example
|
|
607
|
+
it("example 13", () => {
|
|
546
608
|
const example = (
|
|
547
609
|
<View>
|
|
548
610
|
<form onSubmit={() => alert("the form was submitted")}>
|
|
@@ -554,7 +616,7 @@ describe("wonder-blocks-button", () => {
|
|
|
554
616
|
expect(tree).toMatchSnapshot();
|
|
555
617
|
});
|
|
556
618
|
|
|
557
|
-
it("example
|
|
619
|
+
it("example 14", () => {
|
|
558
620
|
const example = (
|
|
559
621
|
<View>
|
|
560
622
|
<Button>Label</Button>
|
|
@@ -564,7 +626,7 @@ describe("wonder-blocks-button", () => {
|
|
|
564
626
|
expect(tree).toMatchSnapshot();
|
|
565
627
|
});
|
|
566
628
|
|
|
567
|
-
it("example
|
|
629
|
+
it("example 15", () => {
|
|
568
630
|
const styles = StyleSheet.create({
|
|
569
631
|
column: {
|
|
570
632
|
alignItems: "flex-start",
|
|
@@ -594,7 +656,7 @@ describe("wonder-blocks-button", () => {
|
|
|
594
656
|
expect(tree).toMatchSnapshot();
|
|
595
657
|
});
|
|
596
658
|
|
|
597
|
-
it("example
|
|
659
|
+
it("example 16", () => {
|
|
598
660
|
const styles = StyleSheet.create({
|
|
599
661
|
row: {
|
|
600
662
|
flexDirection: "row",
|
|
@@ -621,7 +683,7 @@ describe("wonder-blocks-button", () => {
|
|
|
621
683
|
expect(tree).toMatchSnapshot();
|
|
622
684
|
});
|
|
623
685
|
|
|
624
|
-
it("example
|
|
686
|
+
it("example 17", () => {
|
|
625
687
|
const styles = StyleSheet.create({
|
|
626
688
|
row: {
|
|
627
689
|
flexDirection: "row",
|
|
@@ -649,7 +711,7 @@ describe("wonder-blocks-button", () => {
|
|
|
649
711
|
expect(tree).toMatchSnapshot();
|
|
650
712
|
});
|
|
651
713
|
|
|
652
|
-
it("example
|
|
714
|
+
it("example 18", () => {
|
|
653
715
|
const styles = StyleSheet.create({
|
|
654
716
|
row: {
|
|
655
717
|
flexDirection: "row",
|
|
@@ -672,7 +734,7 @@ describe("wonder-blocks-button", () => {
|
|
|
672
734
|
expect(tree).toMatchSnapshot();
|
|
673
735
|
});
|
|
674
736
|
|
|
675
|
-
it("example
|
|
737
|
+
it("example 19", () => {
|
|
676
738
|
const styles = StyleSheet.create({
|
|
677
739
|
row: {
|
|
678
740
|
flexDirection: "row",
|
|
@@ -60,8 +60,7 @@ export default {
|
|
|
60
60
|
category: "Theming",
|
|
61
61
|
type: {
|
|
62
62
|
summary: "boolean",
|
|
63
|
-
detail:
|
|
64
|
-
"Sets primary button background color to white, and secondary and tertiary button title to color.",
|
|
63
|
+
detail: "Sets primary button background color to white, and secondary and tertiary button title to color.",
|
|
65
64
|
},
|
|
66
65
|
},
|
|
67
66
|
},
|
|
@@ -161,8 +160,7 @@ export default {
|
|
|
161
160
|
category: "Navigation",
|
|
162
161
|
type: {
|
|
163
162
|
summary: "Note",
|
|
164
|
-
detail:
|
|
165
|
-
"All URLs containing a protocol are considered external, e.g. https://khanacademy.org/math/algebra/eval-exprs will trigger a full page reload.",
|
|
163
|
+
detail: "All URLs containing a protocol are considered external, e.g. https://khanacademy.org/math/algebra/eval-exprs will trigger a full page reload.",
|
|
166
164
|
},
|
|
167
165
|
},
|
|
168
166
|
},
|
|
@@ -199,12 +197,11 @@ export default {
|
|
|
199
197
|
},
|
|
200
198
|
},
|
|
201
199
|
beforeNav: {
|
|
202
|
-
description: `Run async code before navigating. If the promise returned rejects then navigation will not occur.`,
|
|
200
|
+
description: `Run async code before navigating. If the promise returned rejects then navigation will not occur. If both safeWithNav and beforeNav are provided, beforeNav will be run first and safeWithNav will only be run if beforeNav does not reject.`,
|
|
203
201
|
table: {
|
|
204
202
|
category: "Navigation",
|
|
205
203
|
type: {
|
|
206
204
|
summary: "() => Promise<mixed>",
|
|
207
|
-
detail: `If both safeWithNav and beforeNav are provided, beforeNav will be run first and safeWithNav will only be run if beforeNav does not reject.`,
|
|
208
205
|
},
|
|
209
206
|
},
|
|
210
207
|
},
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import {Meta, Story, Canvas} from "@storybook/addon-docs";
|
|
2
|
+
import {StyleSheet} from "aphrodite";
|
|
3
|
+
|
|
4
|
+
import Button from "@khanacademy/wonder-blocks-button";
|
|
5
|
+
import {View} from "@khanacademy/wonder-blocks-core";
|
|
6
|
+
|
|
7
|
+
<Meta
|
|
8
|
+
title="Navigation/Button/Navigation Callbacks"
|
|
9
|
+
component={Button}
|
|
10
|
+
parameters={{
|
|
11
|
+
previewTabs: {
|
|
12
|
+
canvas: {hidden: true},
|
|
13
|
+
},
|
|
14
|
+
viewMode: "docs",
|
|
15
|
+
chromatic: {
|
|
16
|
+
// Disables chromatic testing for these stories.
|
|
17
|
+
disableSnapshot: true,
|
|
18
|
+
},
|
|
19
|
+
}}
|
|
20
|
+
/>
|
|
21
|
+
|
|
22
|
+
## Running Callbacks on Navigation
|
|
23
|
+
|
|
24
|
+
Sometimes you may need to run some code and also navigate when the user
|
|
25
|
+
clicks the button. For example, you might want to send a request to the
|
|
26
|
+
server and also send the user to a different page. You can do this by
|
|
27
|
+
passing in a URL to the `href` prop and also passing in a callback
|
|
28
|
+
function to either the `onClick`, `beforeNav`, or `safeWithNav` prop.
|
|
29
|
+
Which prop you choose depends on your use case.
|
|
30
|
+
|
|
31
|
+
- `onClick` is guaranteed to run to completion before navigation starts,
|
|
32
|
+
but it is not async aware, so it should only be used if all of the code
|
|
33
|
+
in your callback function executes synchronously.
|
|
34
|
+
|
|
35
|
+
- `beforeNav` is guaranteed to run async operations before navigation
|
|
36
|
+
starts. You must return a promise from the callback function passed in
|
|
37
|
+
to this prop, and the navigation will happen after the promise
|
|
38
|
+
resolves. If the promise rejects, the navigation will not occur.
|
|
39
|
+
This prop should be used if it's important that the async code
|
|
40
|
+
completely finishes before the next URL starts loading.
|
|
41
|
+
|
|
42
|
+
- `safeWithNav` runs async code concurrently with navigation when safe,
|
|
43
|
+
but delays navigation until the async code is finished when
|
|
44
|
+
concurrent execution is not safe. You must return a promise from the
|
|
45
|
+
callback function passed in to this prop, and Wonder Blocks will run
|
|
46
|
+
the async code in parallel with client-side navigation or while opening
|
|
47
|
+
a new tab, but will wait until the async code finishes to start a
|
|
48
|
+
server-side navigation. If the promise rejects the navigation will
|
|
49
|
+
happen anyway. This prop should be used when it's okay to load
|
|
50
|
+
the next URL while the async callback code is running.
|
|
51
|
+
|
|
52
|
+
This table gives an overview of the options:
|
|
53
|
+
|
|
54
|
+
| Prop | Async safe? | Completes before navigation? |
|
|
55
|
+
|-------------|-------------|------------------------------|
|
|
56
|
+
| onClick | no | yes |
|
|
57
|
+
| beforeNav | yes | yes |
|
|
58
|
+
| safeWithNav | yes | no |
|
|
59
|
+
|
|
60
|
+
It is possible to use more than one of these props on the same element.
|
|
61
|
+
If multiple props are used, they will run in this order: first `onClick`,
|
|
62
|
+
then `beforeNav`, then `safeWithNav`. If both `beforeNav` and `safeWithNav`
|
|
63
|
+
are used, the `safeWithNav` callback will not be called until the
|
|
64
|
+
`beforeNav` promise resolves successfully. If the `beforeNav` promise
|
|
65
|
+
rejects, `safeWithNav` will not be run.
|
|
66
|
+
|
|
67
|
+
If the `onClick` handler calls `preventDefault()`, then `beforeNav`
|
|
68
|
+
and `safeWithNav` will still run, but navigation will not occur.
|
package/src/components/button.js
CHANGED
|
@@ -139,11 +139,10 @@ export type SharedProps = {|
|
|
|
139
139
|
/**
|
|
140
140
|
* Function to call when button is clicked.
|
|
141
141
|
*
|
|
142
|
-
* This callback should be used for
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
* stubbed out.
|
|
142
|
+
* This callback should be used for running synchronous code, like
|
|
143
|
+
* dispatching a Redux action. For asynchronous code see the
|
|
144
|
+
* beforeNav and safeWithNav props. It should NOT be used to redirect
|
|
145
|
+
* to a different URL.
|
|
147
146
|
*
|
|
148
147
|
* Note: onClick is optional if href is present, but must be defined if
|
|
149
148
|
* href is not
|
package/src/components/button.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
### Example: kind
|
|
2
2
|
|
|
3
3
|
There are three `kind`s of buttons: `"primary"` (default), `"secondary"`, and
|
|
4
4
|
`"tertiary"`:
|
|
@@ -40,7 +40,7 @@ const styles = StyleSheet.create({
|
|
|
40
40
|
</View>
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
### Example: color
|
|
44
44
|
|
|
45
45
|
Buttons have a `color` that is either `"default"` (the default, as shown above) or `"destructive"` (as can seen below):
|
|
46
46
|
|
|
@@ -85,7 +85,7 @@ const styles = StyleSheet.create({
|
|
|
85
85
|
</View>
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
### Example: disabled
|
|
89
89
|
|
|
90
90
|
Buttons can be `disabled`:
|
|
91
91
|
|
|
@@ -139,7 +139,7 @@ const styles = StyleSheet.create({
|
|
|
139
139
|
</View>
|
|
140
140
|
```
|
|
141
141
|
|
|
142
|
-
|
|
142
|
+
### Example: dark
|
|
143
143
|
|
|
144
144
|
Buttons on a `darkBlue` background should set `light` to `true`.
|
|
145
145
|
```jsx
|
|
@@ -212,7 +212,7 @@ const styles = StyleSheet.create({
|
|
|
212
212
|
</View>
|
|
213
213
|
```
|
|
214
214
|
|
|
215
|
-
|
|
215
|
+
### Example: size
|
|
216
216
|
|
|
217
217
|
Buttons have a `size` that's either `"medium"` (default), `"small"`, or `"xlarge"`.
|
|
218
218
|
```js
|
|
@@ -309,7 +309,7 @@ const styles = StyleSheet.create({
|
|
|
309
309
|
</View>
|
|
310
310
|
```
|
|
311
311
|
|
|
312
|
-
|
|
312
|
+
### Example: spinner
|
|
313
313
|
|
|
314
314
|
Buttons can show a `spinner`. This is useful when indicating to a user that
|
|
315
315
|
their input has been recognized but that the operation will take some time.
|
|
@@ -343,7 +343,7 @@ const styles = StyleSheet.create({
|
|
|
343
343
|
</View>
|
|
344
344
|
```
|
|
345
345
|
|
|
346
|
-
|
|
346
|
+
### Example: Navigation
|
|
347
347
|
|
|
348
348
|
```jsx
|
|
349
349
|
import Button from "@khanacademy/wonder-blocks-button";
|
|
@@ -384,7 +384,7 @@ const styles = StyleSheet.create({
|
|
|
384
384
|
</View>
|
|
385
385
|
```
|
|
386
386
|
|
|
387
|
-
|
|
387
|
+
### Example: Navigation with React Router
|
|
388
388
|
|
|
389
389
|
Buttons do client-side navigation by default, if React Router exists:
|
|
390
390
|
```jsx
|
|
@@ -420,12 +420,59 @@ const styles = StyleSheet.create({
|
|
|
420
420
|
</View>
|
|
421
421
|
</MemoryRouter>
|
|
422
422
|
```
|
|
423
|
+
### Running callbacks on navigation
|
|
424
|
+
|
|
425
|
+
Sometimes you may need to run some code and also navigate when the user
|
|
426
|
+
clicks the button. For example, you might want to send a request to the
|
|
427
|
+
server and also send the user to a different page. You can do this by
|
|
428
|
+
passing in a URL to the `href` prop and also passing in a callback
|
|
429
|
+
function to either the `onClick`, `beforeNav`, or `safeWithNav` prop.
|
|
430
|
+
Which prop you choose depends on your use case.
|
|
431
|
+
|
|
432
|
+
- `onClick` is guaranteed to run to completion before navigation starts,
|
|
433
|
+
but it is not async aware, so it should only be used if all of the code
|
|
434
|
+
in your callback function executes synchronously.
|
|
435
|
+
|
|
436
|
+
- `beforeNav` is guaranteed to run async operations before navigation
|
|
437
|
+
starts. You must return a promise from the callback function passed in
|
|
438
|
+
to this prop, and the navigation will happen after the promise
|
|
439
|
+
resolves. If the promise rejects, the navigation will not occur.
|
|
440
|
+
This prop should be used if it's important that the async code
|
|
441
|
+
completely finishes before the next URL starts loading.
|
|
442
|
+
|
|
443
|
+
- `safeWithNav` runs async code concurrently with navigation when safe,
|
|
444
|
+
but delays navigation until the async code is finished when
|
|
445
|
+
concurrent execution is not safe. You must return a promise from the
|
|
446
|
+
callback function passed in to this prop, and Wonder Blocks will run
|
|
447
|
+
the async code in parallel with client-side navigation or while opening
|
|
448
|
+
a new tab, but will wait until the async code finishes to start a
|
|
449
|
+
server-side navigation. If the promise rejects the navigation will
|
|
450
|
+
happen anyway. This prop should be used when it's okay to load
|
|
451
|
+
the next URL while the async callback code is running.
|
|
452
|
+
|
|
453
|
+
This table gives an overview of the options:
|
|
454
|
+
|
|
455
|
+
| Prop | Async safe? | Completes before navigation? |
|
|
456
|
+
|-------------|-------------|------------------------------|
|
|
457
|
+
| onClick | no | yes |
|
|
458
|
+
| beforeNav | yes | yes |
|
|
459
|
+
| safeWithNav | yes | no |
|
|
460
|
+
|
|
461
|
+
It is possible to use more than one of these props on the same element.
|
|
462
|
+
If multiple props are used, they will run in this order: first `onClick`,
|
|
463
|
+
then `beforeNav`, then `safeWithNav`. If both `beforeNav` and `safeWithNav`
|
|
464
|
+
are used, the `safeWithNav` callback will not be called until the
|
|
465
|
+
`beforeNav` promise resolves successfully. If the `beforeNav` promise
|
|
466
|
+
rejects, `safeWithNav` will not be run.
|
|
467
|
+
|
|
468
|
+
If the `onClick` handler calls `preventDefault()`, then `beforeNav`
|
|
469
|
+
and `safeWithNav` will still run, but navigation will not occur.
|
|
470
|
+
|
|
471
|
+
### Example: beforeNav callbacks
|
|
472
|
+
|
|
473
|
+
These buttons always wait until the async callback code completes before
|
|
474
|
+
starting navigation.
|
|
423
475
|
|
|
424
|
-
#### Example: Navigation with async action
|
|
425
|
-
|
|
426
|
-
Sometimes you may need to perform an async action either before or during
|
|
427
|
-
navigation. This can be accomplished with `beforeNav` and `safeWithNav`
|
|
428
|
-
respectively.
|
|
429
476
|
```jsx
|
|
430
477
|
import Button from "@khanacademy/wonder-blocks-button";
|
|
431
478
|
import {View} from "@khanacademy/wonder-blocks-core";
|
|
@@ -452,7 +499,7 @@ const styles = StyleSheet.create({
|
|
|
452
499
|
setTimeout(resolve, 1000);
|
|
453
500
|
})}
|
|
454
501
|
>
|
|
455
|
-
|
|
502
|
+
beforeNav, client-side nav
|
|
456
503
|
</Button>
|
|
457
504
|
<Button
|
|
458
505
|
href="/foo"
|
|
@@ -462,7 +509,7 @@ const styles = StyleSheet.create({
|
|
|
462
509
|
setTimeout(resolve, 1000);
|
|
463
510
|
})}
|
|
464
511
|
>
|
|
465
|
-
|
|
512
|
+
beforeNav, server-side nav
|
|
466
513
|
</Button>
|
|
467
514
|
<Button
|
|
468
515
|
href="https://google.com"
|
|
@@ -473,7 +520,71 @@ const styles = StyleSheet.create({
|
|
|
473
520
|
setTimeout(resolve, 1000);
|
|
474
521
|
})}
|
|
475
522
|
>
|
|
476
|
-
|
|
523
|
+
beforeNav, open URL in new tab
|
|
524
|
+
</Button>
|
|
525
|
+
<Switch>
|
|
526
|
+
<Route path="/foo">
|
|
527
|
+
<View id="foo">Hello, world!</View>
|
|
528
|
+
</Route>
|
|
529
|
+
</Switch>
|
|
530
|
+
</View>
|
|
531
|
+
</MemoryRouter>
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
### Example: safeWithNav callbacks
|
|
535
|
+
|
|
536
|
+
These buttons navigate immediately when doing client-side navigation
|
|
537
|
+
or when opening a new tab, but wait until the async callback code
|
|
538
|
+
completes before starting server-side navigation.
|
|
539
|
+
|
|
540
|
+
```jsx
|
|
541
|
+
import Button from "@khanacademy/wonder-blocks-button";
|
|
542
|
+
import {View} from "@khanacademy/wonder-blocks-core";
|
|
543
|
+
import {StyleSheet} from "aphrodite";
|
|
544
|
+
import {MemoryRouter, Route, Switch} from "react-router-dom";
|
|
545
|
+
|
|
546
|
+
const styles = StyleSheet.create({
|
|
547
|
+
row: {
|
|
548
|
+
flexDirection: "row",
|
|
549
|
+
alignItems: "center",
|
|
550
|
+
},
|
|
551
|
+
button: {
|
|
552
|
+
marginRight: 10,
|
|
553
|
+
}
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
// NOTE: In actual code you would use BrowserRouter instead
|
|
557
|
+
<MemoryRouter>
|
|
558
|
+
<View style={styles.row}>
|
|
559
|
+
<Button
|
|
560
|
+
href="/foo"
|
|
561
|
+
style={styles.button}
|
|
562
|
+
safeWithNav={() => new Promise((resolve, reject) => {
|
|
563
|
+
setTimeout(resolve, 1000);
|
|
564
|
+
})}
|
|
565
|
+
>
|
|
566
|
+
safeWithNav, client-side nav
|
|
567
|
+
</Button>
|
|
568
|
+
<Button
|
|
569
|
+
href="/foo"
|
|
570
|
+
style={styles.button}
|
|
571
|
+
skipClientNav={true}
|
|
572
|
+
safeWithNav={() => new Promise((resolve, reject) => {
|
|
573
|
+
setTimeout(resolve, 1000);
|
|
574
|
+
})}
|
|
575
|
+
>
|
|
576
|
+
safeWithNav, server-side nav
|
|
577
|
+
</Button>
|
|
578
|
+
<Button
|
|
579
|
+
href="https://google.com"
|
|
580
|
+
target="_blank"
|
|
581
|
+
style={styles.button}
|
|
582
|
+
skipClientNav={true}
|
|
583
|
+
safeWithNav={() => new Promise((resolve, reject) => {
|
|
584
|
+
setTimeout(resolve, 1000);
|
|
585
|
+
})}
|
|
586
|
+
>
|
|
587
|
+
safeWithNav, open URL in new tab
|
|
477
588
|
</Button>
|
|
478
589
|
<Switch>
|
|
479
590
|
<Route path="/foo">
|
|
@@ -484,11 +595,11 @@ const styles = StyleSheet.create({
|
|
|
484
595
|
</MemoryRouter>
|
|
485
596
|
```
|
|
486
597
|
|
|
487
|
-
|
|
598
|
+
### Example: Prevent navigation by calling e.preventDefault()
|
|
599
|
+
|
|
600
|
+
If the `onClick` callback calls `preventDefault()`, then navigation
|
|
601
|
+
will not occur.
|
|
488
602
|
|
|
489
|
-
Sometimes you may need to perform an async action either before or during
|
|
490
|
-
navigation. This can be accomplished with `beforeNav` and `safeWithNav`
|
|
491
|
-
respectively.
|
|
492
603
|
```jsx
|
|
493
604
|
import Button from "@khanacademy/wonder-blocks-button";
|
|
494
605
|
import {View} from "@khanacademy/wonder-blocks-core";
|
|
@@ -513,7 +624,7 @@ const styles = StyleSheet.create({
|
|
|
513
624
|
style={styles.button}
|
|
514
625
|
onClick={e => e.preventDefault()}
|
|
515
626
|
>
|
|
516
|
-
This button
|
|
627
|
+
This button prevents navigation.
|
|
517
628
|
</Button>
|
|
518
629
|
<Switch>
|
|
519
630
|
<Route path="/foo">
|
|
@@ -524,7 +635,7 @@ const styles = StyleSheet.create({
|
|
|
524
635
|
</MemoryRouter>
|
|
525
636
|
```
|
|
526
637
|
|
|
527
|
-
|
|
638
|
+
### Example: style
|
|
528
639
|
|
|
529
640
|
Buttons can have a `style` props which supports width, position, margin,
|
|
530
641
|
and flex styles.
|
|
@@ -582,7 +693,7 @@ const kinds = ["primary", "secondary", "tertiary"];
|
|
|
582
693
|
</View>
|
|
583
694
|
```
|
|
584
695
|
|
|
585
|
-
|
|
696
|
+
### Example: "submit" buttons in forms
|
|
586
697
|
|
|
587
698
|
```jsx
|
|
588
699
|
import Button from "@khanacademy/wonder-blocks-button";
|
|
@@ -48,8 +48,7 @@ DefaultButton.args = {
|
|
|
48
48
|
DefaultButton.parameters = {
|
|
49
49
|
design: {
|
|
50
50
|
type: "figma",
|
|
51
|
-
url:
|
|
52
|
-
"https://www.figma.com/file/VbVu3h2BpBhH80niq101MHHE/Wonder-Blocks-(Web)?node-id=401%3A307",
|
|
51
|
+
url: "https://www.figma.com/file/VbVu3h2BpBhH80niq101MHHE/Wonder-Blocks-(Web)?node-id=401%3A307",
|
|
53
52
|
},
|
|
54
53
|
chromatic: {
|
|
55
54
|
// We already have screenshots of other stories that cover more of the button states
|
|
@@ -353,7 +352,7 @@ ButtonsWithRouter.parameters = {
|
|
|
353
352
|
},
|
|
354
353
|
};
|
|
355
354
|
|
|
356
|
-
export const
|
|
355
|
+
export const BeforeNavCallbacks: StoryComponentType = () => (
|
|
357
356
|
<MemoryRouter>
|
|
358
357
|
<View style={styles.row}>
|
|
359
358
|
<Button
|
|
@@ -365,7 +364,7 @@ export const NavigationWithAsyncAction: StoryComponentType = () => (
|
|
|
365
364
|
})
|
|
366
365
|
}
|
|
367
366
|
>
|
|
368
|
-
|
|
367
|
+
beforeNav, client-side nav
|
|
369
368
|
</Button>
|
|
370
369
|
<Button
|
|
371
370
|
href="/foo"
|
|
@@ -377,7 +376,7 @@ export const NavigationWithAsyncAction: StoryComponentType = () => (
|
|
|
377
376
|
})
|
|
378
377
|
}
|
|
379
378
|
>
|
|
380
|
-
|
|
379
|
+
beforeNav, server-side nav
|
|
381
380
|
</Button>
|
|
382
381
|
<Button
|
|
383
382
|
href="https://google.com"
|
|
@@ -389,7 +388,7 @@ export const NavigationWithAsyncAction: StoryComponentType = () => (
|
|
|
389
388
|
})
|
|
390
389
|
}
|
|
391
390
|
>
|
|
392
|
-
|
|
391
|
+
beforeNav, open URL in new tab
|
|
393
392
|
</Button>
|
|
394
393
|
<Switch>
|
|
395
394
|
<Route path="/foo">
|
|
@@ -400,10 +399,71 @@ export const NavigationWithAsyncAction: StoryComponentType = () => (
|
|
|
400
399
|
</MemoryRouter>
|
|
401
400
|
);
|
|
402
401
|
|
|
403
|
-
|
|
402
|
+
BeforeNavCallbacks.storyName = "beforeNav Callbacks";
|
|
403
|
+
|
|
404
|
+
BeforeNavCallbacks.parameters = {
|
|
404
405
|
docs: {
|
|
405
406
|
storyDescription:
|
|
406
|
-
"
|
|
407
|
+
"These buttons always wait until the async callback code completes before starting navigation.",
|
|
408
|
+
},
|
|
409
|
+
chromatic: {
|
|
410
|
+
disableSnapshot: true,
|
|
411
|
+
},
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
export const SafeWithNavCallbacks: StoryComponentType = () => (
|
|
415
|
+
<MemoryRouter>
|
|
416
|
+
<View style={styles.row}>
|
|
417
|
+
<Button
|
|
418
|
+
href="/foo"
|
|
419
|
+
style={styles.button}
|
|
420
|
+
safeWithNav={() =>
|
|
421
|
+
new Promise((resolve, reject) => {
|
|
422
|
+
setTimeout(resolve, 1000);
|
|
423
|
+
})
|
|
424
|
+
}
|
|
425
|
+
>
|
|
426
|
+
safeWithNav, client-side nav
|
|
427
|
+
</Button>
|
|
428
|
+
<Button
|
|
429
|
+
href="/foo"
|
|
430
|
+
style={styles.button}
|
|
431
|
+
skipClientNav={true}
|
|
432
|
+
safeWithNav={() =>
|
|
433
|
+
new Promise((resolve, reject) => {
|
|
434
|
+
setTimeout(resolve, 1000);
|
|
435
|
+
})
|
|
436
|
+
}
|
|
437
|
+
>
|
|
438
|
+
safeWithNav, server-side nav
|
|
439
|
+
</Button>
|
|
440
|
+
<Button
|
|
441
|
+
href="https://google.com"
|
|
442
|
+
style={styles.button}
|
|
443
|
+
skipClientNav={true}
|
|
444
|
+
safeWithNav={() =>
|
|
445
|
+
new Promise((resolve, reject) => {
|
|
446
|
+
setTimeout(resolve, 1000);
|
|
447
|
+
})
|
|
448
|
+
}
|
|
449
|
+
>
|
|
450
|
+
safeWithNav, open URL in new tab
|
|
451
|
+
</Button>
|
|
452
|
+
<Switch>
|
|
453
|
+
<Route path="/foo">
|
|
454
|
+
<View id="foo">Hello, world!</View>
|
|
455
|
+
</Route>
|
|
456
|
+
</Switch>
|
|
457
|
+
</View>
|
|
458
|
+
</MemoryRouter>
|
|
459
|
+
);
|
|
460
|
+
|
|
461
|
+
SafeWithNavCallbacks.storyName = "safeWithNav Callbacks";
|
|
462
|
+
|
|
463
|
+
SafeWithNavCallbacks.parameters = {
|
|
464
|
+
docs: {
|
|
465
|
+
storyDescription:
|
|
466
|
+
"If the `onClick` callback calls `preventDefault()`, then navigation will not occur.",
|
|
407
467
|
},
|
|
408
468
|
chromatic: {
|
|
409
469
|
disableSnapshot: true,
|
|
@@ -421,7 +481,7 @@ export const PreventNavigation: StoryComponentType = () => (
|
|
|
421
481
|
e.preventDefault();
|
|
422
482
|
}}
|
|
423
483
|
>
|
|
424
|
-
This button
|
|
484
|
+
This button prevents navigation.
|
|
425
485
|
</Button>
|
|
426
486
|
<Switch>
|
|
427
487
|
<Route path="/foo">
|