@khanacademy/wonder-blocks-form 4.9.3 → 4.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @khanacademy/wonder-blocks-form
2
2
 
3
+ ## 4.10.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 7a98815b: LabeledTextField: Adds `name` prop for the `TextField` component
8
+
9
+ ## 4.9.4
10
+
11
+ ### Patch Changes
12
+
13
+ - 61dc4448: Allow `TextField` to be focusable when disabled. It now sets `aria-disabled` instead of the `disabled` attribute based on the `disabled` prop. This makes it so screenreaders will continue to communicate that the component is disabled, while allowing focus on the disabled component. Focus styling is also added to the disabled state.
14
+ - 2dfd5eb6: - Update `TextField` state styling so that it is consistent with other components like `TextArea`, `SingleSelect`, `MultiSelect` (especially the focus styling). The styling also now uses CSS pseudo-classes for easier testing in Chromatic and debugging in browsers.
15
+ - `TextField` and `TextArea` state styling has also been updated so that any outline styles outside of the component are now applied within the component to prevent cropped focus outlines in places where an ancestor element has `overflow: hidden`.
16
+
3
17
  ## 4.9.3
4
18
 
5
19
  ### Patch Changes
@@ -24,7 +24,15 @@ type CommonProps = {
24
24
  */
25
25
  value: string;
26
26
  /**
27
- * Makes a read-only input field that cannot be focused. Defaults to false.
27
+ * Whether the input should be disabled. Defaults to false.
28
+ * If the disabled prop is set to `true`, LabeledTextField will have disabled
29
+ * styling and will not be interactable.
30
+ *
31
+ * Note: The `disabled` prop sets the `aria-disabled` attribute to `true`
32
+ * instead of setting the `disabled` attribute. This is so that the component
33
+ * remains focusable while communicating to screen readers that it is disabled.
34
+ * This `disabled` prop will also set the `readonly` attribute to prevent
35
+ * typing in the field.
28
36
  */
29
37
  disabled: boolean;
30
38
  /**
@@ -112,6 +120,10 @@ type CommonProps = {
112
120
  * Specifies if the TextField allows autocomplete.
113
121
  */
114
122
  autoComplete?: string;
123
+ /**
124
+ * Provide a name for the TextField.
125
+ */
126
+ name?: string;
115
127
  };
116
128
  type OtherInputProps = CommonProps & {
117
129
  /**
@@ -21,7 +21,15 @@ type CommonProps = AriaProps & {
21
21
  */
22
22
  name?: string;
23
23
  /**
24
- * Makes a read-only input field that cannot be focused. Defaults to false.
24
+ * Whether the input should be disabled. Defaults to false.
25
+ * If the disabled prop is set to `true`, TextField will have disabled
26
+ * styling and will not be interactable.
27
+ *
28
+ * Note: The `disabled` prop sets the `aria-disabled` attribute to `true`
29
+ * instead of setting the `disabled` attribute. This is so that the component
30
+ * remains focusable while communicating to screen readers that it is disabled.
31
+ * This `disabled` prop will also set the `readonly` attribute to prevent
32
+ * typing in the field.
25
33
  */
26
34
  disabled: boolean;
27
35
  /**
@@ -133,10 +141,6 @@ type State = {
133
141
  * Displayed when the validation fails.
134
142
  */
135
143
  error: string | null | undefined;
136
- /**
137
- * The user focuses on this field.
138
- */
139
- focused: boolean;
140
144
  };
141
145
  /**
142
146
  * A TextField is an element used to accept a single line of text from the user.
@@ -150,6 +154,7 @@ declare class TextField extends React.Component<PropsWithForwardRef, State> {
150
154
  handleChange: (event: React.ChangeEvent<HTMLInputElement>) => unknown;
151
155
  handleFocus: (event: React.FocusEvent<HTMLInputElement>) => unknown;
152
156
  handleBlur: (event: React.FocusEvent<HTMLInputElement>) => unknown;
157
+ getStyles: () => StyleType;
153
158
  render(): React.ReactNode;
154
159
  }
155
160
  type ExportProps = OmitConstrained<JSX.LibraryManagedAttributes<typeof TextField, React.ComponentProps<typeof TextField>>, "forwardedRef">;
package/dist/es/index.js CHANGED
@@ -592,15 +592,14 @@ const RadioGroup = React.forwardRef(function RadioGroup(props, ref) {
592
592
  })));
593
593
  });
594
594
 
595
- const _excluded$2 = ["id", "type", "value", "name", "disabled", "onKeyDown", "placeholder", "light", "style", "testId", "readOnly", "autoFocus", "autoComplete", "forwardedRef", "onFocus", "onBlur", "onValidate", "validate", "onChange", "required"];
595
+ const _excluded$2 = ["id", "type", "value", "name", "disabled", "onKeyDown", "placeholder", "style", "testId", "readOnly", "autoFocus", "autoComplete", "forwardedRef", "light", "onFocus", "onBlur", "onValidate", "validate", "onChange", "required"];
596
596
  const defaultErrorMessage$1 = "This field is required.";
597
597
  const StyledInput = addStyle("input");
598
598
  class TextField extends React.Component {
599
599
  constructor(props) {
600
600
  super(props);
601
601
  this.state = {
602
- error: null,
603
- focused: false
602
+ error: null
604
603
  };
605
604
  this.maybeValidate = newValue => {
606
605
  const {
@@ -641,25 +640,30 @@ class TextField extends React.Component {
641
640
  const {
642
641
  onFocus
643
642
  } = this.props;
644
- this.setState({
645
- focused: true
646
- }, () => {
647
- if (onFocus) {
648
- onFocus(event);
649
- }
650
- });
643
+ if (onFocus) {
644
+ onFocus(event);
645
+ }
651
646
  };
652
647
  this.handleBlur = event => {
653
648
  const {
654
649
  onBlur
655
650
  } = this.props;
656
- this.setState({
657
- focused: false
658
- }, () => {
659
- if (onBlur) {
660
- onBlur(event);
661
- }
662
- });
651
+ if (onBlur) {
652
+ onBlur(event);
653
+ }
654
+ };
655
+ this.getStyles = () => {
656
+ const {
657
+ disabled,
658
+ light
659
+ } = this.props;
660
+ const {
661
+ error
662
+ } = this.state;
663
+ const baseStyles = [styles$2.input, styles$7.LabelMedium];
664
+ const defaultStyles = [styles$2.default, !disabled && styles$2.defaultFocus, disabled && styles$2.disabled, !!error && styles$2.error];
665
+ const lightStyles = [styles$2.light, !disabled && styles$2.lightFocus, disabled && styles$2.lightDisabled, !!error && styles$2.lightError];
666
+ return [...baseStyles, ...(light ? lightStyles : defaultStyles)];
663
667
  };
664
668
  if (props.validate && props.value !== "") {
665
669
  this.state.error = props.validate(props.value) || null;
@@ -680,7 +684,6 @@ class TextField extends React.Component {
680
684
  disabled,
681
685
  onKeyDown,
682
686
  placeholder,
683
- light,
684
687
  style,
685
688
  testId,
686
689
  readOnly,
@@ -693,19 +696,19 @@ class TextField extends React.Component {
693
696
  id: id,
694
697
  scope: "text-field"
695
698
  }, uniqueId => React.createElement(StyledInput, _extends({
696
- style: [styles$2.input, styles$7.LabelMedium, styles$2.default, disabled ? styles$2.disabled : this.state.focused ? [styles$2.focused, light && styles$2.defaultLight] : !!this.state.error && [styles$2.error, light && styles$2.errorLight], !!this.state.error && styles$2.error, style && style],
699
+ style: [this.getStyles(), style],
697
700
  id: uniqueId,
698
701
  type: type,
699
702
  placeholder: placeholder,
700
703
  value: value,
701
704
  name: name,
702
- disabled: disabled,
705
+ "aria-disabled": disabled,
703
706
  onChange: this.handleChange,
704
- onKeyDown: onKeyDown,
707
+ onKeyDown: disabled ? undefined : onKeyDown,
705
708
  onFocus: this.handleFocus,
706
709
  onBlur: this.handleBlur,
707
710
  "data-testid": testId,
708
- readOnly: readOnly,
711
+ readOnly: readOnly || disabled,
709
712
  autoFocus: autoFocus,
710
713
  autoComplete: autoComplete,
711
714
  ref: forwardedRef
@@ -723,12 +726,10 @@ const styles$2 = StyleSheet.create({
723
726
  input: {
724
727
  width: "100%",
725
728
  height: 40,
726
- borderRadius: 4,
729
+ borderRadius: border.radius.medium_4,
727
730
  boxSizing: "border-box",
728
731
  paddingLeft: spacing.medium_16,
729
- margin: 0,
730
- outline: "none",
731
- boxShadow: "none"
732
+ margin: 0
732
733
  },
733
734
  default: {
734
735
  background: color.white,
@@ -738,12 +739,23 @@ const styles$2 = StyleSheet.create({
738
739
  color: color.offBlack64
739
740
  }
740
741
  },
742
+ defaultFocus: {
743
+ ":focus-visible": {
744
+ borderColor: color.blue,
745
+ outline: `1px solid ${color.blue}`,
746
+ outlineOffset: "-2px"
747
+ }
748
+ },
741
749
  error: {
742
750
  background: color.fadedRed8,
743
751
  border: `1px solid ${color.red}`,
744
752
  color: color.offBlack,
745
753
  "::placeholder": {
746
754
  color: color.offBlack64
755
+ },
756
+ ":focus-visible": {
757
+ outlineColor: color.red,
758
+ borderColor: color.red
747
759
  }
748
760
  },
749
761
  disabled: {
@@ -751,22 +763,56 @@ const styles$2 = StyleSheet.create({
751
763
  border: `1px solid ${color.offBlack16}`,
752
764
  color: color.offBlack64,
753
765
  "::placeholder": {
754
- color: color.offBlack32
766
+ color: color.offBlack64
767
+ },
768
+ cursor: "not-allowed",
769
+ ":focus-visible": {
770
+ outline: `2px solid ${color.offBlack32}`,
771
+ outlineOffset: "-3px"
755
772
  }
756
773
  },
757
- focused: {
774
+ light: {
758
775
  background: color.white,
759
- border: `1px solid ${color.blue}`,
776
+ border: `1px solid ${color.offBlack16}`,
760
777
  color: color.offBlack,
761
778
  "::placeholder": {
762
779
  color: color.offBlack64
763
780
  }
764
781
  },
765
- defaultLight: {
766
- boxShadow: `0px 0px 0px 1px ${color.blue}, 0px 0px 0px 2px ${color.white}`
782
+ lightFocus: {
783
+ ":focus-visible": {
784
+ outline: `3px solid ${color.blue}`,
785
+ outlineOffset: "-4px",
786
+ borderColor: color.white
787
+ }
788
+ },
789
+ lightDisabled: {
790
+ backgroundColor: "transparent",
791
+ border: `1px solid ${color.white32}`,
792
+ color: color.white64,
793
+ "::placeholder": {
794
+ color: color.white64
795
+ },
796
+ cursor: "not-allowed",
797
+ ":focus-visible": {
798
+ borderColor: mix(color.white32, color.blue),
799
+ outline: `3px solid ${color.fadedBlue}`,
800
+ outlineOffset: "-4px"
801
+ }
767
802
  },
768
- errorLight: {
769
- boxShadow: `0px 0px 0px 1px ${color.red}, 0px 0px 0px 2px ${color.white}`
803
+ lightError: {
804
+ background: color.fadedRed8,
805
+ border: `1px solid ${color.white}`,
806
+ outline: `2px solid ${color.red}`,
807
+ outlineOffset: "-3px",
808
+ color: color.offBlack,
809
+ "::placeholder": {
810
+ color: color.offBlack64
811
+ },
812
+ ":focus-visible": {
813
+ outline: `3px solid ${color.red}`,
814
+ outlineOffset: "-4px"
815
+ }
770
816
  }
771
817
  });
772
818
  var TextField$1 = React.forwardRef((props, ref) => React.createElement(TextField, _extends({}, props, {
@@ -870,7 +916,7 @@ const styles$1 = StyleSheet.create({
870
916
  }
871
917
  });
872
918
 
873
- const _excluded$1 = ["id", "type", "label", "description", "value", "disabled", "required", "validate", "onChange", "onKeyDown", "placeholder", "light", "style", "testId", "readOnly", "autoComplete", "forwardedRef", "ariaDescribedby", "onValidate", "onFocus", "onBlur"];
919
+ const _excluded$1 = ["id", "type", "label", "description", "value", "disabled", "required", "validate", "onChange", "onKeyDown", "placeholder", "light", "style", "testId", "readOnly", "autoComplete", "forwardedRef", "ariaDescribedby", "name", "onValidate", "onFocus", "onBlur"];
874
920
  class LabeledTextField extends React.Component {
875
921
  constructor(props) {
876
922
  super(props);
@@ -935,7 +981,8 @@ class LabeledTextField extends React.Component {
935
981
  readOnly,
936
982
  autoComplete,
937
983
  forwardedRef,
938
- ariaDescribedby
984
+ ariaDescribedby,
985
+ name
939
986
  } = _this$props,
940
987
  otherProps = _objectWithoutPropertiesLoose(_this$props, _excluded$1);
941
988
  return React.createElement(IDProvider, {
@@ -965,7 +1012,8 @@ class LabeledTextField extends React.Component {
965
1012
  light: light,
966
1013
  readOnly: readOnly,
967
1014
  autoComplete: autoComplete,
968
- ref: forwardedRef
1015
+ ref: forwardedRef,
1016
+ name: name
969
1017
  }, otherProps)),
970
1018
  label: label,
971
1019
  description: description,
@@ -1062,7 +1110,7 @@ const TextArea = React.forwardRef(function TextArea(props, ref) {
1062
1110
  "data-testid": testId,
1063
1111
  ref: ref,
1064
1112
  className: className,
1065
- style: [...getStyles(), style],
1113
+ style: [getStyles(), style],
1066
1114
  value: value,
1067
1115
  onChange: handleChange,
1068
1116
  placeholder: placeholder,
@@ -1106,7 +1154,7 @@ const styles = StyleSheet.create({
1106
1154
  ":focus-visible": {
1107
1155
  borderColor: color.blue,
1108
1156
  outline: `1px solid ${color.blue}`,
1109
- outlineOffset: 0
1157
+ outlineOffset: "-2px"
1110
1158
  }
1111
1159
  },
1112
1160
  disabled: {
@@ -1118,8 +1166,8 @@ const styles = StyleSheet.create({
1118
1166
  },
1119
1167
  cursor: "not-allowed",
1120
1168
  ":focus-visible": {
1121
- outline: "none",
1122
- boxShadow: `0 0 0 1px ${color.white}, 0 0 0 3px ${color.offBlack32}`
1169
+ outline: `2px solid ${color.offBlack32}`,
1170
+ outlineOffset: "-3px"
1123
1171
  }
1124
1172
  },
1125
1173
  error: {
@@ -1144,10 +1192,9 @@ const styles = StyleSheet.create({
1144
1192
  },
1145
1193
  lightFocus: {
1146
1194
  ":focus-visible": {
1147
- outline: `1px solid ${color.blue}`,
1148
- outlineOffset: 0,
1149
- borderColor: color.blue,
1150
- boxShadow: `0px 0px 0px 2px ${color.blue}, 0px 0px 0px 3px ${color.white}`
1195
+ outline: `3px solid ${color.blue}`,
1196
+ outlineOffset: "-4px",
1197
+ borderColor: color.white
1151
1198
  }
1152
1199
  },
1153
1200
  lightDisabled: {
@@ -1160,22 +1207,22 @@ const styles = StyleSheet.create({
1160
1207
  cursor: "not-allowed",
1161
1208
  ":focus-visible": {
1162
1209
  borderColor: mix(color.white32, color.blue),
1163
- outline: "none",
1164
- boxShadow: `0 0 0 1px ${color.offBlack32}, 0 0 0 3px ${color.fadedBlue}`
1210
+ outline: `3px solid ${color.fadedBlue}`,
1211
+ outlineOffset: "-4px"
1165
1212
  }
1166
1213
  },
1167
1214
  lightError: {
1168
1215
  background: color.fadedRed8,
1169
- border: `1px solid ${color.red}`,
1170
- boxShadow: `0px 0px 0px 1px ${color.red}, 0px 0px 0px 2px ${color.white}`,
1216
+ border: `1px solid ${color.white}`,
1217
+ outline: `2px solid ${color.red}`,
1218
+ outlineOffset: "-3px",
1171
1219
  color: color.offBlack,
1172
1220
  "::placeholder": {
1173
1221
  color: color.offBlack64
1174
1222
  },
1175
1223
  ":focus-visible": {
1176
- outlineColor: color.red,
1177
- borderColor: color.red,
1178
- boxShadow: `0px 0px 0px 2px ${color.red}, 0px 0px 0px 3px ${color.white}`
1224
+ outline: `3px solid ${color.red}`,
1225
+ outlineOffset: "-4px"
1179
1226
  }
1180
1227
  }
1181
1228
  });
package/dist/index.js CHANGED
@@ -622,15 +622,14 @@ const RadioGroup = React__namespace.forwardRef(function RadioGroup(props, ref) {
622
622
  })));
623
623
  });
624
624
 
625
- const _excluded$2 = ["id", "type", "value", "name", "disabled", "onKeyDown", "placeholder", "light", "style", "testId", "readOnly", "autoFocus", "autoComplete", "forwardedRef", "onFocus", "onBlur", "onValidate", "validate", "onChange", "required"];
625
+ const _excluded$2 = ["id", "type", "value", "name", "disabled", "onKeyDown", "placeholder", "style", "testId", "readOnly", "autoFocus", "autoComplete", "forwardedRef", "light", "onFocus", "onBlur", "onValidate", "validate", "onChange", "required"];
626
626
  const defaultErrorMessage$1 = "This field is required.";
627
627
  const StyledInput = wonderBlocksCore.addStyle("input");
628
628
  class TextField extends React__namespace.Component {
629
629
  constructor(props) {
630
630
  super(props);
631
631
  this.state = {
632
- error: null,
633
- focused: false
632
+ error: null
634
633
  };
635
634
  this.maybeValidate = newValue => {
636
635
  const {
@@ -671,25 +670,30 @@ class TextField extends React__namespace.Component {
671
670
  const {
672
671
  onFocus
673
672
  } = this.props;
674
- this.setState({
675
- focused: true
676
- }, () => {
677
- if (onFocus) {
678
- onFocus(event);
679
- }
680
- });
673
+ if (onFocus) {
674
+ onFocus(event);
675
+ }
681
676
  };
682
677
  this.handleBlur = event => {
683
678
  const {
684
679
  onBlur
685
680
  } = this.props;
686
- this.setState({
687
- focused: false
688
- }, () => {
689
- if (onBlur) {
690
- onBlur(event);
691
- }
692
- });
681
+ if (onBlur) {
682
+ onBlur(event);
683
+ }
684
+ };
685
+ this.getStyles = () => {
686
+ const {
687
+ disabled,
688
+ light
689
+ } = this.props;
690
+ const {
691
+ error
692
+ } = this.state;
693
+ const baseStyles = [styles$2.input, wonderBlocksTypography.styles.LabelMedium];
694
+ const defaultStyles = [styles$2.default, !disabled && styles$2.defaultFocus, disabled && styles$2.disabled, !!error && styles$2.error];
695
+ const lightStyles = [styles$2.light, !disabled && styles$2.lightFocus, disabled && styles$2.lightDisabled, !!error && styles$2.lightError];
696
+ return [...baseStyles, ...(light ? lightStyles : defaultStyles)];
693
697
  };
694
698
  if (props.validate && props.value !== "") {
695
699
  this.state.error = props.validate(props.value) || null;
@@ -710,7 +714,6 @@ class TextField extends React__namespace.Component {
710
714
  disabled,
711
715
  onKeyDown,
712
716
  placeholder,
713
- light,
714
717
  style,
715
718
  testId,
716
719
  readOnly,
@@ -723,19 +726,19 @@ class TextField extends React__namespace.Component {
723
726
  id: id,
724
727
  scope: "text-field"
725
728
  }, uniqueId => React__namespace.createElement(StyledInput, _extends__default["default"]({
726
- style: [styles$2.input, wonderBlocksTypography.styles.LabelMedium, styles$2.default, disabled ? styles$2.disabled : this.state.focused ? [styles$2.focused, light && styles$2.defaultLight] : !!this.state.error && [styles$2.error, light && styles$2.errorLight], !!this.state.error && styles$2.error, style && style],
729
+ style: [this.getStyles(), style],
727
730
  id: uniqueId,
728
731
  type: type,
729
732
  placeholder: placeholder,
730
733
  value: value,
731
734
  name: name,
732
- disabled: disabled,
735
+ "aria-disabled": disabled,
733
736
  onChange: this.handleChange,
734
- onKeyDown: onKeyDown,
737
+ onKeyDown: disabled ? undefined : onKeyDown,
735
738
  onFocus: this.handleFocus,
736
739
  onBlur: this.handleBlur,
737
740
  "data-testid": testId,
738
- readOnly: readOnly,
741
+ readOnly: readOnly || disabled,
739
742
  autoFocus: autoFocus,
740
743
  autoComplete: autoComplete,
741
744
  ref: forwardedRef
@@ -753,12 +756,10 @@ const styles$2 = aphrodite.StyleSheet.create({
753
756
  input: {
754
757
  width: "100%",
755
758
  height: 40,
756
- borderRadius: 4,
759
+ borderRadius: wonderBlocksTokens.border.radius.medium_4,
757
760
  boxSizing: "border-box",
758
761
  paddingLeft: wonderBlocksTokens.spacing.medium_16,
759
- margin: 0,
760
- outline: "none",
761
- boxShadow: "none"
762
+ margin: 0
762
763
  },
763
764
  default: {
764
765
  background: wonderBlocksTokens.color.white,
@@ -768,12 +769,23 @@ const styles$2 = aphrodite.StyleSheet.create({
768
769
  color: wonderBlocksTokens.color.offBlack64
769
770
  }
770
771
  },
772
+ defaultFocus: {
773
+ ":focus-visible": {
774
+ borderColor: wonderBlocksTokens.color.blue,
775
+ outline: `1px solid ${wonderBlocksTokens.color.blue}`,
776
+ outlineOffset: "-2px"
777
+ }
778
+ },
771
779
  error: {
772
780
  background: wonderBlocksTokens.color.fadedRed8,
773
781
  border: `1px solid ${wonderBlocksTokens.color.red}`,
774
782
  color: wonderBlocksTokens.color.offBlack,
775
783
  "::placeholder": {
776
784
  color: wonderBlocksTokens.color.offBlack64
785
+ },
786
+ ":focus-visible": {
787
+ outlineColor: wonderBlocksTokens.color.red,
788
+ borderColor: wonderBlocksTokens.color.red
777
789
  }
778
790
  },
779
791
  disabled: {
@@ -781,22 +793,56 @@ const styles$2 = aphrodite.StyleSheet.create({
781
793
  border: `1px solid ${wonderBlocksTokens.color.offBlack16}`,
782
794
  color: wonderBlocksTokens.color.offBlack64,
783
795
  "::placeholder": {
784
- color: wonderBlocksTokens.color.offBlack32
796
+ color: wonderBlocksTokens.color.offBlack64
797
+ },
798
+ cursor: "not-allowed",
799
+ ":focus-visible": {
800
+ outline: `2px solid ${wonderBlocksTokens.color.offBlack32}`,
801
+ outlineOffset: "-3px"
785
802
  }
786
803
  },
787
- focused: {
804
+ light: {
788
805
  background: wonderBlocksTokens.color.white,
789
- border: `1px solid ${wonderBlocksTokens.color.blue}`,
806
+ border: `1px solid ${wonderBlocksTokens.color.offBlack16}`,
790
807
  color: wonderBlocksTokens.color.offBlack,
791
808
  "::placeholder": {
792
809
  color: wonderBlocksTokens.color.offBlack64
793
810
  }
794
811
  },
795
- defaultLight: {
796
- boxShadow: `0px 0px 0px 1px ${wonderBlocksTokens.color.blue}, 0px 0px 0px 2px ${wonderBlocksTokens.color.white}`
812
+ lightFocus: {
813
+ ":focus-visible": {
814
+ outline: `3px solid ${wonderBlocksTokens.color.blue}`,
815
+ outlineOffset: "-4px",
816
+ borderColor: wonderBlocksTokens.color.white
817
+ }
818
+ },
819
+ lightDisabled: {
820
+ backgroundColor: "transparent",
821
+ border: `1px solid ${wonderBlocksTokens.color.white32}`,
822
+ color: wonderBlocksTokens.color.white64,
823
+ "::placeholder": {
824
+ color: wonderBlocksTokens.color.white64
825
+ },
826
+ cursor: "not-allowed",
827
+ ":focus-visible": {
828
+ borderColor: wonderBlocksTokens.mix(wonderBlocksTokens.color.white32, wonderBlocksTokens.color.blue),
829
+ outline: `3px solid ${wonderBlocksTokens.color.fadedBlue}`,
830
+ outlineOffset: "-4px"
831
+ }
797
832
  },
798
- errorLight: {
799
- boxShadow: `0px 0px 0px 1px ${wonderBlocksTokens.color.red}, 0px 0px 0px 2px ${wonderBlocksTokens.color.white}`
833
+ lightError: {
834
+ background: wonderBlocksTokens.color.fadedRed8,
835
+ border: `1px solid ${wonderBlocksTokens.color.white}`,
836
+ outline: `2px solid ${wonderBlocksTokens.color.red}`,
837
+ outlineOffset: "-3px",
838
+ color: wonderBlocksTokens.color.offBlack,
839
+ "::placeholder": {
840
+ color: wonderBlocksTokens.color.offBlack64
841
+ },
842
+ ":focus-visible": {
843
+ outline: `3px solid ${wonderBlocksTokens.color.red}`,
844
+ outlineOffset: "-4px"
845
+ }
800
846
  }
801
847
  });
802
848
  var TextField$1 = React__namespace.forwardRef((props, ref) => React__namespace.createElement(TextField, _extends__default["default"]({}, props, {
@@ -900,7 +946,7 @@ const styles$1 = aphrodite.StyleSheet.create({
900
946
  }
901
947
  });
902
948
 
903
- const _excluded$1 = ["id", "type", "label", "description", "value", "disabled", "required", "validate", "onChange", "onKeyDown", "placeholder", "light", "style", "testId", "readOnly", "autoComplete", "forwardedRef", "ariaDescribedby", "onValidate", "onFocus", "onBlur"];
949
+ const _excluded$1 = ["id", "type", "label", "description", "value", "disabled", "required", "validate", "onChange", "onKeyDown", "placeholder", "light", "style", "testId", "readOnly", "autoComplete", "forwardedRef", "ariaDescribedby", "name", "onValidate", "onFocus", "onBlur"];
904
950
  class LabeledTextField extends React__namespace.Component {
905
951
  constructor(props) {
906
952
  super(props);
@@ -965,7 +1011,8 @@ class LabeledTextField extends React__namespace.Component {
965
1011
  readOnly,
966
1012
  autoComplete,
967
1013
  forwardedRef,
968
- ariaDescribedby
1014
+ ariaDescribedby,
1015
+ name
969
1016
  } = _this$props,
970
1017
  otherProps = _objectWithoutPropertiesLoose__default["default"](_this$props, _excluded$1);
971
1018
  return React__namespace.createElement(wonderBlocksCore.IDProvider, {
@@ -995,7 +1042,8 @@ class LabeledTextField extends React__namespace.Component {
995
1042
  light: light,
996
1043
  readOnly: readOnly,
997
1044
  autoComplete: autoComplete,
998
- ref: forwardedRef
1045
+ ref: forwardedRef,
1046
+ name: name
999
1047
  }, otherProps)),
1000
1048
  label: label,
1001
1049
  description: description,
@@ -1092,7 +1140,7 @@ const TextArea = React__namespace.forwardRef(function TextArea(props, ref) {
1092
1140
  "data-testid": testId,
1093
1141
  ref: ref,
1094
1142
  className: className,
1095
- style: [...getStyles(), style],
1143
+ style: [getStyles(), style],
1096
1144
  value: value,
1097
1145
  onChange: handleChange,
1098
1146
  placeholder: placeholder,
@@ -1136,7 +1184,7 @@ const styles = aphrodite.StyleSheet.create({
1136
1184
  ":focus-visible": {
1137
1185
  borderColor: wonderBlocksTokens.color.blue,
1138
1186
  outline: `1px solid ${wonderBlocksTokens.color.blue}`,
1139
- outlineOffset: 0
1187
+ outlineOffset: "-2px"
1140
1188
  }
1141
1189
  },
1142
1190
  disabled: {
@@ -1148,8 +1196,8 @@ const styles = aphrodite.StyleSheet.create({
1148
1196
  },
1149
1197
  cursor: "not-allowed",
1150
1198
  ":focus-visible": {
1151
- outline: "none",
1152
- boxShadow: `0 0 0 1px ${wonderBlocksTokens.color.white}, 0 0 0 3px ${wonderBlocksTokens.color.offBlack32}`
1199
+ outline: `2px solid ${wonderBlocksTokens.color.offBlack32}`,
1200
+ outlineOffset: "-3px"
1153
1201
  }
1154
1202
  },
1155
1203
  error: {
@@ -1174,10 +1222,9 @@ const styles = aphrodite.StyleSheet.create({
1174
1222
  },
1175
1223
  lightFocus: {
1176
1224
  ":focus-visible": {
1177
- outline: `1px solid ${wonderBlocksTokens.color.blue}`,
1178
- outlineOffset: 0,
1179
- borderColor: wonderBlocksTokens.color.blue,
1180
- boxShadow: `0px 0px 0px 2px ${wonderBlocksTokens.color.blue}, 0px 0px 0px 3px ${wonderBlocksTokens.color.white}`
1225
+ outline: `3px solid ${wonderBlocksTokens.color.blue}`,
1226
+ outlineOffset: "-4px",
1227
+ borderColor: wonderBlocksTokens.color.white
1181
1228
  }
1182
1229
  },
1183
1230
  lightDisabled: {
@@ -1190,22 +1237,22 @@ const styles = aphrodite.StyleSheet.create({
1190
1237
  cursor: "not-allowed",
1191
1238
  ":focus-visible": {
1192
1239
  borderColor: wonderBlocksTokens.mix(wonderBlocksTokens.color.white32, wonderBlocksTokens.color.blue),
1193
- outline: "none",
1194
- boxShadow: `0 0 0 1px ${wonderBlocksTokens.color.offBlack32}, 0 0 0 3px ${wonderBlocksTokens.color.fadedBlue}`
1240
+ outline: `3px solid ${wonderBlocksTokens.color.fadedBlue}`,
1241
+ outlineOffset: "-4px"
1195
1242
  }
1196
1243
  },
1197
1244
  lightError: {
1198
1245
  background: wonderBlocksTokens.color.fadedRed8,
1199
- border: `1px solid ${wonderBlocksTokens.color.red}`,
1200
- boxShadow: `0px 0px 0px 1px ${wonderBlocksTokens.color.red}, 0px 0px 0px 2px ${wonderBlocksTokens.color.white}`,
1246
+ border: `1px solid ${wonderBlocksTokens.color.white}`,
1247
+ outline: `2px solid ${wonderBlocksTokens.color.red}`,
1248
+ outlineOffset: "-3px",
1201
1249
  color: wonderBlocksTokens.color.offBlack,
1202
1250
  "::placeholder": {
1203
1251
  color: wonderBlocksTokens.color.offBlack64
1204
1252
  },
1205
1253
  ":focus-visible": {
1206
- outlineColor: wonderBlocksTokens.color.red,
1207
- borderColor: wonderBlocksTokens.color.red,
1208
- boxShadow: `0px 0px 0px 2px ${wonderBlocksTokens.color.red}, 0px 0px 0px 3px ${wonderBlocksTokens.color.white}`
1254
+ outline: `3px solid ${wonderBlocksTokens.color.red}`,
1255
+ outlineOffset: "-4px"
1209
1256
  }
1210
1257
  }
1211
1258
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khanacademy/wonder-blocks-form",
3
- "version": "4.9.3",
3
+ "version": "4.10.0",
4
4
  "design": "v1",
5
5
  "description": "Form components for Wonder Blocks.",
6
6
  "main": "dist/index.js",