@khanacademy/wonder-blocks-form 4.9.2 → 4.9.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.
Files changed (39) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/components/checkbox-core.d.ts +2 -2
  3. package/dist/components/checkbox.d.ts +2 -2
  4. package/dist/components/choice-internal.d.ts +2 -2
  5. package/dist/components/choice.d.ts +2 -2
  6. package/dist/components/labeled-text-field.d.ts +9 -1
  7. package/dist/components/radio-core.d.ts +2 -2
  8. package/dist/components/radio.d.ts +2 -2
  9. package/dist/components/text-area.d.ts +2 -2
  10. package/dist/components/text-field.d.ts +10 -5
  11. package/dist/es/index.js +93 -48
  12. package/dist/index.js +93 -48
  13. package/package.json +7 -7
  14. package/src/__tests__/__snapshots__/custom-snapshot.test.tsx.snap +0 -247
  15. package/src/__tests__/custom-snapshot.test.tsx +0 -48
  16. package/src/components/__tests__/checkbox-group.test.tsx +0 -162
  17. package/src/components/__tests__/checkbox.test.tsx +0 -138
  18. package/src/components/__tests__/field-heading.test.tsx +0 -225
  19. package/src/components/__tests__/labeled-text-field.test.tsx +0 -750
  20. package/src/components/__tests__/radio-group.test.tsx +0 -182
  21. package/src/components/__tests__/text-area.test.tsx +0 -1286
  22. package/src/components/__tests__/text-field.test.tsx +0 -562
  23. package/src/components/checkbox-core.tsx +0 -239
  24. package/src/components/checkbox-group.tsx +0 -174
  25. package/src/components/checkbox.tsx +0 -99
  26. package/src/components/choice-internal.tsx +0 -184
  27. package/src/components/choice.tsx +0 -157
  28. package/src/components/field-heading.tsx +0 -169
  29. package/src/components/group-styles.ts +0 -33
  30. package/src/components/labeled-text-field.tsx +0 -317
  31. package/src/components/radio-core.tsx +0 -171
  32. package/src/components/radio-group.tsx +0 -159
  33. package/src/components/radio.tsx +0 -82
  34. package/src/components/text-area.tsx +0 -430
  35. package/src/components/text-field.tsx +0 -399
  36. package/src/index.ts +0 -17
  37. package/src/util/types.ts +0 -85
  38. package/tsconfig-build.json +0 -19
  39. package/tsconfig-build.tsbuildinfo +0 -1
@@ -1,239 +0,0 @@
1
- import * as React from "react";
2
- import {StyleSheet} from "aphrodite";
3
-
4
- import {mix, color, spacing} from "@khanacademy/wonder-blocks-tokens";
5
- import {addStyle} from "@khanacademy/wonder-blocks-core";
6
- import {PhosphorIcon} from "@khanacademy/wonder-blocks-icon";
7
- import checkIcon from "@phosphor-icons/core/bold/check-bold.svg";
8
- import minusIcon from "@phosphor-icons/core/bold/minus-bold.svg";
9
-
10
- import type {ChoiceCoreProps, Checked} from "../util/types";
11
-
12
- // `AriaChecked` and `mapCheckedToAriaChecked()` are used to convert the
13
- // `checked` prop value to a value that a screen reader can understand via the
14
- // `aria-checked` attribute
15
- type AriaChecked = "true" | "false" | "mixed";
16
-
17
- function mapCheckedToAriaChecked(value: Checked): AriaChecked {
18
- switch (value) {
19
- case true:
20
- return "true";
21
- case false:
22
- return "false";
23
- default:
24
- return "mixed";
25
- }
26
- }
27
-
28
- const {blue, red, white, offWhite, offBlack16, offBlack32, offBlack50} = color;
29
-
30
- // The checkbox size
31
- const size = spacing.medium_16;
32
- // The check icon size
33
- const checkSize = spacing.small_12;
34
-
35
- const StyledInput = addStyle("input");
36
-
37
- /**
38
- * The internal stateless ☑️ Checkbox
39
- */
40
- const CheckboxCore = React.forwardRef(function CheckboxCore(
41
- props: ChoiceCoreProps,
42
- ref: React.ForwardedRef<HTMLInputElement>,
43
- ) {
44
- const {checked, disabled, error, groupName, id, testId, ...sharedProps} =
45
- props;
46
-
47
- const innerRef = React.useRef<HTMLInputElement>(null);
48
-
49
- React.useEffect(() => {
50
- // Keep the indeterminate state in sync with the checked prop
51
- if (innerRef.current != null) {
52
- innerRef.current.indeterminate = checked == null;
53
- }
54
- }, [checked, innerRef]);
55
-
56
- const handleChange: () => void = () => {
57
- // Empty because change is handled by ClickableBehavior
58
- return;
59
- };
60
-
61
- const stateStyles = _generateStyles(checked, error);
62
-
63
- const defaultStyle = [
64
- sharedStyles.inputReset,
65
- sharedStyles.default,
66
- !disabled && stateStyles.default,
67
- disabled && sharedStyles.disabled,
68
- ];
69
-
70
- const checkboxIcon = (
71
- <PhosphorIcon
72
- color={disabled ? offBlack32 : white}
73
- icon={checked ? checkIcon : minusIcon}
74
- size="small"
75
- style={[
76
- sharedStyles.checkboxIcon,
77
- // The check icon is smaller than the checkbox, as per design.
78
- {
79
- width: checkSize,
80
- height: checkSize,
81
- },
82
- ]}
83
- />
84
- );
85
-
86
- const ariaChecked = mapCheckedToAriaChecked(checked);
87
-
88
- return (
89
- <React.Fragment>
90
- <StyledInput
91
- {...sharedProps}
92
- ref={(node) => {
93
- // @ts-expect-error: current is not actually read-only
94
- innerRef.current = node;
95
- if (typeof ref === "function") {
96
- ref(node);
97
- } else if (ref != null) {
98
- ref.current = node;
99
- }
100
- }}
101
- type="checkbox"
102
- aria-checked={ariaChecked}
103
- aria-invalid={error}
104
- checked={checked ?? undefined}
105
- disabled={disabled}
106
- id={id}
107
- name={groupName}
108
- // Need to specify because this is a controlled React form
109
- // component, but we handle the click via ClickableBehavior
110
- onChange={handleChange}
111
- style={defaultStyle}
112
- data-testid={testId}
113
- />
114
- {checked || checked == null ? checkboxIcon : <></>}
115
- </React.Fragment>
116
- );
117
- });
118
-
119
- const sharedStyles = StyleSheet.create({
120
- // Reset the default styled input element
121
- inputReset: {
122
- appearance: "none",
123
- WebkitAppearance: "none",
124
- MozAppearance: "none",
125
- },
126
-
127
- default: {
128
- height: size,
129
- width: size,
130
- minHeight: size,
131
- minWidth: size,
132
- margin: 0,
133
- outline: "none",
134
- boxSizing: "border-box",
135
- borderStyle: "solid",
136
- borderWidth: 1,
137
- borderRadius: 3,
138
- },
139
-
140
- disabled: {
141
- cursor: "auto",
142
- backgroundColor: offWhite,
143
- borderColor: offBlack16,
144
- borderWidth: 1,
145
- },
146
-
147
- checkboxIcon: {
148
- position: "absolute",
149
- pointerEvents: "none",
150
- // This margin is to center the check icon in the checkbox.
151
- margin: (size - checkSize) / 2,
152
- },
153
- });
154
-
155
- const fadedBlue = mix(color.fadedBlue16, white);
156
- const activeBlue = color.activeBlue;
157
- const fadedRed = mix(color.fadedRed8, white);
158
- const activeRed = color.activeRed;
159
-
160
- const colors = {
161
- default: {
162
- faded: fadedBlue,
163
- base: blue,
164
- active: activeBlue,
165
- },
166
- error: {
167
- faded: fadedRed,
168
- base: red,
169
- active: activeRed,
170
- },
171
- } as const;
172
-
173
- const styles: Record<string, any> = {};
174
-
175
- const _generateStyles = (checked: Checked, error: boolean) => {
176
- // "hash" the parameters
177
- const styleKey = `${String(checked)}-${String(error)}`;
178
- if (styles[styleKey]) {
179
- return styles[styleKey];
180
- }
181
-
182
- const palette = error ? colors.error : colors.default;
183
-
184
- let newStyles: Record<string, any> = {};
185
- if (checked || checked == null) {
186
- newStyles = {
187
- default: {
188
- backgroundColor: palette.base,
189
- borderWidth: 0,
190
-
191
- // Focus and hover have the same style. Focus style only shows
192
- // up with keyboard navigation.
193
- ":focus-visible": {
194
- boxShadow: `0 0 0 1px ${white}, 0 0 0 3px ${palette.base}`,
195
- },
196
-
197
- ":hover": {
198
- boxShadow: `0 0 0 1px ${white}, 0 0 0 3px ${palette.base}`,
199
- },
200
-
201
- ":active": {
202
- boxShadow: `0 0 0 1px ${white}, 0 0 0 3px ${palette.active}`,
203
- background: palette.active,
204
- },
205
- },
206
- };
207
- } else {
208
- newStyles = {
209
- default: {
210
- backgroundColor: error ? fadedRed : white,
211
- borderColor: error ? red : offBlack50,
212
-
213
- // Focus and hover have the same style. Focus style only shows
214
- // up with keyboard navigation.
215
- ":focus-visible": {
216
- backgroundColor: error ? fadedRed : white,
217
- borderColor: palette.base,
218
- borderWidth: 2,
219
- },
220
-
221
- ":hover": {
222
- backgroundColor: error ? fadedRed : white,
223
- borderColor: palette.base,
224
- borderWidth: 2,
225
- },
226
-
227
- ":active": {
228
- backgroundColor: palette.faded,
229
- borderColor: error ? activeRed : blue,
230
- borderWidth: 2,
231
- },
232
- },
233
- };
234
- }
235
- styles[styleKey] = StyleSheet.create(newStyles);
236
- return styles[styleKey];
237
- };
238
-
239
- export default CheckboxCore;
@@ -1,174 +0,0 @@
1
- import * as React from "react";
2
-
3
- import {View, addStyle} from "@khanacademy/wonder-blocks-core";
4
- import {Strut} from "@khanacademy/wonder-blocks-layout";
5
- import {spacing} from "@khanacademy/wonder-blocks-tokens";
6
- import {LabelMedium, LabelSmall} from "@khanacademy/wonder-blocks-typography";
7
- import type {StyleType} from "@khanacademy/wonder-blocks-core";
8
-
9
- import styles from "./group-styles";
10
- import Choice from "./choice";
11
-
12
- // Keep synced with CheckboxGroupProps in ../util/types.js
13
- type CheckboxGroupProps = {
14
- /**
15
- * Children should be Choice components.
16
- */
17
- children: Array<
18
- | React.ReactElement<React.ComponentProps<typeof Choice>>
19
- | false
20
- | null
21
- | undefined
22
- >;
23
- /**
24
- * Group name for this checkbox or radio group. Should be unique for all
25
- * such groups displayed on a page.
26
- */
27
- groupName: string;
28
- /**
29
- * Optional label for the group. This label is optional to allow for
30
- * greater flexibility in implementing checkbox and radio groups.
31
- */
32
- label?: React.ReactNode;
33
- /**
34
- * Optional description for the group.
35
- */
36
- description?: React.ReactNode;
37
- /**
38
- * Optional error message. If supplied, the group will be displayed in an
39
- * error state, along with this error message. If no error state is desired,
40
- * simply do not supply this prop, or pass along null.
41
- */
42
- errorMessage?: string | null | undefined;
43
- /**
44
- * Custom styling for this group of checkboxes.
45
- */
46
- style?: StyleType;
47
- /**
48
- * Callback for when selection of the group has changed. Passes the newly
49
- * selected values.
50
- */
51
- onChange: (selectedValues: Array<string>) => unknown;
52
- /**
53
- * An array of the values of the selected values in this checkbox group.
54
- */
55
- selectedValues: Array<string>;
56
- /**
57
- * Test ID used for e2e testing.
58
- */
59
- testId?: string;
60
- };
61
-
62
- const StyledFieldset = addStyle("fieldset");
63
- const StyledLegend = addStyle("legend");
64
-
65
- /**
66
- * A checkbox group allows multiple selection. This component auto-populates
67
- * many props for its children Choice components. The Choice component is
68
- * exposed for the user to apply custom styles or to indicate which choices are
69
- * disabled.
70
- *
71
- * ### Usage
72
- *
73
- * ```jsx
74
- * import {Choice, CheckboxGroup} from "@khanacademy/wonder-blocks-form";
75
- *
76
- * const [selectedValues, setSelectedValues] = React.useState([]);
77
- *
78
- * <CheckboxGroup
79
- * label="some-label"
80
- * description="some-description"
81
- * groupName="some-group-name"
82
- * onChange={setSelectedValues}
83
- * selectedValues={selectedValues}
84
- * >
85
- * // Add as many choices as necessary
86
- * <Choice
87
- * label="Choice 1"
88
- * value="some-choice-value"
89
- * />
90
- * <Choice
91
- * label="Choice 2"
92
- * value="some-choice-value-2"
93
- * description="Some choice description."
94
- * />
95
- * </CheckboxGroup>
96
- * ```
97
- */
98
- const CheckboxGroup = React.forwardRef(function CheckboxGroup(
99
- props: CheckboxGroupProps,
100
- ref: React.ForwardedRef<HTMLFieldSetElement>,
101
- ) {
102
- const {
103
- children,
104
- label,
105
- description,
106
- errorMessage,
107
- groupName,
108
- onChange,
109
- selectedValues,
110
- style,
111
- testId,
112
- } = props;
113
-
114
- const handleChange = (
115
- changedValue: string,
116
- originalCheckedState: boolean,
117
- ) => {
118
- if (originalCheckedState) {
119
- const index = selectedValues.indexOf(changedValue);
120
- const updatedSelection = [
121
- ...selectedValues.slice(0, index),
122
- ...selectedValues.slice(index + 1),
123
- ];
124
- onChange(updatedSelection);
125
- } else {
126
- onChange([...selectedValues, changedValue]);
127
- }
128
- };
129
-
130
- const allChildren = React.Children.toArray(children).filter(Boolean);
131
-
132
- return (
133
- <StyledFieldset data-testid={testId} style={styles.fieldset} ref={ref}>
134
- {/* We have a View here because fieldset cannot be used with flexbox*/}
135
- <View style={style}>
136
- {label && (
137
- <StyledLegend style={styles.legend}>
138
- <LabelMedium>{label}</LabelMedium>
139
- </StyledLegend>
140
- )}
141
- {description && (
142
- <LabelSmall style={styles.description}>
143
- {description}
144
- </LabelSmall>
145
- )}
146
- {errorMessage && (
147
- <LabelSmall style={styles.error}>{errorMessage}</LabelSmall>
148
- )}
149
- {(label || description || errorMessage) && (
150
- <Strut size={spacing.small_12} />
151
- )}
152
-
153
- {allChildren.map((child, index) => {
154
- // @ts-expect-error [FEI-5019] - TS2339 - Property 'props' does not exist on type 'ReactChild | ReactFragment | ReactPortal'.
155
- const {style, value} = child.props;
156
- const checked = selectedValues.includes(value);
157
- // @ts-expect-error [FEI-5019] - TS2769 - No overload matches this call.
158
- return React.cloneElement(child, {
159
- checked: checked,
160
- error: !!errorMessage,
161
- groupName: groupName,
162
- id: `${groupName}-${value}`,
163
- key: value,
164
- onChange: () => handleChange(value, checked),
165
- style: [index > 0 && styles.defaultLineGap, style],
166
- variant: "checkbox",
167
- });
168
- })}
169
- </View>
170
- </StyledFieldset>
171
- );
172
- });
173
-
174
- export default CheckboxGroup;
@@ -1,99 +0,0 @@
1
- import * as React from "react";
2
-
3
- import type {AriaProps, StyleType} from "@khanacademy/wonder-blocks-core";
4
- import type {Checked} from "../util/types";
5
-
6
- import ChoiceInternal from "./choice-internal";
7
-
8
- // Keep synced with ChoiceComponentProps in ../util/types.js
9
- type ChoiceComponentProps = AriaProps & {
10
- /**
11
- * Whether this component is checked or indeterminate
12
- */
13
- checked: Checked;
14
- /**
15
- * Whether this component is disabled
16
- */
17
- disabled?: boolean;
18
- /**
19
- * Whether this component should show an error state
20
- */
21
- error?: boolean;
22
- /**
23
- * Callback when this component is selected. The newCheckedState is the
24
- * new checked state of the component.
25
- */
26
- onChange: (newCheckedState: boolean) => unknown;
27
- /**
28
- * Optional label for the field.
29
- */
30
- label?: React.ReactNode;
31
- /**
32
- * Optional description for the field.
33
- */
34
- description?: React.ReactNode;
35
- /**
36
- * Unique identifier attached to the HTML input element. If used, need to
37
- * guarantee that the ID is unique within everything rendered on a page.
38
- * Used to match `<label>` with `<input>` elements for screenreaders.
39
- */
40
- id?: string;
41
- /**
42
- * Optional styling for the container. Does not style the component.
43
- */
44
- style?: StyleType;
45
- /**
46
- * Adds CSS classes to the Checkbox.
47
- */
48
- className?: string;
49
- /**
50
- * Optional test ID for e2e testing
51
- */
52
- testId?: string;
53
- /**
54
- * Name for the checkbox or radio button group. Only applicable for group
55
- * contexts, auto-populated by group components via Choice.
56
- * @ignore
57
- */
58
- groupName?: string;
59
- };
60
-
61
- /**
62
- * ☑️ A nicely styled checkbox for all your checking needs. Can optionally take
63
- * label and description props.
64
- *
65
- * If used by itself, a checkbox provides two options - checked and unchecked.
66
- * A group of checkboxes can be used to allow a user to select multiple values
67
- * from a list of options.
68
- *
69
- * If you want a whole group of Checkbox[es] that are related, see the Choice
70
- * and CheckboxGroup components.
71
- *
72
- * ### Usage
73
- *
74
- * ```jsx
75
- * import {Checkbox} from "@khanacademy/wonder-blocks-form";
76
- *
77
- * const [checked, setChecked] = React.useState(false);
78
- *
79
- * <Checkbox checked={checked} onChange={setChecked} />
80
- * ```
81
- */
82
- const Checkbox = React.forwardRef(function Checkbox(
83
- props: ChoiceComponentProps,
84
- ref: React.ForwardedRef<HTMLInputElement>,
85
- ) {
86
- const {disabled = false, error = false} = props;
87
-
88
- return (
89
- <ChoiceInternal
90
- {...props}
91
- variant="checkbox"
92
- disabled={disabled}
93
- error={error}
94
- ref={ref}
95
- />
96
- );
97
- });
98
-
99
- export default Checkbox;
@@ -1,184 +0,0 @@
1
- import * as React from "react";
2
- import {StyleSheet} from "aphrodite";
3
-
4
- import {View, UniqueIDProvider} from "@khanacademy/wonder-blocks-core";
5
- import {Strut} from "@khanacademy/wonder-blocks-layout";
6
- import {color, spacing} from "@khanacademy/wonder-blocks-tokens";
7
- import {LabelMedium, LabelSmall} from "@khanacademy/wonder-blocks-typography";
8
- import type {AriaProps, StyleType} from "@khanacademy/wonder-blocks-core";
9
- import CheckboxCore from "./checkbox-core";
10
- import RadioCore from "./radio-core";
11
-
12
- type Props = AriaProps & {
13
- /** Whether this choice is checked. */
14
- checked: boolean | null | undefined;
15
- /** Whether this choice option is disabled. */
16
- disabled?: boolean;
17
- /** Whether this choice is in error mode. */
18
- error?: boolean;
19
- /** Returns the new checked state of the component. */
20
- onChange: (newCheckedState: boolean) => unknown;
21
- /**
22
- * Used for accessibility purposes, where the label id should match the
23
- * input id.
24
- */
25
- id?: string;
26
- /**
27
- * Optional additional styling.
28
- */
29
- style?: StyleType;
30
- /**
31
- * Adds CSS classes to the Button.
32
- */
33
- className?: string;
34
- /**
35
- * Optional id for testing purposes.
36
- */
37
- testId?: string;
38
- /**
39
- * Label for the field.
40
- */
41
- label?: React.ReactNode;
42
- /** Optional description for the field. */
43
- description?: React.ReactNode;
44
- /** Auto-populated by parent's groupName prop if in a group. */
45
- groupName?: string;
46
- /** Takes either "radio" or "checkbox" value. */
47
- variant: "radio" | "checkbox";
48
- };
49
-
50
- /**
51
- * This is a potentially labeled 🔘 or ☑️ item. This is an internal component
52
- * that's wrapped by Checkbox and Radio. Choice is a wrapper for Checkbox and
53
- * Radio with many of its props auto-populated, to be used with CheckboxGroup
54
- * and RadioGroup. This design allows for more explicit prop typing. For
55
- * example, we can make onChange a required prop on Checkbox but not on Choice
56
- * (because for Choice, that prop would be auto-populated by CheckboxGroup).
57
- */ const ChoiceInternal = React.forwardRef(function ChoiceInternal(
58
- props: Props,
59
- ref: React.ForwardedRef<HTMLInputElement>,
60
- ) {
61
- const {
62
- checked,
63
- description,
64
- disabled = false,
65
- error = false,
66
- id,
67
- label,
68
- onChange,
69
- style,
70
- className,
71
- variant,
72
- ...coreProps
73
- } = props;
74
-
75
- const handleClick: () => void = () => {
76
- // Radio buttons cannot be unchecked
77
- if (variant === "radio" && checked) {
78
- return;
79
- }
80
- onChange(!checked);
81
- };
82
-
83
- const getChoiceCoreComponent = ():
84
- | typeof RadioCore
85
- | typeof CheckboxCore => {
86
- if (variant === "radio") {
87
- return RadioCore;
88
- } else {
89
- return CheckboxCore;
90
- }
91
- };
92
-
93
- const getLabel = (id: string): React.ReactNode => {
94
- return (
95
- <LabelMedium
96
- style={[styles.label, disabled && styles.disabledLabel]}
97
- >
98
- <label htmlFor={id}>{label}</label>
99
- </LabelMedium>
100
- );
101
- };
102
-
103
- const getDescription = (id?: string): React.ReactNode => {
104
- return (
105
- <LabelSmall style={styles.description} id={id}>
106
- {description}
107
- </LabelSmall>
108
- );
109
- };
110
-
111
- const ChoiceCore = getChoiceCoreComponent();
112
-
113
- return (
114
- <UniqueIDProvider mockOnFirstRender={true} scope="choice">
115
- {(ids) => {
116
- // A choice element should always have a unique ID set
117
- // so that the label can always refer to this element.
118
- // This guarantees that clicking on the label will
119
- // always click on the choice as well. If an ID is
120
- // passed in as a prop, use that one. Otherwise,
121
- // create a unique ID using the provider.
122
- const uniqueId = id || ids.get("main");
123
-
124
- // Create a unique ID for the description section to be
125
- // used by this element's `aria-describedby`.
126
- const descriptionId = description
127
- ? ids.get("description")
128
- : undefined;
129
-
130
- return (
131
- <View style={style} className={className}>
132
- <View
133
- style={styles.wrapper}
134
- // We are resetting the tabIndex=0 from handlers
135
- // because the ChoiceCore component will receive
136
- // focus on basis of it being an input element.
137
- tabIndex={-1}
138
- >
139
- <ChoiceCore
140
- {...coreProps}
141
- id={uniqueId}
142
- checked={checked}
143
- aria-describedby={descriptionId}
144
- onClick={handleClick}
145
- disabled={disabled}
146
- error={error}
147
- ref={ref}
148
- />
149
- <Strut size={spacing.xSmall_8} />
150
- {label && getLabel(uniqueId)}
151
- </View>
152
- {description && getDescription(descriptionId)}
153
- </View>
154
- );
155
- }}
156
- </UniqueIDProvider>
157
- );
158
- });
159
-
160
- const styles = StyleSheet.create({
161
- wrapper: {
162
- flexDirection: "row",
163
- alignItems: "flex-start",
164
- outline: "none",
165
- },
166
- label: {
167
- // NOTE: The checkbox/radio button (height 16px) should be center
168
- // aligned with the first line of the label. However, LabelMedium has a
169
- // declared line height of 20px, so we need to adjust the top to get the
170
- // desired alignment.
171
- marginTop: -2,
172
- },
173
- disabledLabel: {
174
- color: color.offBlack32,
175
- },
176
- description: {
177
- // 16 for icon + 8 for spacing strut
178
- marginLeft: spacing.medium_16 + spacing.xSmall_8,
179
- marginTop: spacing.xxxSmall_4,
180
- color: color.offBlack64,
181
- },
182
- });
183
-
184
- export default ChoiceInternal;