@khanacademy/wonder-blocks-form 4.9.0 → 4.9.1
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 +13 -0
- package/dist/components/field-heading.d.ts +4 -0
- package/dist/components/text-field.d.ts +1 -4
- package/dist/es/index.js +101 -38
- package/dist/index.js +101 -38
- package/package.json +6 -6
- package/src/components/__tests__/labeled-text-field.test.tsx +0 -23
- package/src/components/field-heading.tsx +26 -7
- package/src/components/labeled-text-field.tsx +1 -0
- package/src/components/text-area.tsx +3 -3
- package/src/components/text-field.tsx +82 -44
- package/tsconfig-build.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @khanacademy/wonder-blocks-form
|
|
2
2
|
|
|
3
|
+
## 4.9.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 982f6808: 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.
|
|
8
|
+
- 17f9a337: Improve `LabeledTextField` styling when the `light` prop is `true`. This improves the color contrast of the label, required indicator, description, and error message when the component is used on dark backgrounds.
|
|
9
|
+
- Updated dependencies [07f7f407]
|
|
10
|
+
- @khanacademy/wonder-blocks-core@7.0.0
|
|
11
|
+
- @khanacademy/wonder-blocks-layout@2.2.0
|
|
12
|
+
- @khanacademy/wonder-blocks-clickable@4.2.7
|
|
13
|
+
- @khanacademy/wonder-blocks-icon@4.1.4
|
|
14
|
+
- @khanacademy/wonder-blocks-typography@2.1.15
|
|
15
|
+
|
|
3
16
|
## 4.9.0
|
|
4
17
|
|
|
5
18
|
### Minor Changes
|
|
@@ -36,6 +36,10 @@ type Props = {
|
|
|
36
36
|
* Optional test ID for e2e testing.
|
|
37
37
|
*/
|
|
38
38
|
testId?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Change the field’s sub-components to fit a dark background.
|
|
41
|
+
*/
|
|
42
|
+
light?: boolean;
|
|
39
43
|
};
|
|
40
44
|
/**
|
|
41
45
|
* A FieldHeading is an element that provides a label, description, and error element
|
|
@@ -133,10 +133,6 @@ type State = {
|
|
|
133
133
|
* Displayed when the validation fails.
|
|
134
134
|
*/
|
|
135
135
|
error: string | null | undefined;
|
|
136
|
-
/**
|
|
137
|
-
* The user focuses on this field.
|
|
138
|
-
*/
|
|
139
|
-
focused: boolean;
|
|
140
136
|
};
|
|
141
137
|
/**
|
|
142
138
|
* A TextField is an element used to accept a single line of text from the user.
|
|
@@ -150,6 +146,7 @@ declare class TextField extends React.Component<PropsWithForwardRef, State> {
|
|
|
150
146
|
handleChange: (event: React.ChangeEvent<HTMLInputElement>) => unknown;
|
|
151
147
|
handleFocus: (event: React.FocusEvent<HTMLInputElement>) => unknown;
|
|
152
148
|
handleBlur: (event: React.FocusEvent<HTMLInputElement>) => unknown;
|
|
149
|
+
getStyles: () => StyleType;
|
|
153
150
|
render(): React.ReactNode;
|
|
154
151
|
}
|
|
155
152
|
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", "
|
|
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
|
-
|
|
645
|
-
|
|
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
|
-
|
|
657
|
-
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
|
|
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,7 +696,7 @@ class TextField extends React.Component {
|
|
|
693
696
|
id: id,
|
|
694
697
|
scope: "text-field"
|
|
695
698
|
}, uniqueId => React.createElement(StyledInput, _extends({
|
|
696
|
-
style: [
|
|
699
|
+
style: [this.getStyles(), style],
|
|
697
700
|
id: uniqueId,
|
|
698
701
|
type: type,
|
|
699
702
|
placeholder: placeholder,
|
|
@@ -723,12 +726,10 @@ const styles$2 = StyleSheet.create({
|
|
|
723
726
|
input: {
|
|
724
727
|
width: "100%",
|
|
725
728
|
height: 40,
|
|
726
|
-
borderRadius:
|
|
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: 0
|
|
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,57 @@ const styles$2 = StyleSheet.create({
|
|
|
751
763
|
border: `1px solid ${color.offBlack16}`,
|
|
752
764
|
color: color.offBlack64,
|
|
753
765
|
"::placeholder": {
|
|
754
|
-
color: color.
|
|
766
|
+
color: color.offBlack64
|
|
767
|
+
},
|
|
768
|
+
cursor: "not-allowed",
|
|
769
|
+
":focus-visible": {
|
|
770
|
+
outline: "none",
|
|
771
|
+
boxShadow: `0 0 0 1px ${color.white}, 0 0 0 3px ${color.offBlack32}`
|
|
755
772
|
}
|
|
756
773
|
},
|
|
757
|
-
|
|
774
|
+
light: {
|
|
758
775
|
background: color.white,
|
|
759
|
-
border: `1px solid ${color.
|
|
776
|
+
border: `1px solid ${color.offBlack16}`,
|
|
760
777
|
color: color.offBlack,
|
|
761
778
|
"::placeholder": {
|
|
762
779
|
color: color.offBlack64
|
|
763
780
|
}
|
|
764
781
|
},
|
|
765
|
-
|
|
766
|
-
|
|
782
|
+
lightFocus: {
|
|
783
|
+
":focus-visible": {
|
|
784
|
+
outline: `1px solid ${color.blue}`,
|
|
785
|
+
outlineOffset: 0,
|
|
786
|
+
borderColor: color.blue,
|
|
787
|
+
boxShadow: `0px 0px 0px 2px ${color.blue}, 0px 0px 0px 3px ${color.white}`
|
|
788
|
+
}
|
|
767
789
|
},
|
|
768
|
-
|
|
769
|
-
|
|
790
|
+
lightDisabled: {
|
|
791
|
+
backgroundColor: "transparent",
|
|
792
|
+
border: `1px solid ${color.white32}`,
|
|
793
|
+
color: color.white64,
|
|
794
|
+
"::placeholder": {
|
|
795
|
+
color: color.white64
|
|
796
|
+
},
|
|
797
|
+
cursor: "not-allowed",
|
|
798
|
+
":focus-visible": {
|
|
799
|
+
borderColor: mix(color.white32, color.blue),
|
|
800
|
+
outline: "none",
|
|
801
|
+
boxShadow: `0 0 0 1px ${color.offBlack32}, 0 0 0 3px ${color.fadedBlue}`
|
|
802
|
+
}
|
|
803
|
+
},
|
|
804
|
+
lightError: {
|
|
805
|
+
background: color.fadedRed8,
|
|
806
|
+
border: `1px solid ${color.red}`,
|
|
807
|
+
boxShadow: `0px 0px 0px 1px ${color.red}, 0px 0px 0px 2px ${color.white}`,
|
|
808
|
+
color: color.offBlack,
|
|
809
|
+
"::placeholder": {
|
|
810
|
+
color: color.offBlack64
|
|
811
|
+
},
|
|
812
|
+
":focus-visible": {
|
|
813
|
+
outlineColor: color.red,
|
|
814
|
+
borderColor: color.red,
|
|
815
|
+
boxShadow: `0px 0px 0px 2px ${color.red}, 0px 0px 0px 3px ${color.white}`
|
|
816
|
+
}
|
|
770
817
|
}
|
|
771
818
|
});
|
|
772
819
|
var TextField$1 = React.forwardRef((props, ref) => React.createElement(TextField, _extends({}, props, {
|
|
@@ -780,14 +827,15 @@ class FieldHeading extends React.Component {
|
|
|
780
827
|
label,
|
|
781
828
|
id,
|
|
782
829
|
required,
|
|
783
|
-
testId
|
|
830
|
+
testId,
|
|
831
|
+
light
|
|
784
832
|
} = this.props;
|
|
785
833
|
const requiredIcon = React.createElement(StyledSpan, {
|
|
786
|
-
style: styles$1.required,
|
|
834
|
+
style: light ? styles$1.lightRequired : styles$1.required,
|
|
787
835
|
"aria-hidden": true
|
|
788
836
|
}, " ", "*");
|
|
789
837
|
return React.createElement(React.Fragment, null, React.createElement(LabelMedium, {
|
|
790
|
-
style: styles$1.label,
|
|
838
|
+
style: light ? styles$1.lightLabel : styles$1.label,
|
|
791
839
|
tag: "label",
|
|
792
840
|
htmlFor: id && `${id}-field`,
|
|
793
841
|
testId: testId && `${testId}-label`
|
|
@@ -798,13 +846,14 @@ class FieldHeading extends React.Component {
|
|
|
798
846
|
maybeRenderDescription() {
|
|
799
847
|
const {
|
|
800
848
|
description,
|
|
801
|
-
testId
|
|
849
|
+
testId,
|
|
850
|
+
light
|
|
802
851
|
} = this.props;
|
|
803
852
|
if (!description) {
|
|
804
853
|
return null;
|
|
805
854
|
}
|
|
806
855
|
return React.createElement(React.Fragment, null, React.createElement(LabelSmall, {
|
|
807
|
-
style: styles$1.description,
|
|
856
|
+
style: light ? styles$1.lightDescription : styles$1.description,
|
|
808
857
|
testId: testId && `${testId}-description`
|
|
809
858
|
}, description), React.createElement(Strut, {
|
|
810
859
|
size: spacing.xxxSmall_4
|
|
@@ -814,7 +863,8 @@ class FieldHeading extends React.Component {
|
|
|
814
863
|
const {
|
|
815
864
|
error,
|
|
816
865
|
id,
|
|
817
|
-
testId
|
|
866
|
+
testId,
|
|
867
|
+
light
|
|
818
868
|
} = this.props;
|
|
819
869
|
if (!error) {
|
|
820
870
|
return null;
|
|
@@ -822,7 +872,7 @@ class FieldHeading extends React.Component {
|
|
|
822
872
|
return React.createElement(React.Fragment, null, React.createElement(Strut, {
|
|
823
873
|
size: spacing.small_12
|
|
824
874
|
}), React.createElement(LabelSmall, {
|
|
825
|
-
style: styles$1.error,
|
|
875
|
+
style: light ? styles$1.lightError : styles$1.error,
|
|
826
876
|
role: "alert",
|
|
827
877
|
id: id && `${id}-error`,
|
|
828
878
|
testId: testId && `${testId}-error`
|
|
@@ -844,14 +894,26 @@ const styles$1 = StyleSheet.create({
|
|
|
844
894
|
label: {
|
|
845
895
|
color: color.offBlack
|
|
846
896
|
},
|
|
897
|
+
lightLabel: {
|
|
898
|
+
color: color.white
|
|
899
|
+
},
|
|
847
900
|
description: {
|
|
848
901
|
color: color.offBlack64
|
|
849
902
|
},
|
|
903
|
+
lightDescription: {
|
|
904
|
+
color: color.white64
|
|
905
|
+
},
|
|
850
906
|
error: {
|
|
851
907
|
color: color.red
|
|
852
908
|
},
|
|
909
|
+
lightError: {
|
|
910
|
+
color: color.fadedRed
|
|
911
|
+
},
|
|
853
912
|
required: {
|
|
854
913
|
color: color.red
|
|
914
|
+
},
|
|
915
|
+
lightRequired: {
|
|
916
|
+
color: color.fadedRed
|
|
855
917
|
}
|
|
856
918
|
});
|
|
857
919
|
|
|
@@ -930,6 +992,7 @@ class LabeledTextField extends React.Component {
|
|
|
930
992
|
id: uniqueId,
|
|
931
993
|
testId: testId,
|
|
932
994
|
style: style,
|
|
995
|
+
light: light,
|
|
933
996
|
field: React.createElement(TextField$1, _extends({
|
|
934
997
|
id: `${uniqueId}-field`,
|
|
935
998
|
"aria-describedby": ariaDescribedby ? ariaDescribedby : `${uniqueId}-error`,
|
|
@@ -1046,7 +1109,7 @@ const TextArea = React.forwardRef(function TextArea(props, ref) {
|
|
|
1046
1109
|
"data-testid": testId,
|
|
1047
1110
|
ref: ref,
|
|
1048
1111
|
className: className,
|
|
1049
|
-
style: [
|
|
1112
|
+
style: [getStyles(), style],
|
|
1050
1113
|
value: value,
|
|
1051
1114
|
onChange: handleChange,
|
|
1052
1115
|
placeholder: placeholder,
|
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", "
|
|
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
|
-
|
|
675
|
-
|
|
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
|
-
|
|
687
|
-
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
|
|
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,7 +726,7 @@ 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: [
|
|
729
|
+
style: [this.getStyles(), style],
|
|
727
730
|
id: uniqueId,
|
|
728
731
|
type: type,
|
|
729
732
|
placeholder: placeholder,
|
|
@@ -753,12 +756,10 @@ const styles$2 = aphrodite.StyleSheet.create({
|
|
|
753
756
|
input: {
|
|
754
757
|
width: "100%",
|
|
755
758
|
height: 40,
|
|
756
|
-
borderRadius:
|
|
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: 0
|
|
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,57 @@ 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.
|
|
796
|
+
color: wonderBlocksTokens.color.offBlack64
|
|
797
|
+
},
|
|
798
|
+
cursor: "not-allowed",
|
|
799
|
+
":focus-visible": {
|
|
800
|
+
outline: "none",
|
|
801
|
+
boxShadow: `0 0 0 1px ${wonderBlocksTokens.color.white}, 0 0 0 3px ${wonderBlocksTokens.color.offBlack32}`
|
|
785
802
|
}
|
|
786
803
|
},
|
|
787
|
-
|
|
804
|
+
light: {
|
|
788
805
|
background: wonderBlocksTokens.color.white,
|
|
789
|
-
border: `1px solid ${wonderBlocksTokens.color.
|
|
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
|
-
|
|
796
|
-
|
|
812
|
+
lightFocus: {
|
|
813
|
+
":focus-visible": {
|
|
814
|
+
outline: `1px solid ${wonderBlocksTokens.color.blue}`,
|
|
815
|
+
outlineOffset: 0,
|
|
816
|
+
borderColor: wonderBlocksTokens.color.blue,
|
|
817
|
+
boxShadow: `0px 0px 0px 2px ${wonderBlocksTokens.color.blue}, 0px 0px 0px 3px ${wonderBlocksTokens.color.white}`
|
|
818
|
+
}
|
|
797
819
|
},
|
|
798
|
-
|
|
799
|
-
|
|
820
|
+
lightDisabled: {
|
|
821
|
+
backgroundColor: "transparent",
|
|
822
|
+
border: `1px solid ${wonderBlocksTokens.color.white32}`,
|
|
823
|
+
color: wonderBlocksTokens.color.white64,
|
|
824
|
+
"::placeholder": {
|
|
825
|
+
color: wonderBlocksTokens.color.white64
|
|
826
|
+
},
|
|
827
|
+
cursor: "not-allowed",
|
|
828
|
+
":focus-visible": {
|
|
829
|
+
borderColor: wonderBlocksTokens.mix(wonderBlocksTokens.color.white32, wonderBlocksTokens.color.blue),
|
|
830
|
+
outline: "none",
|
|
831
|
+
boxShadow: `0 0 0 1px ${wonderBlocksTokens.color.offBlack32}, 0 0 0 3px ${wonderBlocksTokens.color.fadedBlue}`
|
|
832
|
+
}
|
|
833
|
+
},
|
|
834
|
+
lightError: {
|
|
835
|
+
background: wonderBlocksTokens.color.fadedRed8,
|
|
836
|
+
border: `1px solid ${wonderBlocksTokens.color.red}`,
|
|
837
|
+
boxShadow: `0px 0px 0px 1px ${wonderBlocksTokens.color.red}, 0px 0px 0px 2px ${wonderBlocksTokens.color.white}`,
|
|
838
|
+
color: wonderBlocksTokens.color.offBlack,
|
|
839
|
+
"::placeholder": {
|
|
840
|
+
color: wonderBlocksTokens.color.offBlack64
|
|
841
|
+
},
|
|
842
|
+
":focus-visible": {
|
|
843
|
+
outlineColor: wonderBlocksTokens.color.red,
|
|
844
|
+
borderColor: wonderBlocksTokens.color.red,
|
|
845
|
+
boxShadow: `0px 0px 0px 2px ${wonderBlocksTokens.color.red}, 0px 0px 0px 3px ${wonderBlocksTokens.color.white}`
|
|
846
|
+
}
|
|
800
847
|
}
|
|
801
848
|
});
|
|
802
849
|
var TextField$1 = React__namespace.forwardRef((props, ref) => React__namespace.createElement(TextField, _extends__default["default"]({}, props, {
|
|
@@ -810,14 +857,15 @@ class FieldHeading extends React__namespace.Component {
|
|
|
810
857
|
label,
|
|
811
858
|
id,
|
|
812
859
|
required,
|
|
813
|
-
testId
|
|
860
|
+
testId,
|
|
861
|
+
light
|
|
814
862
|
} = this.props;
|
|
815
863
|
const requiredIcon = React__namespace.createElement(StyledSpan, {
|
|
816
|
-
style: styles$1.required,
|
|
864
|
+
style: light ? styles$1.lightRequired : styles$1.required,
|
|
817
865
|
"aria-hidden": true
|
|
818
866
|
}, " ", "*");
|
|
819
867
|
return React__namespace.createElement(React__namespace.Fragment, null, React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
|
|
820
|
-
style: styles$1.label,
|
|
868
|
+
style: light ? styles$1.lightLabel : styles$1.label,
|
|
821
869
|
tag: "label",
|
|
822
870
|
htmlFor: id && `${id}-field`,
|
|
823
871
|
testId: testId && `${testId}-label`
|
|
@@ -828,13 +876,14 @@ class FieldHeading extends React__namespace.Component {
|
|
|
828
876
|
maybeRenderDescription() {
|
|
829
877
|
const {
|
|
830
878
|
description,
|
|
831
|
-
testId
|
|
879
|
+
testId,
|
|
880
|
+
light
|
|
832
881
|
} = this.props;
|
|
833
882
|
if (!description) {
|
|
834
883
|
return null;
|
|
835
884
|
}
|
|
836
885
|
return React__namespace.createElement(React__namespace.Fragment, null, React__namespace.createElement(wonderBlocksTypography.LabelSmall, {
|
|
837
|
-
style: styles$1.description,
|
|
886
|
+
style: light ? styles$1.lightDescription : styles$1.description,
|
|
838
887
|
testId: testId && `${testId}-description`
|
|
839
888
|
}, description), React__namespace.createElement(wonderBlocksLayout.Strut, {
|
|
840
889
|
size: wonderBlocksTokens.spacing.xxxSmall_4
|
|
@@ -844,7 +893,8 @@ class FieldHeading extends React__namespace.Component {
|
|
|
844
893
|
const {
|
|
845
894
|
error,
|
|
846
895
|
id,
|
|
847
|
-
testId
|
|
896
|
+
testId,
|
|
897
|
+
light
|
|
848
898
|
} = this.props;
|
|
849
899
|
if (!error) {
|
|
850
900
|
return null;
|
|
@@ -852,7 +902,7 @@ class FieldHeading extends React__namespace.Component {
|
|
|
852
902
|
return React__namespace.createElement(React__namespace.Fragment, null, React__namespace.createElement(wonderBlocksLayout.Strut, {
|
|
853
903
|
size: wonderBlocksTokens.spacing.small_12
|
|
854
904
|
}), React__namespace.createElement(wonderBlocksTypography.LabelSmall, {
|
|
855
|
-
style: styles$1.error,
|
|
905
|
+
style: light ? styles$1.lightError : styles$1.error,
|
|
856
906
|
role: "alert",
|
|
857
907
|
id: id && `${id}-error`,
|
|
858
908
|
testId: testId && `${testId}-error`
|
|
@@ -874,14 +924,26 @@ const styles$1 = aphrodite.StyleSheet.create({
|
|
|
874
924
|
label: {
|
|
875
925
|
color: wonderBlocksTokens.color.offBlack
|
|
876
926
|
},
|
|
927
|
+
lightLabel: {
|
|
928
|
+
color: wonderBlocksTokens.color.white
|
|
929
|
+
},
|
|
877
930
|
description: {
|
|
878
931
|
color: wonderBlocksTokens.color.offBlack64
|
|
879
932
|
},
|
|
933
|
+
lightDescription: {
|
|
934
|
+
color: wonderBlocksTokens.color.white64
|
|
935
|
+
},
|
|
880
936
|
error: {
|
|
881
937
|
color: wonderBlocksTokens.color.red
|
|
882
938
|
},
|
|
939
|
+
lightError: {
|
|
940
|
+
color: wonderBlocksTokens.color.fadedRed
|
|
941
|
+
},
|
|
883
942
|
required: {
|
|
884
943
|
color: wonderBlocksTokens.color.red
|
|
944
|
+
},
|
|
945
|
+
lightRequired: {
|
|
946
|
+
color: wonderBlocksTokens.color.fadedRed
|
|
885
947
|
}
|
|
886
948
|
});
|
|
887
949
|
|
|
@@ -960,6 +1022,7 @@ class LabeledTextField extends React__namespace.Component {
|
|
|
960
1022
|
id: uniqueId,
|
|
961
1023
|
testId: testId,
|
|
962
1024
|
style: style,
|
|
1025
|
+
light: light,
|
|
963
1026
|
field: React__namespace.createElement(TextField$1, _extends__default["default"]({
|
|
964
1027
|
id: `${uniqueId}-field`,
|
|
965
1028
|
"aria-describedby": ariaDescribedby ? ariaDescribedby : `${uniqueId}-error`,
|
|
@@ -1076,7 +1139,7 @@ const TextArea = React__namespace.forwardRef(function TextArea(props, ref) {
|
|
|
1076
1139
|
"data-testid": testId,
|
|
1077
1140
|
ref: ref,
|
|
1078
1141
|
className: className,
|
|
1079
|
-
style: [
|
|
1142
|
+
style: [getStyles(), style],
|
|
1080
1143
|
value: value,
|
|
1081
1144
|
onChange: handleChange,
|
|
1082
1145
|
placeholder: placeholder,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khanacademy/wonder-blocks-form",
|
|
3
|
-
"version": "4.9.
|
|
3
|
+
"version": "4.9.1",
|
|
4
4
|
"design": "v1",
|
|
5
5
|
"description": "Form components for Wonder Blocks.",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -16,12 +16,12 @@
|
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@babel/runtime": "^7.18.6",
|
|
19
|
-
"@khanacademy/wonder-blocks-clickable": "^4.2.
|
|
20
|
-
"@khanacademy/wonder-blocks-core": "^
|
|
21
|
-
"@khanacademy/wonder-blocks-icon": "^4.1.
|
|
22
|
-
"@khanacademy/wonder-blocks-layout": "^2.
|
|
19
|
+
"@khanacademy/wonder-blocks-clickable": "^4.2.7",
|
|
20
|
+
"@khanacademy/wonder-blocks-core": "^7.0.0",
|
|
21
|
+
"@khanacademy/wonder-blocks-icon": "^4.1.4",
|
|
22
|
+
"@khanacademy/wonder-blocks-layout": "^2.2.0",
|
|
23
23
|
"@khanacademy/wonder-blocks-tokens": "^2.0.0",
|
|
24
|
-
"@khanacademy/wonder-blocks-typography": "^2.1.
|
|
24
|
+
"@khanacademy/wonder-blocks-typography": "^2.1.15"
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
27
|
"aphrodite": "^1.2.5",
|
|
@@ -3,7 +3,6 @@ import {render, screen, fireEvent} from "@testing-library/react";
|
|
|
3
3
|
import {userEvent} from "@testing-library/user-event";
|
|
4
4
|
|
|
5
5
|
import {StyleSheet} from "aphrodite";
|
|
6
|
-
import {color} from "@khanacademy/wonder-blocks-tokens";
|
|
7
6
|
import LabeledTextField from "../labeled-text-field";
|
|
8
7
|
|
|
9
8
|
describe("LabeledTextField", () => {
|
|
@@ -382,28 +381,6 @@ describe("LabeledTextField", () => {
|
|
|
382
381
|
expect(input).toBeInTheDocument();
|
|
383
382
|
});
|
|
384
383
|
|
|
385
|
-
it("light prop is passed to textfield", async () => {
|
|
386
|
-
// Arrange
|
|
387
|
-
|
|
388
|
-
// Act
|
|
389
|
-
render(
|
|
390
|
-
<LabeledTextField
|
|
391
|
-
label="Label"
|
|
392
|
-
value=""
|
|
393
|
-
onChange={() => {}}
|
|
394
|
-
light={true}
|
|
395
|
-
/>,
|
|
396
|
-
);
|
|
397
|
-
|
|
398
|
-
const textField = await screen.findByRole("textbox");
|
|
399
|
-
textField.focus();
|
|
400
|
-
|
|
401
|
-
// Assert
|
|
402
|
-
expect(textField).toHaveStyle({
|
|
403
|
-
boxShadow: `0px 0px 0px 1px ${color.blue}, 0px 0px 0px 2px ${color.white}`,
|
|
404
|
-
});
|
|
405
|
-
});
|
|
406
|
-
|
|
407
384
|
it("style prop is passed to fieldheading", async () => {
|
|
408
385
|
// Arrange
|
|
409
386
|
const styles = StyleSheet.create({
|