@khanacademy/wonder-blocks-form 2.4.3 → 2.4.6

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.
@@ -0,0 +1,160 @@
1
+ // @flow
2
+ import * as React from "react";
3
+ import {StyleSheet} from "aphrodite";
4
+
5
+ import {View} from "@khanacademy/wonder-blocks-core";
6
+ import {Radio} from "@khanacademy/wonder-blocks-form";
7
+ import {LabelMedium, LabelSmall} from "@khanacademy/wonder-blocks-typography";
8
+ import type {StoryComponentType} from "@storybook/react";
9
+
10
+ import ComponentInfo from "../../../../../.storybook/components/component-info.js";
11
+ import {name, version} from "../../../package.json";
12
+
13
+ export default {
14
+ title: "Form / Radio",
15
+ component: Radio,
16
+ parameters: {
17
+ componentSubtitle: ((
18
+ <ComponentInfo name={name} version={version} />
19
+ ): any),
20
+ },
21
+ };
22
+
23
+ export const Default: StoryComponentType = (args) => <Radio {...args} />;
24
+
25
+ Default.args = {
26
+ checked: false,
27
+ onChange: () => {},
28
+ };
29
+
30
+ Default.parameters = {
31
+ chromatic: {
32
+ // We already have screenshots of another story that covers
33
+ // this and more cases.
34
+ disableSnapshot: true,
35
+ },
36
+ };
37
+
38
+ export const Controlled: StoryComponentType = () => {
39
+ const [checked, setChecked] = React.useState(false);
40
+ return <Radio checked={checked} onChange={setChecked} />;
41
+ };
42
+
43
+ Controlled.parameters = {
44
+ chromatic: {
45
+ // Disabling because this doesn't test visuals, it tests
46
+ // that the `checked` state works as expected.
47
+ disableSnapshot: true,
48
+ },
49
+ docs: {
50
+ storyDescription: `Use state to keep track of whether
51
+ the radio button has been checked. A radio button cannot be unchecked
52
+ by the user once it has been checked. It would become unchecked if a
53
+ different radio button is selected as part of a radio group.`,
54
+ },
55
+ };
56
+
57
+ export const Variants: StoryComponentType = () => (
58
+ <View style={styles.row}>
59
+ <Radio checked={false} style={styles.marginRight} onChange={() => {}} />
60
+ <Radio checked={true} style={styles.marginRight} onChange={() => {}} />
61
+ <Radio
62
+ error={true}
63
+ checked={false}
64
+ style={styles.marginRight}
65
+ onChange={() => {}}
66
+ />
67
+ <Radio
68
+ error={true}
69
+ checked={true}
70
+ style={styles.marginRight}
71
+ onChange={() => {}}
72
+ />
73
+ <Radio
74
+ disabled={true}
75
+ checked={false}
76
+ style={styles.marginRight}
77
+ onChange={() => {}}
78
+ />
79
+ <Radio disabled={true} checked={true} onChange={() => {}} />
80
+ </View>
81
+ );
82
+
83
+ Variants.parameters = {
84
+ docs: {
85
+ storyDescription: `The radio button has various styles for
86
+ clickable states. Here are sets of default radio buttons,
87
+ radio buttons in an error state, and disabled radio buttons.`,
88
+ },
89
+ };
90
+
91
+ export const WithLabel: StoryComponentType = () => {
92
+ const [checked, setChecked] = React.useState(false);
93
+
94
+ return (
95
+ <Radio
96
+ label="Easy"
97
+ description="Opt for a less difficult exercise set."
98
+ checked={checked}
99
+ onChange={setChecked}
100
+ />
101
+ );
102
+ };
103
+
104
+ WithLabel.parameters = {
105
+ docs: {
106
+ storyDescription: `The radio button can have an optional label
107
+ and description. This allows it to be used as a settings-like item,
108
+ as opposed to its usage in a radio grid.`,
109
+ },
110
+ };
111
+
112
+ export const AdditionalClickTarget: StoryComponentType = () => {
113
+ const [checked, setChecked] = React.useState(false);
114
+ const headingText = "Functions";
115
+ const descriptionText = `A great cook knows how to take basic
116
+ ingredients and prepare a delicious meal. In this topic, you will
117
+ become function-chefs! You will learn how to combine functions
118
+ with arithmetic operations and how to compose functions.`;
119
+
120
+ return (
121
+ <View style={styles.wrapper}>
122
+ <View style={styles.topic}>
123
+ <label htmlFor="topic-123">
124
+ <LabelMedium>{headingText}</LabelMedium>
125
+ </label>
126
+ <LabelSmall>{descriptionText}</LabelSmall>
127
+ </View>
128
+ <Radio checked={checked} id="topic-123" onChange={setChecked} />
129
+ </View>
130
+ );
131
+ };
132
+
133
+ AdditionalClickTarget.parameters = {
134
+ docs: {
135
+ storyDescription: `Sometimes one may wish to use a radio button
136
+ in a different context (label may not be right next to the
137
+ radio button), like in this example content item. Use a
138
+ \`<label htmlFor={id}>\` element where the id matches the \`id\`
139
+ prop of the Radio. This is for accessibility purposes,
140
+ and doing this also automatically makes the label a click target
141
+ for the radio button.`,
142
+ },
143
+ };
144
+
145
+ const styles = StyleSheet.create({
146
+ row: {
147
+ flexDirection: "row",
148
+ },
149
+ marginRight: {
150
+ marginRight: 16,
151
+ },
152
+ wrapper: {
153
+ flexDirection: "row",
154
+ alignItems: "center",
155
+ justifyContent: "space-evenly",
156
+ },
157
+ topic: {
158
+ maxWidth: 600,
159
+ },
160
+ });
@@ -0,0 +1,206 @@
1
+ // @flow
2
+
3
+ export default {
4
+ id: {
5
+ description: "The unique identifier for the input.",
6
+ type: {required: true},
7
+ table: {
8
+ type: {
9
+ summary: "string",
10
+ },
11
+ },
12
+ control: {
13
+ type: "text",
14
+ },
15
+ },
16
+ type: {
17
+ description:
18
+ "Determines the type of input. Defaults to text. This may change the appearance or type of characters allowed.",
19
+ table: {
20
+ type: {
21
+ summary: `"text" | "password" | "email" | "number" | "tel"`,
22
+ },
23
+ defaultValue: {
24
+ summary: "text",
25
+ },
26
+ },
27
+ options: ["text", "password", "email", "number", "tel"],
28
+ control: {
29
+ type: "select",
30
+ },
31
+ },
32
+ value: {
33
+ description: "The input value.",
34
+ type: {required: true},
35
+ table: {
36
+ type: {
37
+ summary: "string",
38
+ },
39
+ },
40
+ control: {type: "text"},
41
+ },
42
+ autoComplete: {
43
+ description: "Specifies if the input field allows autocomplete.",
44
+ table: {
45
+ type: {
46
+ summary: "string",
47
+ detail: `There is a large number of options, including "on", "off", "username", "current-password", and many others.`,
48
+ },
49
+ },
50
+ control: {
51
+ type: "text",
52
+ },
53
+ },
54
+ disabled: {
55
+ description: "Makes a read-only input field that cannot be focused.",
56
+ table: {
57
+ type: {
58
+ summary: "boolean",
59
+ },
60
+ defaultValue: {
61
+ summary: "false",
62
+ },
63
+ },
64
+ control: {
65
+ type: "boolean",
66
+ },
67
+ },
68
+ light: {
69
+ description:
70
+ "Change the default focus ring color to fit a dark background.",
71
+ table: {
72
+ type: {
73
+ summary: "boolean",
74
+ },
75
+ defaultValue: {
76
+ summary: "false",
77
+ },
78
+ },
79
+ control: {
80
+ type: "boolean",
81
+ },
82
+ },
83
+ required: {
84
+ description:
85
+ "Whether this field is required to to continue, or the error message to render if this field is left blank. Pass in a message instead of `true` if possible.",
86
+ table: {
87
+ type: {
88
+ summary: "boolean | string",
89
+ detail: "The string will not be used if a `validate` prop is passed in.",
90
+ },
91
+ },
92
+ control: {
93
+ type: "null",
94
+ },
95
+ },
96
+ placeholder: {
97
+ description: "Provide hints or examples of what to enter.",
98
+ table: {
99
+ type: {
100
+ summary: "string",
101
+ },
102
+ },
103
+ control: {
104
+ type: "text",
105
+ },
106
+ },
107
+ readOnly: {
108
+ description: "Specifies if the input field is read-only.",
109
+ table: {
110
+ type: {
111
+ summary: "boolean",
112
+ },
113
+ },
114
+ control: {
115
+ type: "boolean",
116
+ },
117
+ },
118
+ style: {
119
+ description: "Custom styles for the input.",
120
+ table: {
121
+ type: {
122
+ summary: "StyleType",
123
+ },
124
+ },
125
+ },
126
+ testId: {
127
+ description: "Optional test ID for e2e testing.",
128
+ table: {
129
+ type: {
130
+ summary: "string",
131
+ },
132
+ },
133
+ control: {
134
+ type: "text",
135
+ },
136
+ },
137
+ validate: {
138
+ description:
139
+ "Provide a validation for the input value. Return a string error message or null | void for a valid input.",
140
+ table: {
141
+ type: {
142
+ summary: "(value: string) => ?string",
143
+ },
144
+ },
145
+ control: {
146
+ type: "null",
147
+ },
148
+ },
149
+
150
+ /**
151
+ * Events
152
+ */
153
+ onValidate: {
154
+ description: "Called right after the TextField input is validated.",
155
+ table: {
156
+ category: "Events",
157
+ type: {
158
+ summary: "(errorMessage: ?string) => mixed",
159
+ },
160
+ },
161
+ },
162
+ onChange: {
163
+ description:
164
+ "Called when the value has changed. Use this in conjunction with the `value` prop to update the string rendered in the input field.",
165
+ type: {required: true},
166
+ table: {
167
+ category: "Events",
168
+ type: {
169
+ summary: "(newValue: string) => mixed",
170
+ },
171
+ },
172
+ },
173
+ onKeyDown: {
174
+ action: "keyDown",
175
+ description: "Called when a key is pressed.",
176
+ table: {
177
+ category: "Events",
178
+ type: {
179
+ summary:
180
+ "(event: SyntheticKeyboardEvent<HTMLInputElement>) => mixed",
181
+ },
182
+ },
183
+ },
184
+ onFocus: {
185
+ action: "focus",
186
+ description: "Called when the element has been focused.",
187
+ table: {
188
+ category: "Events",
189
+ type: {
190
+ summary:
191
+ "(event: SyntheticFocusEvent<HTMLInputElement>) => mixed",
192
+ },
193
+ },
194
+ },
195
+ onBlur: {
196
+ action: "blur",
197
+ description: "Called when the element has been blurred.",
198
+ table: {
199
+ category: "Events",
200
+ type: {
201
+ summary:
202
+ "(event: SyntheticFocusEvent<HTMLInputElement>) => mixed",
203
+ },
204
+ },
205
+ },
206
+ };