@khanacademy/wonder-blocks-button 2.11.7 → 3.0.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.
@@ -1,921 +1,5 @@
1
- ### Example: kind
1
+ Documentation for `@khanacademy/wonder-blocks-button` is now in Storybook.
2
2
 
3
- There are three `kind`s of buttons: `"primary"` (default), `"secondary"`, and
4
- `"tertiary"`:
5
- ```jsx
6
- import Button from "@khanacademy/wonder-blocks-button";
7
- import {View} from "@khanacademy/wonder-blocks-core";
8
- import {StyleSheet} from "aphrodite";
9
-
10
- const styles = StyleSheet.create({
11
- row: {
12
- flexDirection: "row",
13
- },
14
- button: {
15
- marginRight: 10,
16
- }
17
- });
18
-
19
- <View style={styles.row}>
20
- <Button
21
- style={styles.button}
22
- onClick={(e) => window.alert("Hello, world!")}
23
- >
24
- Primary
25
- </Button>
26
- <Button
27
- style={styles.button}
28
- onClick={(e) => window.alert("Hello, world!")}
29
- kind="secondary"
30
- >
31
- Secondary
32
- </Button>
33
- <Button
34
- style={styles.button}
35
- onClick={(e) => window.alert("Hello, world!")}
36
- kind="tertiary"
37
- >
38
- Tertiary
39
- </Button>
40
- </View>
41
- ```
42
-
43
- ### Example: color
44
-
45
- Buttons have a `color` that is either `"default"` (the default, as shown above) or `"destructive"` (as can seen below):
46
-
47
- ```jsx
48
- import Button from "@khanacademy/wonder-blocks-button";
49
- import {View} from "@khanacademy/wonder-blocks-core";
50
- import {StyleSheet} from "aphrodite";
51
-
52
- const styles = StyleSheet.create({
53
- row: {
54
- flexDirection: "row",
55
- },
56
- button: {
57
- marginRight: 10,
58
- }
59
- });
60
-
61
- <View style={styles.row}>
62
- <Button
63
- style={styles.button}
64
- onClick={(e) => window.alert("Hello, world!")}
65
- color="destructive"
66
- >
67
- Primary
68
- </Button>
69
- <Button
70
- style={styles.button}
71
- onClick={(e) => window.alert("Hello, world!")}
72
- kind="secondary"
73
- color="destructive"
74
- >
75
- Secondary
76
- </Button>
77
- <Button
78
- style={styles.button}
79
- onClick={(e) => window.alert("Hello, world!")}
80
- kind="tertiary"
81
- color="destructive"
82
- >
83
- Tertiary
84
- </Button>
85
- </View>
86
- ```
87
-
88
- ### Example: disabled
89
-
90
- Buttons can be `disabled`:
91
-
92
- ⚠️ Buttons do not need an `aria-disabled` attribute, if it also has a `disabled` attribute.
93
- Users operating the web page through a screen reader may not be able to fully evaluate the implied
94
- behaviors of the button element itself.
95
-
96
- Links:
97
- - [Implicit ARIA semantics](https://www.w3.org/TR/wai-aria-1.1/#implicit_semantics)
98
- - [Document conformance requirements](https://www.w3.org/TR/html-aria/#document-conformance-requirements-for-use-of-aria-attributes-in-html)
99
-
100
-
101
- ```jsx
102
- import Button from "@khanacademy/wonder-blocks-button";
103
- import {View} from "@khanacademy/wonder-blocks-core";
104
- import {StyleSheet} from "aphrodite";
105
-
106
- const styles = StyleSheet.create({
107
- row: {
108
- flexDirection: "row",
109
- },
110
- button: {
111
- marginRight: 10,
112
- }
113
- });
114
-
115
- <View style={styles.row}>
116
- <Button
117
- style={styles.button}
118
- onClick={(e) => window.alert("Hello, world!")}
119
- disabled={true}
120
- >
121
- Primary
122
- </Button>
123
- <Button
124
- style={styles.button}
125
- href={"/foo"}
126
- kind="secondary"
127
- disabled={true}
128
- >
129
- Secondary
130
- </Button>
131
- <Button
132
- style={styles.button}
133
- onClick={(e) => window.alert("Hello, world!")}
134
- kind="tertiary"
135
- disabled={true}
136
- >
137
- Tertiary
138
- </Button>
139
- </View>
140
- ```
141
-
142
- ### Example: dark
143
-
144
- Buttons on a `darkBlue` background should set `light` to `true`.
145
- ```jsx
146
- import Button from "@khanacademy/wonder-blocks-button";
147
- import Color from "@khanacademy/wonder-blocks-color";
148
- import {View} from "@khanacademy/wonder-blocks-core";
149
- import {StyleSheet} from "aphrodite";
150
-
151
- const styles = StyleSheet.create({
152
- row: {
153
- flexDirection: "row",
154
- backgroundColor: Color.darkBlue,
155
- padding: 10,
156
- },
157
- button: {
158
- marginRight: 10,
159
- }
160
- });
161
-
162
- <View style={styles.row}>
163
- <Button
164
- light={true}
165
- style={styles.button}
166
- onClick={(e) => window.alert("Hello, world!")}
167
- >
168
- Primary
169
- </Button>
170
- <Button
171
- light={true}
172
- style={styles.button}
173
- onClick={(e) => window.alert("Hello, world!")}
174
- kind="secondary"
175
- >
176
- Secondary
177
- </Button>
178
- <Button
179
- light={true}
180
- style={styles.button}
181
- onClick={(e) => window.alert("Hello, world!")}
182
- kind="tertiary"
183
- >
184
- Tertiary
185
- </Button>
186
- <Button
187
- light={true}
188
- style={styles.button}
189
- onClick={(e) => window.alert("Hello, world!")}
190
- disabled={true}
191
- >
192
- Primary
193
- </Button>
194
- <Button
195
- light={true}
196
- style={styles.button}
197
- onClick={(e) => window.alert("Hello, world!")}
198
- kind="secondary"
199
- disabled={true}
200
- >
201
- Secondary
202
- </Button>
203
- <Button
204
- light={true}
205
- style={styles.button}
206
- onClick={(e) => window.alert("Hello, world!")}
207
- kind="tertiary"
208
- disabled={true}
209
- >
210
- Tertiary
211
- </Button>
212
- </View>
213
- ```
214
-
215
- ### Example: size
216
-
217
- Buttons have a `size` that's either `"medium"` (default), `"small"`, or `"xlarge"`.
218
- ```js
219
- import Button from "@khanacademy/wonder-blocks-button";
220
- import {View} from "@khanacademy/wonder-blocks-core";
221
- import {StyleSheet} from "aphrodite";
222
-
223
- const styles = StyleSheet.create({
224
- row: {
225
- flexDirection: "row",
226
- marginBottom: 8,
227
- },
228
- button: {
229
- marginRight: 10,
230
- }
231
- });
232
-
233
- <View>
234
- <View style={styles.row}>
235
- <Button
236
- style={styles.button}
237
- onClick={(e) => window.alert("Hello, world!")}
238
- size="small"
239
- >
240
- Label
241
- </Button>
242
- <Button
243
- style={styles.button}
244
- onClick={(e) => window.alert("Hello, world!")}
245
- kind="secondary"
246
- size="small"
247
- >
248
- Label
249
- </Button>
250
- <Button
251
- style={styles.button}
252
- onClick={(e) => window.alert("Hello, world!")}
253
- kind="tertiary"
254
- size="small"
255
- >
256
- Label
257
- </Button>
258
- </View>
259
- <View style={styles.row}>
260
- <Button
261
- style={styles.button}
262
- onClick={(e) => window.alert("Hello, world!")}
263
- size="medium"
264
- >
265
- Label
266
- </Button>
267
- <Button
268
- style={styles.button}
269
- onClick={(e) => window.alert("Hello, world!")}
270
- kind="secondary"
271
- size="medium"
272
- >
273
- Label
274
- </Button>
275
- <Button
276
- style={styles.button}
277
- onClick={(e) => window.alert("Hello, world!")}
278
- kind="tertiary"
279
- size="medium"
280
- >
281
- Label
282
- </Button>
283
- </View>
284
- <View style={styles.row}>
285
- <Button
286
- style={styles.button}
287
- onClick={(e) => window.alert("Hello, world!")}
288
- size="xlarge"
289
- >
290
- Label
291
- </Button>
292
- <Button
293
- style={styles.button}
294
- onClick={(e) => window.alert("Hello, world!")}
295
- kind="secondary"
296
- size="xlarge"
297
- >
298
- Label
299
- </Button>
300
- <Button
301
- style={styles.button}
302
- onClick={(e) => window.alert("Hello, world!")}
303
- kind="tertiary"
304
- size="xlarge"
305
- >
306
- Label
307
- </Button>
308
- </View>
309
- </View>
310
- ```
311
-
312
- ### Example: spinner
313
-
314
- Buttons can show a `spinner`. This is useful when indicating to a user that
315
- their input has been recognized but that the operation will take some time.
316
- While the `spinner` property is set to `true` the button is disabled.
317
-
318
- ```jsx
319
- import Button from "@khanacademy/wonder-blocks-button";
320
- import {View} from "@khanacademy/wonder-blocks-core";
321
- import {StyleSheet} from "aphrodite";
322
-
323
- const styles = StyleSheet.create({
324
- row: {
325
- flexDirection: "row",
326
- alignItems: "center",
327
- },
328
- button: {
329
- marginRight: 10,
330
- }
331
- });
332
-
333
- <View style={styles.row}>
334
- <Button spinner={true} aria-label="loading" size="xlarge" style={styles.button}>
335
- Click me!
336
- </Button>
337
- <Button spinner={true} aria-label="loading" style={styles.button} href="/foo">
338
- Click me!
339
- </Button>
340
- <Button spinner={true} aria-label="loading" size="small" style={styles.button}>
341
- Click me!
342
- </Button>
343
- </View>
344
- ```
345
-
346
- ### Example: Navigation
347
-
348
- ```jsx
349
- import Button from "@khanacademy/wonder-blocks-button";
350
- import {View} from "@khanacademy/wonder-blocks-core";
351
- import {StyleSheet} from "aphrodite";
352
-
353
- const styles = StyleSheet.create({
354
- row: {
355
- flexDirection: "row",
356
- },
357
- button: {
358
- marginRight: 10,
359
- }
360
- });
361
-
362
- <View style={styles.row}>
363
- <Button
364
- href="#button-1"
365
- style={styles.button}
366
- >
367
- href
368
- </Button>
369
- <Button
370
- kind="secondary"
371
- onClick={(e) => window.alert("Hello, world!")}
372
- style={styles.button}
373
- >
374
- onClick
375
- </Button>
376
- <Button
377
- kind="tertiary"
378
- href="#button-1"
379
- onClick={(e) => window.alert("Hello, world!")}
380
- style={styles.button}
381
- >
382
- both
383
- </Button>
384
- </View>
385
- ```
386
-
387
- ### Example: Navigation with React Router
388
-
389
- Buttons do client-side navigation by default, if React Router exists:
390
- ```jsx
391
- import Button from "@khanacademy/wonder-blocks-button";
392
- import {View} from "@khanacademy/wonder-blocks-core";
393
- import {StyleSheet} from "aphrodite";
394
- import {MemoryRouter, Route, Switch} from "react-router-dom";
395
-
396
- const styles = StyleSheet.create({
397
- row: {
398
- flexDirection: "row",
399
- alignItems: "center",
400
- },
401
- button: {
402
- marginRight: 10,
403
- }
404
- });
405
-
406
- // NOTE: In actual code you would use BrowserRouter instead
407
- <MemoryRouter>
408
- <View style={styles.row}>
409
- <Button href="/foo" style={styles.button}>
410
- Uses Client-side Nav
411
- </Button>
412
- <Button href="/foo" style={styles.button} skipClientNav>
413
- Avoids Client-side Nav
414
- </Button>
415
- <Switch>
416
- <Route path="/foo">
417
- <View id="foo">Hello, world!</View>
418
- </Route>
419
- </Switch>
420
- </View>
421
- </MemoryRouter>
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.
475
-
476
- ```jsx
477
- import Button from "@khanacademy/wonder-blocks-button";
478
- import {View} from "@khanacademy/wonder-blocks-core";
479
- import {StyleSheet} from "aphrodite";
480
- import {MemoryRouter, Route, Switch} from "react-router-dom";
481
-
482
- const styles = StyleSheet.create({
483
- row: {
484
- flexDirection: "row",
485
- alignItems: "center",
486
- },
487
- button: {
488
- marginRight: 10,
489
- }
490
- });
491
-
492
- // NOTE: In actual code you would use BrowserRouter instead
493
- <MemoryRouter>
494
- <View style={styles.row}>
495
- <Button
496
- href="/foo"
497
- style={styles.button}
498
- beforeNav={() => new Promise((resolve, reject) => {
499
- setTimeout(resolve, 1000);
500
- })}
501
- >
502
- beforeNav, client-side nav
503
- </Button>
504
- <Button
505
- href="/foo"
506
- style={styles.button}
507
- skipClientNav={true}
508
- beforeNav={() => new Promise((resolve, reject) => {
509
- setTimeout(resolve, 1000);
510
- })}
511
- >
512
- beforeNav, server-side nav
513
- </Button>
514
- <Button
515
- href="https://google.com"
516
- target="_blank"
517
- style={styles.button}
518
- skipClientNav={true}
519
- beforeNav={() => new Promise((resolve, reject) => {
520
- setTimeout(resolve, 1000);
521
- })}
522
- >
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
588
- </Button>
589
- <Switch>
590
- <Route path="/foo">
591
- <View id="foo">Hello, world!</View>
592
- </Route>
593
- </Switch>
594
- </View>
595
- </MemoryRouter>
596
- ```
597
-
598
- ### Example: Prevent navigation by calling e.preventDefault()
599
-
600
- If the `onClick` callback calls `preventDefault()`, then navigation
601
- will not occur.
602
-
603
- ```jsx
604
- import Button from "@khanacademy/wonder-blocks-button";
605
- import {View} from "@khanacademy/wonder-blocks-core";
606
- import {StyleSheet} from "aphrodite";
607
- import {MemoryRouter, Route, Switch} from "react-router-dom";
608
-
609
- const styles = StyleSheet.create({
610
- row: {
611
- flexDirection: "row",
612
- alignItems: "center",
613
- },
614
- button: {
615
- marginRight: 10,
616
- }
617
- });
618
-
619
- // NOTE: In actual code you would use BrowserRouter instead
620
- <MemoryRouter>
621
- <View style={styles.row}>
622
- <Button
623
- href="/foo"
624
- style={styles.button}
625
- onClick={e => e.preventDefault()}
626
- >
627
- This button prevents navigation.
628
- </Button>
629
- <Switch>
630
- <Route path="/foo">
631
- <View id="foo">Hello, world!</View>
632
- </Route>
633
- </Switch>
634
- </View>
635
- </MemoryRouter>
636
- ```
637
-
638
- ### Example: style
639
-
640
- Buttons can have a `style` props which supports width, position, margin,
641
- and flex styles.
642
-
643
- Buttons can have an icon on it's left side.
644
-
645
- ```jsx
646
- import Button from "@khanacademy/wonder-blocks-button";
647
- import {View} from "@khanacademy/wonder-blocks-core";
648
- import {StyleSheet} from "aphrodite";
649
- import {icons} from "@khanacademy/wonder-blocks-icon";
650
-
651
- const styles = StyleSheet.create({
652
- row: {
653
- flexDirection: "row",
654
- marginBottom: 10,
655
- },
656
- button: {
657
- marginRight: 10,
658
- },
659
- });
660
-
661
- const kinds = ["primary", "secondary", "tertiary"];
662
-
663
- <View>
664
- <View style={styles.row}>
665
- {
666
- kinds.map((kind, idx) => (
667
- <Button
668
- kind={kind}
669
- icon={icons.contentExercise}
670
- style={styles.button}
671
- key={idx}
672
- >
673
- {kind}
674
- </Button>
675
- ))
676
- }
677
- </View>
678
- <View style={styles.row}>
679
- {
680
- kinds.map((kind, idx) => (
681
- <Button
682
- kind={kind}
683
- icon={icons.contentExercise}
684
- style={styles.button}
685
- key={idx}
686
- size="small"
687
- >
688
- {kind} small
689
- </Button>
690
- ))
691
- }
692
- </View>
693
- </View>
694
- ```
695
-
696
- ### Example: "submit" buttons in forms
697
-
698
- ```jsx
699
- import Button from "@khanacademy/wonder-blocks-button";
700
- import {View} from "@khanacademy/wonder-blocks-core";
701
-
702
- <View>
703
- <form onSubmit={() => alert("the form was submitted")}>
704
- <Button type="submit">Submit</Button>
705
- </form>
706
- </View>
707
- ```
708
-
709
- ### Best Practices
710
-
711
- In vertical layouts, buttons will stretch horizontally to fill the available
712
- space. This is probably not what you want unless you're on a very narrow
713
- screen.
714
-
715
- ```jsx
716
- import Button from "@khanacademy/wonder-blocks-button";
717
- import {View} from "@khanacademy/wonder-blocks-core";
718
-
719
- <View>
720
- <Button>
721
- Label
722
- </Button>
723
- </View>
724
- ```
725
-
726
- This can be corrected by applying appropriate flex styles to the container.
727
-
728
- ```jsx
729
- import Button from "@khanacademy/wonder-blocks-button";
730
- import {View} from "@khanacademy/wonder-blocks-core";
731
- import {StyleSheet} from "aphrodite";
732
-
733
- const styles = StyleSheet.create({
734
- column: {
735
- alignItems: "flex-start",
736
- },
737
- row: {
738
- flexDirection: "row",
739
- },
740
- gap: {
741
- height: 16,
742
- },
743
- button: {
744
- marginRight: 10,
745
- },
746
- });
747
-
748
- <View>
749
- <View style={styles.row}>
750
- <Button>
751
- Button in a row
752
- </Button>
753
- </View>
754
- <View style={styles.gap} />
755
- <View style={styles.column}>
756
- <Button>
757
- Button in a column
758
- </Button>
759
- </View>
760
- </View>
761
- ```
762
-
763
- Layouts often specify a specific width of button. When implementing such
764
- designs use `minWidth` instead of `width`. `minWidth` allows the button
765
- to resize to fit the content whereas `width` does not. This is important
766
- for international sites since sometimes strings for UI elements can be much
767
- longer in other languages. Both of the buttons below have a "natural" width
768
- of 144px. The one on the right is wider but it accommodates the full string
769
- instead of wrapping it.
770
- ```jsx
771
- import Button from "@khanacademy/wonder-blocks-button";
772
- import {View} from "@khanacademy/wonder-blocks-core";
773
- import {StyleSheet} from "aphrodite";
774
-
775
- const styles = StyleSheet.create({
776
- row: {
777
- flexDirection: "row",
778
- },
779
- gap: {
780
- height: 16,
781
- },
782
- button: {
783
- marginRight: 10,
784
- minWidth: 144,
785
- },
786
- });
787
-
788
- <View style={styles.row}>
789
- <Button
790
- style={styles.button}
791
- kind="secondary"
792
- >
793
- label
794
- </Button>
795
- <Button
796
- style={styles.button}
797
- >
798
- label in a different language
799
- </Button>
800
- </View>
801
- ```
802
-
803
- If the parent container of the button doesn't have enough room to accommodate
804
- the width of the button, the text will truncate. This should ideally never
805
- happen, but it's sometimes a necessary fallback.
806
- ```jsx
807
- import Button from "@khanacademy/wonder-blocks-button";
808
- import {View} from "@khanacademy/wonder-blocks-core";
809
- import {StyleSheet} from "aphrodite";
810
-
811
- const styles = StyleSheet.create({
812
- row: {
813
- flexDirection: "row",
814
- width: 300,
815
- },
816
- gap: {
817
- height: 16,
818
- },
819
- button: {
820
- marginRight: 10,
821
- minWidth: 144,
822
- },
823
- });
824
-
825
- <View style={styles.row}>
826
- <Button
827
- style={styles.button}
828
- kind="secondary"
829
- >
830
- label
831
- </Button>
832
- <Button
833
- style={styles.button}
834
- >
835
- label too long for the parent container
836
- </Button>
837
- </View>
838
- ```
839
-
840
- Only one button in a layout should be `primary`.
841
- ```jsx
842
- import Button from "@khanacademy/wonder-blocks-button";
843
- import {View} from "@khanacademy/wonder-blocks-core";
844
- import {StyleSheet} from "aphrodite";
845
-
846
- const styles = StyleSheet.create({
847
- row: {
848
- flexDirection: "row",
849
- },
850
- button: {
851
- marginRight: 10,
852
- },
853
- });
854
-
855
- <View>
856
- <View style={styles.row}>
857
- <Button
858
- style={styles.button}
859
- kind="tertiary"
860
- >
861
- Tertiary
862
- </Button>
863
- <Button
864
- style={styles.badButton}
865
- >
866
- Primary
867
- </Button>
868
- </View>
869
- </View>
870
- ```
871
-
872
- When an action is going to take a while, show a spinner during that time.
873
-
874
- ```jsx
875
- import Button from "@khanacademy/wonder-blocks-button";
876
- import {View} from "@khanacademy/wonder-blocks-core";
877
- import {StyleSheet} from "aphrodite";
878
-
879
- const styles = StyleSheet.create({
880
- row: {
881
- flexDirection: "row",
882
- },
883
- button: {
884
- marginRight: 10,
885
- },
886
- });
887
-
888
- class Example extends React.Component {
889
- constructor(props) {
890
- super(props);
891
- this.state = {
892
- waiting: false,
893
- }
894
- }
895
-
896
- componentWillUnmount() {
897
- this.timeout && this.timeout.clear();
898
- }
899
-
900
- handleClick() {
901
- this.setState({waiting: true});
902
- this.timeout = setTimeout(() => {
903
- this.setState({waiting: false});
904
- }, 2000);
905
- }
906
-
907
- render() {
908
- return <View style={styles.row}>
909
- <Button
910
- spinner={this.state.waiting}
911
- aria-label={this.state.waiting ? "waiting" : ""}
912
- onClick={() => this.handleClick()}
913
- >
914
- Click me!
915
- </Button>
916
- </View>
917
- }
918
- }
919
-
920
- <Example />
921
- ```
3
+ Either run `yarn start:storybook` locally, or visit the docs for the `main`
4
+ branch on [GitHub
5
+ Pages](https://khan.github.io/wonder-blocks/?path=/docs/button--default).