@scripso-homepad/ui 0.3.7 → 0.3.9
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/README.md +7 -2
- package/dist/index.cjs +152 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -4
- package/dist/index.d.ts +10 -4
- package/dist/index.js +153 -45
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Button.tsx +11 -2
- package/src/components/Input.stories.tsx +9 -0
- package/src/components/Input.tsx +60 -5
- package/src/components/PhoneInput.tsx +2 -2
- package/src/icons/EyeIcon.tsx +25 -37
- package/src/icons/EyeIcon.web.tsx +42 -0
- package/src/icons/EyeOffIcon.tsx +29 -0
- package/src/icons/EyeOffIcon.web.tsx +35 -0
- package/src/icons/eyeIconPaths.ts +8 -0
- package/src/theme/input.ts +29 -14
- package/src/theme/tokens.ts +3 -3
package/src/components/Input.tsx
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
type ReactNode,
|
|
8
8
|
} from "react";
|
|
9
9
|
import {
|
|
10
|
+
Pressable,
|
|
10
11
|
StyleSheet,
|
|
11
12
|
Text,
|
|
12
13
|
TextInput,
|
|
@@ -18,6 +19,8 @@ import {
|
|
|
18
19
|
type TextStyle,
|
|
19
20
|
type ViewStyle,
|
|
20
21
|
} from "react-native";
|
|
22
|
+
import { EyeIcon } from "../icons/EyeIcon";
|
|
23
|
+
import { EyeOffIcon } from "../icons/EyeOffIcon";
|
|
21
24
|
import {
|
|
22
25
|
getInputFieldStyles,
|
|
23
26
|
inputFieldMetrics,
|
|
@@ -58,10 +61,16 @@ export interface InputProps extends TextInputProps {
|
|
|
58
61
|
containerStyle?: StyleProp<ViewStyle>;
|
|
59
62
|
style?: StyleProp<TextStyle>;
|
|
60
63
|
className?: string;
|
|
64
|
+
/** CSS classes for the bordered field container (web). */
|
|
65
|
+
fieldClassName?: string;
|
|
66
|
+
/** Styles merged into the bordered field container. */
|
|
67
|
+
fieldStyle?: StyleProp<ViewStyle>;
|
|
61
68
|
labelClassName?: string;
|
|
62
69
|
inputClassName?: string;
|
|
63
70
|
errorClassName?: string;
|
|
64
71
|
hintClassName?: string;
|
|
72
|
+
/** When `secureTextEntry` is set, show a toggleable eye icon. Pass `false` to disable. */
|
|
73
|
+
showPasswordToggle?: boolean;
|
|
65
74
|
}
|
|
66
75
|
|
|
67
76
|
export function Input({
|
|
@@ -73,25 +82,37 @@ export function Input({
|
|
|
73
82
|
containerStyle,
|
|
74
83
|
style,
|
|
75
84
|
className,
|
|
85
|
+
fieldClassName,
|
|
86
|
+
fieldStyle,
|
|
76
87
|
labelClassName,
|
|
77
88
|
inputClassName,
|
|
78
89
|
errorClassName,
|
|
79
90
|
hintClassName,
|
|
80
91
|
editable = true,
|
|
92
|
+
secureTextEntry,
|
|
93
|
+
showPasswordToggle,
|
|
81
94
|
onFocus,
|
|
82
95
|
onBlur,
|
|
83
96
|
...props
|
|
84
97
|
}: InputProps) {
|
|
85
98
|
const wrapperRef = useRef<ComponentRef<typeof View>>(null);
|
|
99
|
+
const fieldRef = useRef<ComponentRef<typeof View>>(null);
|
|
86
100
|
const inputRef = useRef<ComponentRef<typeof TextInput>>(null);
|
|
87
101
|
const helperRef = useRef<ComponentRef<typeof Text>>(null);
|
|
88
102
|
const [focused, setFocused] = useState(false);
|
|
103
|
+
const [passwordVisible, setPasswordVisible] = useState(false);
|
|
89
104
|
|
|
90
105
|
useApplyWebClassName(wrapperRef, className);
|
|
106
|
+
useApplyWebClassName(fieldRef, fieldClassName);
|
|
91
107
|
useApplyWebClassName(inputRef, inputClassName);
|
|
92
108
|
useApplyWebClassName(helperRef, error ? errorClassName : hintClassName);
|
|
93
109
|
|
|
94
110
|
const isDisabled = editable === false;
|
|
111
|
+
const passwordToggleEnabled =
|
|
112
|
+
secureTextEntry === true && showPasswordToggle !== false && rightIcon == null;
|
|
113
|
+
const effectiveSecureTextEntry = passwordToggleEnabled
|
|
114
|
+
? !passwordVisible
|
|
115
|
+
: secureTextEntry;
|
|
95
116
|
const visualState = resolveInputVisualState({
|
|
96
117
|
focused,
|
|
97
118
|
error: Boolean(error),
|
|
@@ -112,6 +133,30 @@ export function Input({
|
|
|
112
133
|
|
|
113
134
|
const helperMessage = error ?? hint;
|
|
114
135
|
|
|
136
|
+
function togglePasswordVisibility() {
|
|
137
|
+
if (!isDisabled) {
|
|
138
|
+
setPasswordVisible((visible) => !visible);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const trailingIcon = passwordToggleEnabled ? (
|
|
143
|
+
<Pressable
|
|
144
|
+
onPress={togglePasswordVisibility}
|
|
145
|
+
disabled={isDisabled}
|
|
146
|
+
accessibilityRole="button"
|
|
147
|
+
accessibilityLabel={passwordVisible ? "Hide password" : "Show password"}
|
|
148
|
+
hitSlop={8}
|
|
149
|
+
style={styles.iconPressable}
|
|
150
|
+
>
|
|
151
|
+
{renderInputIcon(
|
|
152
|
+
passwordVisible ? <EyeOffIcon /> : <EyeIcon />,
|
|
153
|
+
iconColor,
|
|
154
|
+
)}
|
|
155
|
+
</Pressable>
|
|
156
|
+
) : rightIcon ? (
|
|
157
|
+
renderInputIcon(rightIcon, iconColor)
|
|
158
|
+
) : null;
|
|
159
|
+
|
|
115
160
|
return (
|
|
116
161
|
<View ref={wrapperRef} style={[styles.wrapper, containerStyle]}>
|
|
117
162
|
{label ? (
|
|
@@ -120,7 +165,10 @@ export function Input({
|
|
|
120
165
|
</Label>
|
|
121
166
|
) : null}
|
|
122
167
|
<View style={fieldStyles.outline}>
|
|
123
|
-
<View
|
|
168
|
+
<View
|
|
169
|
+
ref={fieldRef}
|
|
170
|
+
style={[inputFieldMetrics.container, fieldStyles.container, fieldStyle]}
|
|
171
|
+
>
|
|
124
172
|
{leftIcon ? (
|
|
125
173
|
<View style={styles.iconSlot}>{renderInputIcon(leftIcon, iconColor)}</View>
|
|
126
174
|
) : null}
|
|
@@ -133,13 +181,14 @@ export function Input({
|
|
|
133
181
|
]}
|
|
134
182
|
placeholderTextColor={fieldStyles.placeholder}
|
|
135
183
|
editable={editable}
|
|
184
|
+
secureTextEntry={effectiveSecureTextEntry}
|
|
136
185
|
onFocus={handleFocus}
|
|
137
186
|
onBlur={handleBlur}
|
|
138
187
|
accessibilityState={{ disabled: isDisabled }}
|
|
139
188
|
{...props}
|
|
140
189
|
/>
|
|
141
|
-
{
|
|
142
|
-
<View style={styles.iconSlot}>{
|
|
190
|
+
{trailingIcon ? (
|
|
191
|
+
<View style={styles.iconSlot}>{trailingIcon}</View>
|
|
143
192
|
) : null}
|
|
144
193
|
</View>
|
|
145
194
|
</View>
|
|
@@ -164,14 +213,20 @@ const styles = StyleSheet.create({
|
|
|
164
213
|
justifyContent: "center",
|
|
165
214
|
flexShrink: 0,
|
|
166
215
|
},
|
|
216
|
+
iconPressable: {
|
|
217
|
+
width: INPUT_ICON_SIZE,
|
|
218
|
+
height: INPUT_ICON_SIZE,
|
|
219
|
+
alignItems: "center",
|
|
220
|
+
justifyContent: "center",
|
|
221
|
+
},
|
|
167
222
|
error: {
|
|
168
223
|
fontSize: 12,
|
|
169
|
-
lineHeight:
|
|
224
|
+
lineHeight: 16,
|
|
170
225
|
color: colors.inputError,
|
|
171
226
|
},
|
|
172
227
|
hint: {
|
|
173
228
|
fontSize: 12,
|
|
174
|
-
lineHeight:
|
|
229
|
+
lineHeight: 16,
|
|
175
230
|
color: colors.stormGray300,
|
|
176
231
|
},
|
|
177
232
|
});
|
|
@@ -161,12 +161,12 @@ const styles = StyleSheet.create({
|
|
|
161
161
|
},
|
|
162
162
|
error: {
|
|
163
163
|
fontSize: 12,
|
|
164
|
-
lineHeight:
|
|
164
|
+
lineHeight: 16,
|
|
165
165
|
color: colors.inputError,
|
|
166
166
|
},
|
|
167
167
|
hint: {
|
|
168
168
|
fontSize: 12,
|
|
169
|
-
lineHeight:
|
|
169
|
+
lineHeight: 16,
|
|
170
170
|
color: colors.stormGray300,
|
|
171
171
|
},
|
|
172
172
|
});
|
package/src/icons/EyeIcon.tsx
CHANGED
|
@@ -1,48 +1,36 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import Svg, { Path } from "react-native-svg";
|
|
2
|
+
import { EYE_OPEN_OUTLINE_PATH, EYE_OPEN_PUPIL_PATH } from "./eyeIconPaths";
|
|
3
|
+
|
|
4
|
+
export { EYE_OPEN_OUTLINE_PATH, EYE_OPEN_PUPIL_PATH } from "./eyeIconPaths";
|
|
2
5
|
|
|
3
6
|
interface EyeIconProps {
|
|
4
7
|
size?: number;
|
|
5
8
|
color?: string;
|
|
9
|
+
strokeWidth?: number;
|
|
6
10
|
}
|
|
7
11
|
|
|
8
|
-
/**
|
|
9
|
-
export function EyeIcon({
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
/** Native — open eye (password hidden). */
|
|
13
|
+
export function EyeIcon({
|
|
14
|
+
size = 20,
|
|
15
|
+
color = "#c7cdd1",
|
|
16
|
+
strokeWidth = 2,
|
|
17
|
+
}: EyeIconProps) {
|
|
14
18
|
return (
|
|
15
|
-
<
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
height: eyeHeight,
|
|
23
|
-
borderRadius: eyeHeight / 2,
|
|
24
|
-
borderWidth: stroke,
|
|
25
|
-
borderColor: color,
|
|
26
|
-
}}
|
|
19
|
+
<Svg width={size} height={size} viewBox="0 0 20 20" fill="none">
|
|
20
|
+
<Path
|
|
21
|
+
d={EYE_OPEN_OUTLINE_PATH}
|
|
22
|
+
stroke={color}
|
|
23
|
+
strokeWidth={strokeWidth}
|
|
24
|
+
strokeLinecap="round"
|
|
25
|
+
strokeLinejoin="round"
|
|
27
26
|
/>
|
|
28
|
-
<
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
height: size * 0.28,
|
|
35
|
-
borderRadius: size * 0.14,
|
|
36
|
-
borderWidth: stroke,
|
|
37
|
-
borderColor: color,
|
|
38
|
-
}}
|
|
27
|
+
<Path
|
|
28
|
+
d={EYE_OPEN_PUPIL_PATH}
|
|
29
|
+
stroke={color}
|
|
30
|
+
strokeWidth={strokeWidth}
|
|
31
|
+
strokeLinecap="round"
|
|
32
|
+
strokeLinejoin="round"
|
|
39
33
|
/>
|
|
40
|
-
</
|
|
34
|
+
</Svg>
|
|
41
35
|
);
|
|
42
36
|
}
|
|
43
|
-
|
|
44
|
-
const styles = StyleSheet.create({
|
|
45
|
-
root: {
|
|
46
|
-
position: "relative",
|
|
47
|
-
},
|
|
48
|
-
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { EYE_OPEN_OUTLINE_PATH, EYE_OPEN_PUPIL_PATH } from "./eyeIconPaths";
|
|
2
|
+
|
|
3
|
+
interface EyeIconProps {
|
|
4
|
+
size?: number;
|
|
5
|
+
color?: string;
|
|
6
|
+
strokeWidth?: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Web — open eye (password hidden). */
|
|
10
|
+
export function EyeIcon({
|
|
11
|
+
size = 20,
|
|
12
|
+
color = "#c7cdd1",
|
|
13
|
+
strokeWidth = 2,
|
|
14
|
+
}: EyeIconProps) {
|
|
15
|
+
return (
|
|
16
|
+
<svg
|
|
17
|
+
width={size}
|
|
18
|
+
height={size}
|
|
19
|
+
viewBox="0 0 20 20"
|
|
20
|
+
fill="none"
|
|
21
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
22
|
+
aria-hidden
|
|
23
|
+
>
|
|
24
|
+
<path
|
|
25
|
+
d={EYE_OPEN_OUTLINE_PATH}
|
|
26
|
+
stroke={color}
|
|
27
|
+
strokeWidth={strokeWidth}
|
|
28
|
+
strokeLinecap="round"
|
|
29
|
+
strokeLinejoin="round"
|
|
30
|
+
/>
|
|
31
|
+
<path
|
|
32
|
+
d={EYE_OPEN_PUPIL_PATH}
|
|
33
|
+
stroke={color}
|
|
34
|
+
strokeWidth={strokeWidth}
|
|
35
|
+
strokeLinecap="round"
|
|
36
|
+
strokeLinejoin="round"
|
|
37
|
+
/>
|
|
38
|
+
</svg>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export { EYE_OPEN_OUTLINE_PATH, EYE_OPEN_PUPIL_PATH } from "./eyeIconPaths";
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import Svg, { Path } from "react-native-svg";
|
|
2
|
+
import { EYE_OFF_PATH } from "./eyeIconPaths";
|
|
3
|
+
|
|
4
|
+
export { EYE_OFF_PATH } from "./eyeIconPaths";
|
|
5
|
+
|
|
6
|
+
interface EyeOffIconProps {
|
|
7
|
+
size?: number;
|
|
8
|
+
color?: string;
|
|
9
|
+
strokeWidth?: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Native — slashed eye (password visible). */
|
|
13
|
+
export function EyeOffIcon({
|
|
14
|
+
size = 20,
|
|
15
|
+
color = "#c7cdd1",
|
|
16
|
+
strokeWidth = 2,
|
|
17
|
+
}: EyeOffIconProps) {
|
|
18
|
+
return (
|
|
19
|
+
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
20
|
+
<Path
|
|
21
|
+
d={EYE_OFF_PATH}
|
|
22
|
+
stroke={color}
|
|
23
|
+
strokeWidth={strokeWidth}
|
|
24
|
+
strokeLinecap="round"
|
|
25
|
+
strokeLinejoin="round"
|
|
26
|
+
/>
|
|
27
|
+
</Svg>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { EYE_OFF_PATH } from "./eyeIconPaths";
|
|
2
|
+
|
|
3
|
+
interface EyeOffIconProps {
|
|
4
|
+
size?: number;
|
|
5
|
+
color?: string;
|
|
6
|
+
strokeWidth?: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Web — slashed eye (password visible). */
|
|
10
|
+
export function EyeOffIcon({
|
|
11
|
+
size = 20,
|
|
12
|
+
color = "#c7cdd1",
|
|
13
|
+
strokeWidth = 2,
|
|
14
|
+
}: EyeOffIconProps) {
|
|
15
|
+
return (
|
|
16
|
+
<svg
|
|
17
|
+
width={size}
|
|
18
|
+
height={size}
|
|
19
|
+
viewBox="0 0 24 24"
|
|
20
|
+
fill="none"
|
|
21
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
22
|
+
aria-hidden
|
|
23
|
+
>
|
|
24
|
+
<path
|
|
25
|
+
d={EYE_OFF_PATH}
|
|
26
|
+
stroke={color}
|
|
27
|
+
strokeWidth={strokeWidth}
|
|
28
|
+
strokeLinecap="round"
|
|
29
|
+
strokeLinejoin="round"
|
|
30
|
+
/>
|
|
31
|
+
</svg>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export { EYE_OFF_PATH } from "./eyeIconPaths";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export const EYE_OPEN_OUTLINE_PATH =
|
|
2
|
+
"M1.71835 10.2898C1.6489 10.1027 1.6489 9.89691 1.71835 9.70981C2.39476 8.06969 3.54294 6.66735 5.01732 5.68056C6.4917 4.69378 8.22588 4.16699 10 4.16699C11.7741 4.16699 13.5083 4.69378 14.9827 5.68056C16.4571 6.66735 17.6053 8.06969 18.2817 9.70981C18.3511 9.89691 18.3511 10.1027 18.2817 10.2898C17.6053 11.9299 16.4571 13.3323 14.9827 14.3191C13.5083 15.3058 11.7741 15.8326 10 15.8326C8.22588 15.8326 6.4917 15.3058 5.01732 14.3191C3.54294 13.3323 2.39476 11.9299 1.71835 10.2898Z";
|
|
3
|
+
|
|
4
|
+
export const EYE_OPEN_PUPIL_PATH =
|
|
5
|
+
"M10 12.4998C11.3807 12.4998 12.5 11.3805 12.5 9.99981C12.5 8.6191 11.3807 7.49981 10 7.49981C8.6193 7.49981 7.50001 8.6191 7.50001 9.99981C7.50001 11.3805 8.6193 12.4998 10 12.4998Z";
|
|
6
|
+
|
|
7
|
+
export const EYE_OFF_PATH =
|
|
8
|
+
"M10.733 5.076C13.0624 4.7984 15.4186 5.29082 17.4419 6.47805C19.4651 7.66528 21.0442 9.48208 21.938 11.651C22.0213 11.8755 22.0213 12.1225 21.938 12.347C21.5705 13.238 21.0848 14.0755 20.494 14.837M14.084 14.158C13.5182 14.7045 12.7604 15.0069 11.9738 15C11.1872 14.9932 10.4348 14.6777 9.87854 14.1215C9.32232 13.5652 9.00681 12.8128 8.99998 12.0262C8.99314 11.2396 9.29553 10.4818 9.842 9.916M17.479 17.499C16.1525 18.2848 14.6725 18.776 13.1394 18.9394C11.6063 19.1028 10.056 18.9345 8.59363 18.4459C7.13131 17.9573 5.79119 17.1599 4.66421 16.1077C3.53723 15.0556 2.64975 13.7734 2.062 12.348C1.97866 12.1235 1.97866 11.8765 2.062 11.652C2.94863 9.50186 4.50867 7.69725 6.508 6.509M2 2L22 22";
|
package/src/theme/input.ts
CHANGED
|
@@ -37,18 +37,33 @@ interface FieldStyleSet {
|
|
|
37
37
|
icon: string;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
function createOutlineStyle(ringColor: string): ViewStyle {
|
|
41
|
+
return {
|
|
42
42
|
borderRadius: radii.lg + INPUT_OUTLINE_WIDTH,
|
|
43
|
-
|
|
43
|
+
borderWidth: INPUT_OUTLINE_WIDTH,
|
|
44
|
+
borderColor: ringColor,
|
|
45
|
+
padding: 0,
|
|
44
46
|
backgroundColor: colors.transparent,
|
|
47
|
+
width: "100%",
|
|
48
|
+
alignSelf: "stretch",
|
|
49
|
+
...(Platform.OS !== "web" ? { overflow: "hidden" as const } : null),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const defaultOutline = createOutlineStyle(colors.transparent);
|
|
54
|
+
|
|
55
|
+
export function getInputFieldStyles(state: InputVisualState): FieldStyleSet {
|
|
56
|
+
const containerBase: ViewStyle = {
|
|
57
|
+
borderRadius: radii.lg,
|
|
58
|
+
...(Platform.OS !== "web" ? { overflow: "hidden" as const } : null),
|
|
45
59
|
};
|
|
46
60
|
|
|
47
61
|
switch (state) {
|
|
48
62
|
case "disabled":
|
|
49
63
|
return {
|
|
50
|
-
outline:
|
|
64
|
+
outline: defaultOutline,
|
|
51
65
|
container: {
|
|
66
|
+
...containerBase,
|
|
52
67
|
borderWidth: 1,
|
|
53
68
|
borderColor: colors.stormGray50,
|
|
54
69
|
backgroundColor: colors.stormGray50,
|
|
@@ -59,11 +74,9 @@ export function getInputFieldStyles(state: InputVisualState): FieldStyleSet {
|
|
|
59
74
|
};
|
|
60
75
|
case "error":
|
|
61
76
|
return {
|
|
62
|
-
outline:
|
|
63
|
-
...outlineBase,
|
|
64
|
-
backgroundColor: colors.inputOutlineError,
|
|
65
|
-
},
|
|
77
|
+
outline: createOutlineStyle(colors.inputOutlineError),
|
|
66
78
|
container: {
|
|
79
|
+
...containerBase,
|
|
67
80
|
borderWidth: 1,
|
|
68
81
|
borderColor: colors.inputError,
|
|
69
82
|
backgroundColor: colors.white,
|
|
@@ -74,11 +87,9 @@ export function getInputFieldStyles(state: InputVisualState): FieldStyleSet {
|
|
|
74
87
|
};
|
|
75
88
|
case "focused":
|
|
76
89
|
return {
|
|
77
|
-
outline:
|
|
78
|
-
...outlineBase,
|
|
79
|
-
backgroundColor: colors.inputOutlineFocus,
|
|
80
|
-
},
|
|
90
|
+
outline: createOutlineStyle(colors.inputOutlineFocus),
|
|
81
91
|
container: {
|
|
92
|
+
...containerBase,
|
|
82
93
|
borderWidth: 1,
|
|
83
94
|
borderColor: colors.navy,
|
|
84
95
|
backgroundColor: colors.white,
|
|
@@ -89,8 +100,9 @@ export function getInputFieldStyles(state: InputVisualState): FieldStyleSet {
|
|
|
89
100
|
};
|
|
90
101
|
default:
|
|
91
102
|
return {
|
|
92
|
-
outline:
|
|
103
|
+
outline: defaultOutline,
|
|
93
104
|
container: {
|
|
105
|
+
...containerBase,
|
|
94
106
|
borderWidth: 1,
|
|
95
107
|
borderColor: colors.stormGray50,
|
|
96
108
|
backgroundColor: colors.white,
|
|
@@ -122,12 +134,15 @@ export const inputFieldMetrics = StyleSheet.create({
|
|
|
122
134
|
fontFamily: fonts.sans,
|
|
123
135
|
fontSize: fontSize.md,
|
|
124
136
|
fontWeight: fontWeight.medium,
|
|
125
|
-
lineHeight: fontSize.md,
|
|
137
|
+
lineHeight: Platform.OS === "web" ? fontSize.md : 20,
|
|
126
138
|
paddingVertical: 0,
|
|
127
139
|
paddingHorizontal: 0,
|
|
128
140
|
margin: 0,
|
|
129
141
|
borderWidth: 0,
|
|
130
142
|
backgroundColor: colors.transparent,
|
|
143
|
+
...(Platform.OS === "android"
|
|
144
|
+
? { includeFontPadding: false }
|
|
145
|
+
: null),
|
|
131
146
|
...(Platform.OS === "web"
|
|
132
147
|
? ({
|
|
133
148
|
height: "100%",
|
package/src/theme/tokens.ts
CHANGED
|
@@ -236,20 +236,20 @@ export const labelTypography = {
|
|
|
236
236
|
letterSpacing: 0,
|
|
237
237
|
} as const;
|
|
238
238
|
|
|
239
|
-
/** Button label typography —
|
|
239
|
+
/** Button label typography — SemiBold; line-height slightly above 100% for RN clipping. */
|
|
240
240
|
export const buttonTypography = {
|
|
241
241
|
lg: {
|
|
242
242
|
fontFamily: fonts.sans,
|
|
243
243
|
fontSize: 14,
|
|
244
244
|
fontWeight: fontWeight.semibold,
|
|
245
|
-
lineHeight:
|
|
245
|
+
lineHeight: 18,
|
|
246
246
|
letterSpacing: 0,
|
|
247
247
|
},
|
|
248
248
|
sm: {
|
|
249
249
|
fontFamily: fonts.sans,
|
|
250
250
|
fontSize: 12,
|
|
251
251
|
fontWeight: fontWeight.semibold,
|
|
252
|
-
lineHeight:
|
|
252
|
+
lineHeight: 16,
|
|
253
253
|
letterSpacing: 0,
|
|
254
254
|
},
|
|
255
255
|
} as const;
|