@idealyst/components 1.1.6 → 1.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/package.json +8 -3
  2. package/src/Accordion/Accordion.native.tsx +22 -14
  3. package/src/Accordion/Accordion.styles.old.tsx +298 -0
  4. package/src/Accordion/Accordion.styles.tsx +139 -248
  5. package/src/Accordion/Accordion.web.tsx +12 -7
  6. package/src/ActivityIndicator/ActivityIndicator.native.tsx +3 -2
  7. package/src/ActivityIndicator/ActivityIndicator.styles.old.tsx +94 -0
  8. package/src/ActivityIndicator/ActivityIndicator.styles.tsx +43 -62
  9. package/src/ActivityIndicator/ActivityIndicator.web.tsx +2 -2
  10. package/src/Alert/Alert.native.tsx +26 -15
  11. package/src/Alert/Alert.styles.old.tsx +209 -0
  12. package/src/Alert/Alert.styles.tsx +108 -281
  13. package/src/Alert/Alert.web.tsx +6 -10
  14. package/src/Avatar/Avatar.native.tsx +5 -2
  15. package/src/Avatar/Avatar.styles.old.tsx +99 -0
  16. package/src/Avatar/Avatar.styles.tsx +47 -62
  17. package/src/Avatar/Avatar.web.tsx +2 -2
  18. package/src/Badge/Badge.native.tsx +2 -2
  19. package/src/Badge/Badge.styles.old.tsx +157 -0
  20. package/src/Badge/Badge.styles.tsx +69 -108
  21. package/src/Badge/Badge.web.tsx +6 -6
  22. package/src/Breadcrumb/Breadcrumb.native.tsx +12 -5
  23. package/src/Breadcrumb/Breadcrumb.styles.old.tsx +231 -0
  24. package/src/Breadcrumb/Breadcrumb.styles.tsx +93 -209
  25. package/src/Breadcrumb/Breadcrumb.web.tsx +39 -27
  26. package/src/Button/Button.native.tsx +39 -14
  27. package/src/Button/Button.styles.tsx +99 -253
  28. package/src/Button/Button.web.tsx +10 -8
  29. package/src/Card/Card.native.tsx +8 -4
  30. package/src/Card/Card.styles.old.tsx +160 -0
  31. package/src/Card/Card.styles.tsx +107 -142
  32. package/src/Card/Card.web.tsx +6 -4
  33. package/src/Checkbox/Checkbox.native.tsx +14 -6
  34. package/src/Checkbox/Checkbox.styles.old.tsx +271 -0
  35. package/src/Checkbox/Checkbox.styles.tsx +109 -197
  36. package/src/Checkbox/Checkbox.web.tsx +7 -7
  37. package/src/Chip/Chip.native.tsx +5 -5
  38. package/src/Chip/Chip.styles.old.tsx +184 -0
  39. package/src/Chip/Chip.styles.tsx +34 -22
  40. package/src/Chip/Chip.web.tsx +5 -5
  41. package/src/Dialog/Dialog.native.tsx +16 -7
  42. package/src/Dialog/Dialog.styles.old.tsx +202 -0
  43. package/src/Dialog/Dialog.styles.tsx +108 -132
  44. package/src/Dialog/Dialog.web.tsx +4 -4
  45. package/src/Divider/Divider.native.tsx +29 -42
  46. package/src/Divider/Divider.styles.old.tsx +172 -0
  47. package/src/Divider/Divider.styles.tsx +116 -242
  48. package/src/Divider/Divider.web.tsx +17 -14
  49. package/src/Icon/Icon.native.tsx +12 -4
  50. package/src/Icon/Icon.styles.old.tsx +81 -0
  51. package/src/Icon/Icon.styles.tsx +52 -60
  52. package/src/Icon/Icon.web.tsx +43 -7
  53. package/src/Icon/IconSvg/IconSvg.web.tsx +2 -0
  54. package/src/Image/Image.styles.old.tsx +69 -0
  55. package/src/Image/Image.styles.tsx +45 -43
  56. package/src/Input/Input.native.tsx +140 -56
  57. package/src/Input/Input.styles.old.tsx +289 -0
  58. package/src/Input/Input.styles.tsx +177 -228
  59. package/src/Input/Input.web.tsx +5 -8
  60. package/src/Link/Link.native.tsx +4 -1
  61. package/src/List/List.native.tsx +5 -2
  62. package/src/List/List.styles.old.tsx +242 -0
  63. package/src/List/List.styles.tsx +178 -240
  64. package/src/List/ListItem.native.tsx +16 -8
  65. package/src/List/ListItem.web.tsx +26 -15
  66. package/src/Menu/Menu.native.tsx +1 -1
  67. package/src/Menu/Menu.styles.old.tsx +197 -0
  68. package/src/Menu/Menu.styles.tsx +90 -156
  69. package/src/Menu/Menu.web.tsx +2 -2
  70. package/src/Menu/MenuItem.native.tsx +9 -5
  71. package/src/Menu/MenuItem.styles.old.tsx +114 -0
  72. package/src/Menu/MenuItem.styles.tsx +71 -104
  73. package/src/Menu/MenuItem.web.tsx +23 -5
  74. package/src/Popover/Popover.native.tsx +10 -4
  75. package/src/Popover/Popover.styles.old.tsx +135 -0
  76. package/src/Popover/Popover.styles.tsx +46 -96
  77. package/src/Popover/Popover.web.tsx +1 -1
  78. package/src/Pressable/Pressable.native.tsx +3 -1
  79. package/src/Pressable/Pressable.styles.old.tsx +27 -0
  80. package/src/Pressable/Pressable.styles.tsx +35 -20
  81. package/src/Pressable/Pressable.web.tsx +1 -1
  82. package/src/Progress/Progress.native.tsx +15 -6
  83. package/src/Progress/Progress.styles.old.tsx +200 -0
  84. package/src/Progress/Progress.styles.tsx +69 -118
  85. package/src/Progress/Progress.web.tsx +10 -9
  86. package/src/RadioButton/RadioButton.native.tsx +10 -4
  87. package/src/RadioButton/RadioButton.styles.old.tsx +175 -0
  88. package/src/RadioButton/RadioButton.styles.tsx +81 -145
  89. package/src/RadioButton/RadioButton.web.tsx +4 -4
  90. package/src/SVGImage/SVGImage.styles.old.tsx +86 -0
  91. package/src/SVGImage/SVGImage.styles.tsx +35 -66
  92. package/src/Screen/Screen.native.tsx +30 -27
  93. package/src/Screen/Screen.styles.old.tsx +87 -0
  94. package/src/Screen/Screen.styles.tsx +120 -71
  95. package/src/Screen/Screen.web.tsx +2 -2
  96. package/src/Select/Select.native.tsx +44 -29
  97. package/src/Select/Select.styles.old.tsx +353 -0
  98. package/src/Select/Select.styles.tsx +244 -293
  99. package/src/Select/Select.web.tsx +5 -5
  100. package/src/Skeleton/Skeleton.styles.old.tsx +67 -0
  101. package/src/Skeleton/Skeleton.styles.tsx +31 -43
  102. package/src/Slider/Slider.native.tsx +9 -5
  103. package/src/Slider/Slider.styles.old.tsx +259 -0
  104. package/src/Slider/Slider.styles.tsx +157 -227
  105. package/src/Slider/Slider.web.tsx +5 -5
  106. package/src/Switch/Switch.native.tsx +11 -5
  107. package/src/Switch/Switch.styles.old.tsx +203 -0
  108. package/src/Switch/Switch.styles.tsx +103 -149
  109. package/src/Switch/Switch.web.tsx +8 -8
  110. package/src/TabBar/TabBar.native.tsx +24 -31
  111. package/src/TabBar/TabBar.styles.old.tsx +343 -0
  112. package/src/TabBar/TabBar.styles.tsx +204 -494
  113. package/src/TabBar/TabBar.web.tsx +21 -33
  114. package/src/Table/Table.native.tsx +18 -9
  115. package/src/Table/Table.styles.old.tsx +311 -0
  116. package/src/Table/Table.styles.tsx +151 -278
  117. package/src/Table/Table.web.tsx +1 -1
  118. package/src/Text/Text.native.tsx +1 -4
  119. package/src/Text/Text.style.demo.tsx +16 -0
  120. package/src/Text/Text.styles.old.tsx +219 -0
  121. package/src/Text/Text.styles.tsx +94 -78
  122. package/src/Text/Text.web.tsx +2 -2
  123. package/src/Text/index.ts +1 -0
  124. package/src/TextArea/TextArea.styles.old.tsx +213 -0
  125. package/src/TextArea/TextArea.styles.tsx +101 -157
  126. package/src/Tooltip/Tooltip.native.tsx +2 -2
  127. package/src/Tooltip/Tooltip.styles.old.tsx +82 -0
  128. package/src/Tooltip/Tooltip.styles.tsx +38 -53
  129. package/src/Tooltip/Tooltip.web.tsx +2 -2
  130. package/src/Video/Video.styles.old.tsx +51 -0
  131. package/src/Video/Video.styles.tsx +32 -28
  132. package/src/View/View.native.tsx +12 -12
  133. package/src/View/View.styles.old.tsx +125 -0
  134. package/src/View/View.styles.tsx +84 -103
  135. package/src/View/View.web.tsx +14 -2
  136. package/src/examples/CardExamples.tsx +0 -6
  137. package/src/extensions/applyExtension.ts +210 -0
  138. package/src/extensions/extendComponent.ts +438 -0
  139. package/src/extensions/index.ts +102 -0
  140. package/src/extensions/types.ts +497 -0
  141. package/src/globals.ts +16 -0
  142. package/src/index.native.ts +4 -0
  143. package/src/index.ts +28 -0
  144. package/src/utils/deepMerge.ts +54 -2
@@ -1,180 +1,134 @@
1
+ /**
2
+ * Switch styles using defineStyle with dynamic props.
3
+ */
1
4
  import { StyleSheet } from 'react-native-unistyles';
2
- import { Theme, StylesheetStyles, Intent, Size} from '@idealyst/theme';
3
- import { buildSizeVariants } from '../utils/buildSizeVariants';
4
- import {
5
- buildMarginVariants,
6
- buildMarginVerticalVariants,
7
- buildMarginHorizontalVariants,
8
- } from '../utils/buildViewStyleVariants';
9
- import { SwitchIntentVariant, SwitchSizeVariant } from './types';
5
+ import { defineStyle, ThemeStyleWrapper } from '@idealyst/theme';
6
+ import type { Theme as BaseTheme, Intent, Size } from '@idealyst/theme';
7
+ import { ViewStyleSize } from '../utils/viewStyleProps';
10
8
 
11
- function createTrackSizeVariants(theme: Theme) {
12
- return buildSizeVariants(theme, 'switch', (size) => ({
13
- width: size.trackWidth,
14
- height: size.trackHeight,
15
- }));
16
- }
9
+ // Required: Unistyles must see StyleSheet usage in original source to process this file
10
+ void StyleSheet;
17
11
 
18
- function getTrackBackgroundColor(theme: Theme, checked: boolean, intent: SwitchIntentVariant) {
19
- if (checked) {
20
- return theme.intents[intent].primary;
21
- }
22
- return theme.colors.border.secondary;
23
- }
12
+ // Wrap theme for $iterator support
13
+ type Theme = ThemeStyleWrapper<BaseTheme>;
24
14
 
25
- function createThumbSizeVariants(theme: Theme) {
26
- return buildSizeVariants(theme, 'switch', (size) => ({
27
- width: size.thumbSize,
28
- height: size.thumbSize,
29
- left: 2,
30
- }));
31
- }
15
+ type LabelPosition = 'left' | 'right';
32
16
 
33
- function getThumbTransform(theme: Theme, size: SwitchSizeVariant, checked: boolean) {
34
- const sizeValue = theme.sizes.switch[size];
35
- const translateX = checked ? sizeValue.translateX : 0;
36
- return `translateY(-50%) translateX(${translateX}px)`;
37
- }
17
+ export type SwitchDynamicProps = {
18
+ size?: Size;
19
+ intent?: Intent;
20
+ checked?: boolean;
21
+ disabled?: boolean;
22
+ labelPosition?: LabelPosition;
23
+ margin?: ViewStyleSize;
24
+ marginVertical?: ViewStyleSize;
25
+ marginHorizontal?: ViewStyleSize;
26
+ };
38
27
 
39
- function createThumbIconSizeVariants(theme: Theme) {
40
- return buildSizeVariants(theme, 'switch', (size) => ({
41
- width: size.thumbIconSize,
42
- height: size.thumbIconSize,
43
- }));
44
- }
28
+ /**
29
+ * Switch styles with intent/checked/disabled handling.
30
+ */
31
+ export const switchStyles = defineStyle('Switch', (theme: Theme) => ({
32
+ container: (_props: SwitchDynamicProps) => ({
33
+ flexDirection: 'row' as const,
34
+ alignItems: 'center' as const,
35
+ gap: 8,
36
+ variants: {
37
+ margin: {
38
+ margin: theme.sizes.$view.padding,
39
+ },
40
+ marginVertical: {
41
+ marginVertical: theme.sizes.$view.padding,
42
+ },
43
+ marginHorizontal: {
44
+ marginHorizontal: theme.sizes.$view.padding,
45
+ },
46
+ },
47
+ }),
45
48
 
46
- function getThumbIconColor(theme: Theme, checked: boolean, intent: SwitchIntentVariant) {
47
- if (checked) {
48
- return theme.intents[intent].primary;
49
- }
50
- return theme.colors.border.secondary;
51
- }
49
+ switchContainer: (_props: SwitchDynamicProps) => ({
50
+ justifyContent: 'center' as const,
51
+ _web: {
52
+ border: 'none',
53
+ padding: 0,
54
+ backgroundColor: 'transparent',
55
+ width: 'fit-content',
56
+ },
57
+ }),
52
58
 
53
- function createSwitchTrackStyles(theme: Theme) {
54
- return ({ checked, intent }: { checked: boolean, intent: SwitchIntentVariant }) => {
55
- return {
56
- borderRadius: 9999,
57
- position: 'relative',
58
- backgroundColor: getTrackBackgroundColor(theme, checked, intent),
59
- variants: {
60
- size: createTrackSizeVariants(theme),
61
- disabled: {
62
- true: {
63
- opacity: 0.5,
64
- _web: {
65
- cursor: 'not-allowed',
66
- },
67
- },
68
- false: {
69
- opacity: 1,
70
- _web: {
71
- cursor: 'pointer',
72
- _hover: {
73
- opacity: 0.9,
74
- },
75
- _active: {
76
- opacity: 0.8,
77
- },
78
- },
79
- },
80
- },
81
- } as const,
82
- _web: {
83
- transition: 'background-color 0.2s ease',
59
+ switchTrack: ({ intent = 'primary', checked = false, disabled = false }: SwitchDynamicProps) => ({
60
+ borderRadius: 9999,
61
+ position: 'relative' as const,
62
+ backgroundColor: checked
63
+ ? theme.intents[intent].primary
64
+ : theme.colors.border.secondary,
65
+ opacity: disabled ? 0.5 : 1,
66
+ variants: {
67
+ size: {
68
+ width: theme.sizes.$switch.trackWidth,
69
+ height: theme.sizes.$switch.trackHeight,
84
70
  },
85
- } as const;
86
- }
87
- }
71
+ },
72
+ _web: {
73
+ transition: 'background-color 0.2s ease',
74
+ cursor: disabled ? 'not-allowed' : 'pointer',
75
+ _hover: disabled ? {} : { opacity: 0.9 },
76
+ _active: disabled ? {} : { opacity: 0.8 },
77
+ },
78
+ }),
79
+
80
+ switchThumb: ({ size = 'md', checked = false }: SwitchDynamicProps) => {
81
+ const sizeValue = theme.sizes.switch[size];
82
+ const translateX = checked ? sizeValue.translateX : 0;
88
83
 
89
- function createSwitchThumbStyles(theme: Theme) {
90
- return ({ size, checked }: { size: SwitchSizeVariant, checked: boolean }) => {
91
84
  return {
92
- position: 'absolute',
85
+ position: 'absolute' as const,
93
86
  backgroundColor: theme.colors.surface.primary,
94
87
  borderRadius: 9999,
95
88
  top: '50%',
96
- display: 'flex',
97
- alignItems: 'center',
98
- justifyContent: 'center',
89
+ display: 'flex' as const,
90
+ alignItems: 'center' as const,
91
+ justifyContent: 'center' as const,
99
92
  shadowColor: '#000',
100
93
  shadowOffset: { width: 0, height: 1 },
101
94
  shadowOpacity: 0.2,
102
95
  shadowRadius: 3,
103
96
  elevation: 2,
104
97
  variants: {
105
- size: createThumbSizeVariants(theme),
98
+ size: {
99
+ width: theme.sizes.$switch.thumbSize,
100
+ height: theme.sizes.$switch.thumbSize,
101
+ left: 2,
102
+ },
106
103
  },
107
104
  _web: {
108
105
  boxShadow: '0 1px 3px rgba(0, 0, 0, 0.2)',
109
106
  transition: 'transform 0.2s ease',
110
- transform: getThumbTransform(theme, size, checked),
107
+ transform: `translateY(-50%) translateX(${translateX}px)`,
111
108
  },
112
109
  } as const;
113
- }
114
- }
115
-
116
- function createThumbIconStyles(theme: Theme) {
117
- return ({ checked, intent }: { checked: boolean, intent: SwitchIntentVariant }) => {
118
- return {
119
- display: 'flex',
120
- alignItems: 'center',
121
- justifyContent: 'center',
122
- color: getThumbIconColor(theme, checked, intent),
123
- variants: {
124
- size: createThumbIconSizeVariants(theme),
125
- },
126
- } as const;
127
- }
128
- }
110
+ },
129
111
 
130
- // Styles are inlined here instead of in @idealyst/theme because Unistyles' Babel
131
- // transform on native cannot resolve function calls to extract variant structures.
132
- export const switchStyles = StyleSheet.create((theme: Theme) => {
133
- return {
134
- container: {
135
- flexDirection: 'row',
136
- alignItems: 'center',
137
- gap: 8,
112
+ thumbIcon: ({ intent = 'primary', checked = false }: SwitchDynamicProps) => ({
113
+ display: 'flex' as const,
114
+ alignItems: 'center' as const,
115
+ justifyContent: 'center' as const,
116
+ color: checked
117
+ ? theme.intents[intent].primary
118
+ : theme.colors.border.secondary,
138
119
  variants: {
139
- // Spacing variants from FormInputStyleProps
140
- margin: buildMarginVariants(theme),
141
- marginVertical: buildMarginVerticalVariants(theme),
142
- marginHorizontal: buildMarginHorizontalVariants(theme),
120
+ size: {
121
+ width: theme.sizes.$switch.thumbIconSize,
122
+ height: theme.sizes.$switch.thumbIconSize,
123
+ },
143
124
  },
144
- },
145
- switchContainer: {
146
- justifyContent: 'center',
147
- _web: {
148
- border: 'none',
149
- padding: 0,
150
- backgroundColor: 'transparent',
151
- width: 'fit-content',
152
- }
153
- },
154
- switchTrack: createSwitchTrackStyles(theme),
155
- switchThumb: createSwitchThumbStyles(theme),
156
- thumbIcon: createThumbIconStyles(theme),
157
- label: {
125
+ }),
126
+
127
+ label: ({ disabled = false, labelPosition = 'right' }: SwitchDynamicProps) => ({
158
128
  fontSize: 14,
159
129
  color: theme.colors.text.primary,
160
- variants: {
161
- disabled: {
162
- true: {
163
- opacity: 0.5,
164
- },
165
- false: {
166
- opacity: 1,
167
- },
168
- },
169
- position: {
170
- left: {
171
- marginRight: 8,
172
- },
173
- right: {
174
- marginLeft: 8,
175
- },
176
- },
177
- } as const,
178
- } as const,
179
- };
180
- });
130
+ opacity: disabled ? 0.5 : 1,
131
+ marginRight: labelPosition === 'left' ? 8 : 0,
132
+ marginLeft: labelPosition === 'right' ? 8 : 0,
133
+ }),
134
+ }));
@@ -82,10 +82,10 @@ const Switch = forwardRef<HTMLDivElement | HTMLButtonElement, SwitchProps>(({
82
82
  marginHorizontal,
83
83
  });
84
84
 
85
- const trackProps = getWebProps([switchStyles.switchTrack({ checked, intent })]);
86
- const thumbProps = getWebProps([switchStyles.switchThumb({ size, checked })]);
87
- const thumbIconProps = getWebProps([switchStyles.thumbIcon({ checked, intent })]);
88
- const labelProps = getWebProps([switchStyles.label]);
85
+ const trackProps = getWebProps([(switchStyles.switchTrack as any)({ checked, intent, disabled })]);
86
+ const thumbProps = getWebProps([(switchStyles.switchThumb as any)({ size, checked })]);
87
+ const thumbIconProps = getWebProps([(switchStyles.thumbIcon as any)({ checked, intent })]);
88
+ const labelProps = getWebProps([(switchStyles.label as any)({ disabled, labelPosition })]);
89
89
 
90
90
  // Helper to render icon
91
91
  const renderIcon = () => {
@@ -109,13 +109,13 @@ const Switch = forwardRef<HTMLDivElement | HTMLButtonElement, SwitchProps>(({
109
109
  };
110
110
 
111
111
  // Computed button props with dynamic styles
112
- const computedButtonProps = getWebProps(
113
- switchStyles.switchContainer
114
- );
112
+ const computedButtonProps = getWebProps([
113
+ (switchStyles.switchContainer as any)({})
114
+ ]);
115
115
 
116
116
  // Computed container props with dynamic styles (for when label exists)
117
117
  const computedContainerProps = getWebProps([
118
- switchStyles.container,
118
+ (switchStyles.container as any)({}),
119
119
  style as any,
120
120
  {
121
121
  cursor: disabled ? 'not-allowed' : 'pointer',
@@ -88,11 +88,11 @@ const TabBar = forwardRef<View, TabBarProps>(({
88
88
  const containerPadding = type === 'pills' ? 4 : 0;
89
89
 
90
90
  indicatorPosition.value = withSpring(layout.x + containerPadding, {
91
- damping: 30,
91
+ damping: 100,
92
92
  stiffness: 300,
93
93
  });
94
94
  indicatorWidth.value = withSpring(layout.width, {
95
- damping: 30,
95
+ damping: 100,
96
96
  stiffness: 300,
97
97
  });
98
98
  }
@@ -128,11 +128,8 @@ const TabBar = forwardRef<View, TabBarProps>(({
128
128
  };
129
129
  });
130
130
 
131
- // Apply container and indicator types right before rendering
131
+ // Apply container variants (for spacing only)
132
132
  tabBarContainerStyles.useVariants({
133
- type,
134
- size,
135
- pillMode,
136
133
  justify,
137
134
  gap,
138
135
  padding,
@@ -142,46 +139,37 @@ const TabBar = forwardRef<View, TabBarProps>(({
142
139
  marginVertical,
143
140
  marginHorizontal,
144
141
  });
145
- tabBarIndicatorStyles.useVariants({ type, pillMode });
142
+
143
+ // Compute dynamic container and indicator styles
144
+ const containerStyle = (tabBarContainerStyles.container as any)({ type, pillMode });
145
+ const indicatorStyle = (tabBarIndicatorStyles.indicator as any)({ type, pillMode });
146
146
 
147
147
  return (
148
148
  <ScrollView
149
149
  horizontal
150
150
  showsHorizontalScrollIndicator={false}
151
- contentContainerStyle={{ position: 'relative' }}
151
+ contentContainerStyle={{
152
+ position: 'relative',
153
+ flexGrow: 1,
154
+ }}
155
+ style={{ width: '100%' }}
152
156
  >
153
- <View ref={ref} nativeID={id} style={[tabBarContainerStyles.container, style]} testID={testID} {...nativeA11yProps}>
157
+ <View ref={ref} nativeID={id} style={[containerStyle, style]} testID={testID} {...nativeA11yProps}>
154
158
  {/* Animated indicator - render first so it's behind */}
155
159
  <Animated.View
156
160
  style={[
157
- tabBarIndicatorStyles.indicator,
161
+ indicatorStyle,
158
162
  indicatorAnimatedStyle,
159
163
  ]}
160
164
  />
161
165
 
162
166
  {/* Tabs - render second so they're on top */}
163
- <View style={{ flexDirection: 'row' }}>
167
+ <View style={{ flexDirection: 'row', flex: 1 }}>
164
168
  {items.map((item) => {
165
169
  const isActive = value === item.value;
166
170
  const iconSize = ICON_SIZES[size] || 18;
167
171
 
168
- // Apply tab and label types for this specific tab
169
- tabBarTabStyles.useVariants({
170
- size,
171
- type,
172
- active: isActive,
173
- disabled: Boolean(item.disabled),
174
- pillMode,
175
- iconPosition,
176
- justify,
177
- });
178
- tabBarLabelStyles.useVariants({
179
- size,
180
- type,
181
- pillMode,
182
- active: isActive,
183
- disabled: Boolean(item.disabled),
184
- });
172
+ // Apply icon variants (size, disabled, iconPosition)
185
173
  tabBarIconStyles.useVariants({
186
174
  size,
187
175
  active: isActive,
@@ -189,6 +177,11 @@ const TabBar = forwardRef<View, TabBarProps>(({
189
177
  iconPosition,
190
178
  });
191
179
 
180
+ // Compute dynamic styles for this tab - call as functions for theme reactivity
181
+ const tabStyle = (tabBarTabStyles.tab as any)({ type, size, active: isActive, pillMode, justify });
182
+ const labelStyle = (tabBarLabelStyles.tabLabel as any)({ type, active: isActive, pillMode });
183
+ const iconContainerStyle = (tabBarIconStyles.tabIcon as any)({});
184
+
192
185
  const icon = renderIcon(item.icon, isActive, iconSize);
193
186
 
194
187
  return (
@@ -198,7 +191,7 @@ const TabBar = forwardRef<View, TabBarProps>(({
198
191
  const { x, width } = event.nativeEvent.layout;
199
192
  handleTabLayout(item.value, x, width);
200
193
  }}
201
- style={tabBarTabStyles.tab}
194
+ style={tabStyle}
202
195
  onPress={() => handleTabClick(item.value, item.disabled)}
203
196
  disabled={item.disabled}
204
197
  activeOpacity={0.7}
@@ -207,8 +200,8 @@ const TabBar = forwardRef<View, TabBarProps>(({
207
200
  accessibilityLabel={item.label}
208
201
  accessibilityState={{ selected: isActive, disabled: item.disabled }}
209
202
  >
210
- {icon && <View style={tabBarIconStyles.tabIcon}>{icon}</View>}
211
- <Text style={tabBarLabelStyles.tabLabel}>{item.label}</Text>
203
+ {icon && <View style={iconContainerStyle}>{icon}</View>}
204
+ <Text style={labelStyle}>{item.label}</Text>
212
205
  </TouchableOpacity>
213
206
  );
214
207
  })}