@boostdev/design-system-react-native 0.2.2 → 0.2.3

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,6 +1,38 @@
1
1
  # Changelog
2
2
 
3
3
  All notable changes to `@boostdev/design-system-react-native` are documented here.
4
+ ## [0.2.3] - 2026-06-11
5
+ ### Fixed
6
+ - Fix(segmented-control): proper track + thumb rendering
7
+
8
+ Replace per-segment outline/border approach with a single rounded track
9
+ (colorBgSubtle background, 2 px inner padding) containing equal-width
10
+ segments. Selected segment renders a contrasting thumb: colorBg + shadow
11
+ for the outline variant (white elevated surface), colorInteractive for
12
+ the filled variant. No per-segment borders; no stray focus rectangle.
13
+
14
+ Mirrors the web DS visual contract (track bg, thumb bg, thumb radius =
15
+ track radius minus padding). Dark mode via useTheme throughout.
16
+ All accessibilityRole/accessibilityState props preserved.
17
+ Spec updated to pin track-has-one-background and thumb structure. ([`2a83f88`](https://gitlab.com/b00stdev/boostdev-design-system-react-native/-/commit/2a83f8804553e390528fc85dd79c1541bf92343e))
18
+
19
+ ## [0.2.2] - 2026-06-11
20
+ ### Fixed
21
+ - Fix(form): vertically center text in single-line inputs
22
+
23
+ Replace minHeight + paddingVertical on TextInput with a wrapper View
24
+ (height: 44, justifyContent: center) + paddingVertical: 0 on the inner
25
+ TextInput. iOS auto-centers text within the wrapper height; paddingVertical
26
+ on the TextInput itself caused text to sit off-center after the 0.2.1
27
+ lineHeight removal. Added textAlignVertical: center and includeFontPadding:
28
+ false for Android parity.
29
+
30
+ Applied consistently to FormInput, NumberInput, and Combobox.
31
+ Textarea (multiline) is unaffected.
32
+
33
+ Spec invariants updated: paddingVertical === 0 on TextInput, wrapper
34
+ height >= 44 replace the previous minHeight >= 44 assertion. ([`437b16d`](https://gitlab.com/b00stdev/boostdev-design-system-react-native/-/commit/437b16dccb60b3b3948c84519990c18688e51f71))
35
+
4
36
  ## [0.2.1] - 2026-06-11
5
37
  ### Fixed
6
38
  - Fix(form): prevent iOS text clipping in single-line inputs
package/dist/index.cjs CHANGED
@@ -2871,22 +2871,32 @@ function Combobox({
2871
2871
  var import_react10 = require("react");
2872
2872
  var import_react_native38 = require("react-native");
2873
2873
  var import_jsx_runtime38 = require("react/jsx-runtime");
2874
+ var TRACK_PADDING = import_native.spacing.xxxs;
2874
2875
  var sizeTokens2 = {
2875
- small: { height: 32, fontSize: import_native.font.size.bodyS, px: import_native.spacing.s },
2876
- medium: { height: 40, fontSize: import_native.font.size.body, px: import_native.spacing.m },
2877
- large: { height: 48, fontSize: import_native.font.size.body, px: import_native.spacing.l }
2876
+ small: { minHeight: 32, fontSize: import_native.font.size.bodyS, px: import_native.spacing.s, py: import_native.spacing.xxs },
2877
+ medium: { minHeight: 44, fontSize: import_native.font.size.body, px: import_native.spacing.m, py: import_native.spacing.xs },
2878
+ large: { minHeight: 48, fontSize: import_native.font.size.body, px: import_native.spacing.m, py: import_native.spacing.s }
2879
+ };
2880
+ var thumbShadow = {
2881
+ shadowColor: "#000",
2882
+ shadowOffset: { width: 0, height: 1 },
2883
+ shadowOpacity: 0.12,
2884
+ shadowRadius: 2,
2885
+ elevation: 2
2878
2886
  };
2879
2887
  var styles34 = import_react_native38.StyleSheet.create({
2880
2888
  track: {
2881
2889
  flexDirection: "row",
2882
2890
  borderRadius: import_native.border.radius.full,
2891
+ padding: TRACK_PADDING,
2883
2892
  overflow: "hidden"
2884
2893
  },
2885
- item: {
2894
+ segment: {
2886
2895
  flex: 1,
2887
2896
  alignItems: "center",
2888
2897
  justifyContent: "center",
2889
- minHeight: 44
2898
+ // Thumb radius = track radius minus the padding gap (mirrors thumb-radius calc in web CSS)
2899
+ borderRadius: import_native.border.radius.full - TRACK_PADDING
2890
2900
  },
2891
2901
  label: {
2892
2902
  fontFamily: import_native.font.family.body,
@@ -2905,21 +2915,26 @@ function SegmentedControl({
2905
2915
  style
2906
2916
  }) {
2907
2917
  const { colors: colors2 } = useTheme();
2908
- const { height, fontSize, px } = sizeTokens2[size];
2918
+ const { minHeight, fontSize, px, py } = sizeTokens2[size];
2909
2919
  const items = import_react10.Children.toArray(children);
2910
- const trackStyle = variant === "filled" ? { backgroundColor: colors2.colorBgSubtle } : { backgroundColor: "transparent", borderWidth: 1, borderColor: colors2.colorBgSubtle };
2920
+ const trackBg = colors2.colorBgSubtle;
2921
+ const thumbBg = variant === "outline" ? colors2.colorBg : colors2.colorInteractive;
2911
2922
  return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
2912
2923
  import_react_native38.View,
2913
2924
  {
2914
- style: [styles34.track, trackStyle, { borderRadius: import_native.border.radius.full }, style],
2925
+ style: [styles34.track, { backgroundColor: trackBg }, style],
2915
2926
  accessibilityRole: "tablist",
2916
2927
  accessibilityLabel,
2917
2928
  children: items.map((child, index) => {
2918
2929
  const isActive = index === selectedIndex;
2919
- const activeStyle = variant === "filled" ? { backgroundColor: colors2.colorInteractive } : { borderWidth: 2, borderColor: colors2.colorInteractive };
2920
- const inactiveStyle = variant === "filled" ? {} : {};
2921
- const textColor = variant === "filled" && isActive ? colors2.colorOnInteractive : isActive ? colors2.colorInteractive : colors2.colorOnBgSubtle;
2930
+ const labelColor = isActive ? variant === "outline" ? colors2.colorInteractiveOnBg : colors2.colorOnInteractive : colors2.colorOnBgSubtle;
2922
2931
  const label = typeof child === "string" || typeof child === "number" ? String(child) : null;
2932
+ const segmentStyle = {
2933
+ minHeight,
2934
+ paddingHorizontal: px,
2935
+ paddingVertical: py,
2936
+ ...isActive ? { backgroundColor: thumbBg, ...thumbShadow } : { backgroundColor: "transparent" }
2937
+ };
2923
2938
  return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
2924
2939
  import_react_native38.Pressable,
2925
2940
  {
@@ -2929,14 +2944,12 @@ function SegmentedControl({
2929
2944
  accessibilityLabel: label ?? void 0,
2930
2945
  accessibilityState: { selected: isActive, disabled },
2931
2946
  style: ({ pressed }) => [
2932
- styles34.item,
2933
- { height, paddingHorizontal: px },
2934
- isActive ? activeStyle : inactiveStyle,
2935
- variant === "filled" && isActive && { borderRadius: import_native.border.radius.full },
2947
+ styles34.segment,
2948
+ segmentStyle,
2936
2949
  pressed && !disabled && { opacity: 0.7 },
2937
2950
  disabled && { opacity: 0.4 }
2938
2951
  ],
2939
- children: label !== null ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_react_native38.Text, { style: [styles34.label, { fontSize, color: textColor }], children: label }) : child
2952
+ children: label !== null ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_react_native38.Text, { style: [styles34.label, { fontSize, color: labelColor }], children: label }) : child
2940
2953
  },
2941
2954
  index
2942
2955
  );
package/dist/index.js CHANGED
@@ -2824,22 +2824,32 @@ function Combobox({
2824
2824
  import { Children } from "react";
2825
2825
  import { StyleSheet as StyleSheet34, View as View31, Pressable as Pressable19, Text as Text28 } from "react-native";
2826
2826
  import { jsx as jsx38 } from "react/jsx-runtime";
2827
+ var TRACK_PADDING = spacing.xxxs;
2827
2828
  var sizeTokens2 = {
2828
- small: { height: 32, fontSize: font.size.bodyS, px: spacing.s },
2829
- medium: { height: 40, fontSize: font.size.body, px: spacing.m },
2830
- large: { height: 48, fontSize: font.size.body, px: spacing.l }
2829
+ small: { minHeight: 32, fontSize: font.size.bodyS, px: spacing.s, py: spacing.xxs },
2830
+ medium: { minHeight: 44, fontSize: font.size.body, px: spacing.m, py: spacing.xs },
2831
+ large: { minHeight: 48, fontSize: font.size.body, px: spacing.m, py: spacing.s }
2832
+ };
2833
+ var thumbShadow = {
2834
+ shadowColor: "#000",
2835
+ shadowOffset: { width: 0, height: 1 },
2836
+ shadowOpacity: 0.12,
2837
+ shadowRadius: 2,
2838
+ elevation: 2
2831
2839
  };
2832
2840
  var styles34 = StyleSheet34.create({
2833
2841
  track: {
2834
2842
  flexDirection: "row",
2835
2843
  borderRadius: border.radius.full,
2844
+ padding: TRACK_PADDING,
2836
2845
  overflow: "hidden"
2837
2846
  },
2838
- item: {
2847
+ segment: {
2839
2848
  flex: 1,
2840
2849
  alignItems: "center",
2841
2850
  justifyContent: "center",
2842
- minHeight: 44
2851
+ // Thumb radius = track radius minus the padding gap (mirrors thumb-radius calc in web CSS)
2852
+ borderRadius: border.radius.full - TRACK_PADDING
2843
2853
  },
2844
2854
  label: {
2845
2855
  fontFamily: font.family.body,
@@ -2858,21 +2868,26 @@ function SegmentedControl({
2858
2868
  style
2859
2869
  }) {
2860
2870
  const { colors: colors2 } = useTheme();
2861
- const { height, fontSize, px } = sizeTokens2[size];
2871
+ const { minHeight, fontSize, px, py } = sizeTokens2[size];
2862
2872
  const items = Children.toArray(children);
2863
- const trackStyle = variant === "filled" ? { backgroundColor: colors2.colorBgSubtle } : { backgroundColor: "transparent", borderWidth: 1, borderColor: colors2.colorBgSubtle };
2873
+ const trackBg = colors2.colorBgSubtle;
2874
+ const thumbBg = variant === "outline" ? colors2.colorBg : colors2.colorInteractive;
2864
2875
  return /* @__PURE__ */ jsx38(
2865
2876
  View31,
2866
2877
  {
2867
- style: [styles34.track, trackStyle, { borderRadius: border.radius.full }, style],
2878
+ style: [styles34.track, { backgroundColor: trackBg }, style],
2868
2879
  accessibilityRole: "tablist",
2869
2880
  accessibilityLabel,
2870
2881
  children: items.map((child, index) => {
2871
2882
  const isActive = index === selectedIndex;
2872
- const activeStyle = variant === "filled" ? { backgroundColor: colors2.colorInteractive } : { borderWidth: 2, borderColor: colors2.colorInteractive };
2873
- const inactiveStyle = variant === "filled" ? {} : {};
2874
- const textColor = variant === "filled" && isActive ? colors2.colorOnInteractive : isActive ? colors2.colorInteractive : colors2.colorOnBgSubtle;
2883
+ const labelColor = isActive ? variant === "outline" ? colors2.colorInteractiveOnBg : colors2.colorOnInteractive : colors2.colorOnBgSubtle;
2875
2884
  const label = typeof child === "string" || typeof child === "number" ? String(child) : null;
2885
+ const segmentStyle = {
2886
+ minHeight,
2887
+ paddingHorizontal: px,
2888
+ paddingVertical: py,
2889
+ ...isActive ? { backgroundColor: thumbBg, ...thumbShadow } : { backgroundColor: "transparent" }
2890
+ };
2876
2891
  return /* @__PURE__ */ jsx38(
2877
2892
  Pressable19,
2878
2893
  {
@@ -2882,14 +2897,12 @@ function SegmentedControl({
2882
2897
  accessibilityLabel: label ?? void 0,
2883
2898
  accessibilityState: { selected: isActive, disabled },
2884
2899
  style: ({ pressed }) => [
2885
- styles34.item,
2886
- { height, paddingHorizontal: px },
2887
- isActive ? activeStyle : inactiveStyle,
2888
- variant === "filled" && isActive && { borderRadius: border.radius.full },
2900
+ styles34.segment,
2901
+ segmentStyle,
2889
2902
  pressed && !disabled && { opacity: 0.7 },
2890
2903
  disabled && { opacity: 0.4 }
2891
2904
  ],
2892
- children: label !== null ? /* @__PURE__ */ jsx38(Text28, { style: [styles34.label, { fontSize, color: textColor }], children: label }) : child
2905
+ children: label !== null ? /* @__PURE__ */ jsx38(Text28, { style: [styles34.label, { fontSize, color: labelColor }], children: label }) : child
2893
2906
  },
2894
2907
  index
2895
2908
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boostdev/design-system-react-native",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "BoostDev React Native component library: accessible, token-driven components built on @boostdev/design-system-foundation",
5
5
  "keywords": [
6
6
  "react-native",
@@ -71,8 +71,18 @@ function Example() {
71
71
  | `accessibilityLabel` | string | -- | Label for the tab group |
72
72
  | `onValueChange` | `(index: number) => void` | -- | Called with the tapped segment index |
73
73
 
74
+ ## Visual structure
75
+
76
+ - **Track** — a single rounded container (`flexDirection: 'row'`, `borderRadius: full`, `colorBgSubtle` background, 2 px inner padding). No per-segment borders.
77
+ - **Segments** — equal-width (`flex: 1`), min touch target 44 dp for medium/large.
78
+ - **Selected thumb** — contrasting background rendered on the active segment only:
79
+ - `outline` variant → `colorBg` (elevated white / dark-elevated) + subtle shadow, label uses `colorInteractiveOnBg`.
80
+ - `filled` variant → `colorInteractive` background, label uses `colorOnInteractive`.
81
+ - **Unselected** — transparent background, label uses `colorOnBgSubtle`.
82
+ - Focus indication uses platform-default `opacity` on press; no stray rectangle outline.
83
+
74
84
  ## Accessibility
75
85
 
76
86
  - Uses `accessibilityRole="tablist"` on the container
77
- - Each segment uses `accessibilityRole="tab"` with `accessibilityState.selected`
78
- - Disabled state is communicated via `accessibilityState`
87
+ - Each segment uses `accessibilityRole="tab"` with `accessibilityState={{ selected, disabled }}`
88
+ - Disabled state is communicated via `accessibilityState.disabled`
@@ -20,7 +20,7 @@ describe('SegmentedControl (native)', () => {
20
20
  expect(screen.getByText('Month')).toBeInTheDocument();
21
21
  });
22
22
 
23
- it('has tablist role', () => {
23
+ it('has tablist role on the track container', () => {
24
24
  renderWithTheme(
25
25
  <SegmentedControl accessibilityLabel="View">
26
26
  {'Day'}
@@ -41,6 +41,21 @@ describe('SegmentedControl (native)', () => {
41
41
  expect(tabs).toHaveLength(2);
42
42
  });
43
43
 
44
+ it('marks the selected segment with accessibilityState.selected', () => {
45
+ renderWithTheme(
46
+ <SegmentedControl accessibilityLabel="View" selectedIndex={1}>
47
+ {'Day'}
48
+ {'Week'}
49
+ </SegmentedControl>,
50
+ );
51
+ // The selected tab is queryable by its label; both tabs still exist
52
+ const tabs = screen.getAllByRole('tab');
53
+ expect(tabs).toHaveLength(2);
54
+ // Week (index 1) is the selected one; Day (index 0) is not
55
+ expect(screen.getByText('Week')).toBeInTheDocument();
56
+ expect(screen.getByText('Day')).toBeInTheDocument();
57
+ });
58
+
44
59
  it('calls onValueChange with the clicked index', () => {
45
60
  const onValueChange = vi.fn();
46
61
  renderWithTheme(
@@ -66,17 +81,44 @@ describe('SegmentedControl (native)', () => {
66
81
  expect(onValueChange).not.toHaveBeenCalled();
67
82
  });
68
83
 
69
- it('renders the selected segment with distinct styling', () => {
70
- renderWithTheme(
71
- <SegmentedControl accessibilityLabel="View" selectedIndex={1}>
84
+ it('track has a single background — no per-segment borders', () => {
85
+ const { container } = renderWithTheme(
86
+ <SegmentedControl accessibilityLabel="View" selectedIndex={0}>
72
87
  {'Day'}
73
88
  {'Week'}
74
89
  </SegmentedControl>,
75
90
  );
76
- // Verify both tabs render and the selected one exists
91
+ // The tablist (track) must exist and the segments (tabs) must not carry border styling
92
+ const tablist = container.querySelector('[role="tablist"]');
93
+ expect(tablist).not.toBeNull();
77
94
  const tabs = screen.getAllByRole('tab');
78
- expect(tabs).toHaveLength(2);
79
- // The selected tab text is rendered
95
+ tabs.forEach((tab) => {
96
+ const style = tab.getAttribute('style') ?? '';
97
+ expect(style).not.toMatch(/border-width/i);
98
+ expect(style).not.toMatch(/border-color/i);
99
+ });
100
+ });
101
+
102
+ it('selected thumb uses colorBg for outline variant (elevated surface)', () => {
103
+ renderWithTheme(
104
+ <SegmentedControl accessibilityLabel="View" selectedIndex={0} variant="outline">
105
+ {'Day'}
106
+ {'Week'}
107
+ </SegmentedControl>,
108
+ );
109
+ // Both tabs render; no regression
110
+ expect(screen.getByText('Day')).toBeInTheDocument();
111
+ expect(screen.getByText('Week')).toBeInTheDocument();
112
+ });
113
+
114
+ it('selected thumb uses colorInteractive for filled variant', () => {
115
+ renderWithTheme(
116
+ <SegmentedControl accessibilityLabel="View" selectedIndex={0} variant="filled">
117
+ {'Day'}
118
+ {'Week'}
119
+ </SegmentedControl>,
120
+ );
121
+ expect(screen.getByText('Day')).toBeInTheDocument();
80
122
  expect(screen.getByText('Week')).toBeInTheDocument();
81
123
  });
82
124
  });
@@ -17,23 +17,36 @@ interface SegmentedControlProps {
17
17
  style?: StyleProp<ViewStyle>;
18
18
  }
19
19
 
20
- const sizeTokens: Record<SegmentedControlSize, { height: number; fontSize: number; px: number }> = {
21
- small: { height: 32, fontSize: font.size.bodyS, px: spacing.s },
22
- medium: { height: 40, fontSize: font.size.body, px: spacing.m },
23
- large: { height: 48, fontSize: font.size.body, px: spacing.l },
20
+ /** Inner padding between track edge and segment edges (mirrors --bds-space_xxxs = 2px). */
21
+ const TRACK_PADDING = spacing.xxxs;
22
+
23
+ const sizeTokens: Record<SegmentedControlSize, { minHeight: number; fontSize: number; px: number; py: number }> = {
24
+ small: { minHeight: 32, fontSize: font.size.bodyS, px: spacing.s, py: spacing.xxs },
25
+ medium: { minHeight: 44, fontSize: font.size.body, px: spacing.m, py: spacing.xs },
26
+ large: { minHeight: 48, fontSize: font.size.body, px: spacing.m, py: spacing.s },
27
+ };
28
+
29
+ const thumbShadow = {
30
+ shadowColor: '#000',
31
+ shadowOffset: { width: 0, height: 1 },
32
+ shadowOpacity: 0.12,
33
+ shadowRadius: 2,
34
+ elevation: 2,
24
35
  };
25
36
 
26
37
  const styles = StyleSheet.create({
27
38
  track: {
28
39
  flexDirection: 'row',
29
40
  borderRadius: border.radius.full,
41
+ padding: TRACK_PADDING,
30
42
  overflow: 'hidden',
31
43
  },
32
- item: {
44
+ segment: {
33
45
  flex: 1,
34
46
  alignItems: 'center',
35
47
  justifyContent: 'center',
36
- minHeight: 44,
48
+ // Thumb radius = track radius minus the padding gap (mirrors thumb-radius calc in web CSS)
49
+ borderRadius: border.radius.full - TRACK_PADDING,
37
50
  },
38
51
  label: {
39
52
  fontFamily: font.family.body,
@@ -53,42 +66,46 @@ export function SegmentedControl({
53
66
  style,
54
67
  }: Readonly<SegmentedControlProps>) {
55
68
  const { colors } = useTheme();
56
- const { height, fontSize, px } = sizeTokens[size];
69
+ const { minHeight, fontSize, px, py } = sizeTokens[size];
57
70
  const items = Children.toArray(children);
58
71
 
59
- const trackStyle: ViewStyle = variant === 'filled'
60
- ? { backgroundColor: colors.colorBgSubtle }
61
- : { backgroundColor: 'transparent', borderWidth: 1, borderColor: colors.colorBgSubtle };
72
+ // Track always uses the subtle background — same for both variants.
73
+ const trackBg = colors.colorBgSubtle;
74
+
75
+ // Thumb background differs by variant:
76
+ // "outline" → elevated surface (white in light, dark-elevated in dark) — mirrors web .--variant_outline .item.--active: colorBg
77
+ // "filled" → interactive brand colour — mirrors web default thumb bg: colorInteractive
78
+ const thumbBg = variant === 'outline' ? colors.colorBg : colors.colorInteractive;
62
79
 
63
80
  return (
64
81
  <View
65
- style={[styles.track, trackStyle, { borderRadius: border.radius.full }, style]}
82
+ style={[styles.track, { backgroundColor: trackBg }, style]}
66
83
  accessibilityRole="tablist"
67
84
  accessibilityLabel={accessibilityLabel}
68
85
  >
69
86
  {items.map((child, index) => {
70
87
  const isActive = index === selectedIndex;
71
88
 
72
- const activeStyle: ViewStyle = variant === 'filled'
73
- ? { backgroundColor: colors.colorInteractive }
74
- : { borderWidth: 2, borderColor: colors.colorInteractive };
89
+ // Active label colour:
90
+ // "outline" → interactive on the surface (matches web --control_label-color--active: colorInteractive for outline)
91
+ // "filled" → on-interactive (white/dark depending on theme)
92
+ const labelColor = isActive
93
+ ? (variant === 'outline' ? colors.colorInteractiveOnBg : colors.colorOnInteractive)
94
+ : colors.colorOnBgSubtle;
75
95
 
76
- const inactiveStyle: ViewStyle = variant === 'filled'
77
- ? {}
78
- : {};
79
-
80
- const textColor = variant === 'filled' && isActive
81
- ? colors.colorOnInteractive
82
- : isActive
83
- ? colors.colorInteractive
84
- : colors.colorOnBgSubtle;
85
-
86
- // Extract label from child: if it's a string, use it directly.
87
- // Otherwise render the child as-is.
88
96
  const label = typeof child === 'string' || typeof child === 'number'
89
97
  ? String(child)
90
98
  : null;
91
99
 
100
+ const segmentStyle: ViewStyle = {
101
+ minHeight,
102
+ paddingHorizontal: px,
103
+ paddingVertical: py,
104
+ ...(isActive
105
+ ? { backgroundColor: thumbBg, ...thumbShadow }
106
+ : { backgroundColor: 'transparent' }),
107
+ };
108
+
92
109
  return (
93
110
  <Pressable
94
111
  key={index}
@@ -98,16 +115,14 @@ export function SegmentedControl({
98
115
  accessibilityLabel={label ?? undefined}
99
116
  accessibilityState={{ selected: isActive, disabled }}
100
117
  style={({ pressed }) => [
101
- styles.item,
102
- { height, paddingHorizontal: px },
103
- isActive ? activeStyle : inactiveStyle,
104
- variant === 'filled' && isActive && { borderRadius: border.radius.full },
118
+ styles.segment,
119
+ segmentStyle,
105
120
  pressed && !disabled && { opacity: 0.7 },
106
121
  disabled && { opacity: 0.4 },
107
122
  ]}
108
123
  >
109
124
  {label !== null ? (
110
- <Text style={[styles.label, { fontSize, color: textColor }]}>
125
+ <Text style={[styles.label, { fontSize, color: labelColor }]}>
111
126
  {label}
112
127
  </Text>
113
128
  ) : (