@sudobility/components-rn 1.0.41 → 1.0.43

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 (142) hide show
  1. package/dist/index.cjs.js +1092 -473
  2. package/dist/index.cjs.js.map +1 -1
  3. package/dist/index.esm.js +1095 -476
  4. package/dist/index.esm.js.map +1 -1
  5. package/dist/ui/Alert/Alert.d.ts.map +1 -1
  6. package/dist/ui/Avatar/Avatar.d.ts.map +1 -1
  7. package/dist/ui/Badge/Badge.d.ts.map +1 -1
  8. package/dist/ui/Banner/Banner.d.ts.map +1 -1
  9. package/dist/ui/Breadcrumb/Breadcrumb.d.ts.map +1 -1
  10. package/dist/ui/BreadcrumbNav/BreadcrumbNav.d.ts.map +1 -1
  11. package/dist/ui/CTASection/CTASection.d.ts.map +1 -1
  12. package/dist/ui/Calendar/Calendar.d.ts.map +1 -1
  13. package/dist/ui/ChainBadge/ChainBadge.d.ts.map +1 -1
  14. package/dist/ui/Checkbox/Checkbox.d.ts +0 -22
  15. package/dist/ui/Checkbox/Checkbox.d.ts.map +1 -1
  16. package/dist/ui/Code/Code.d.ts +0 -17
  17. package/dist/ui/Code/Code.d.ts.map +1 -1
  18. package/dist/ui/CodeDisplay/CodeDisplay.d.ts +0 -21
  19. package/dist/ui/CodeDisplay/CodeDisplay.d.ts.map +1 -1
  20. package/dist/ui/CollapsibleSection/CollapsibleSection.d.ts.map +1 -1
  21. package/dist/ui/Combobox/Combobox.d.ts.map +1 -1
  22. package/dist/ui/Command/Command.d.ts.map +1 -1
  23. package/dist/ui/DashboardStatCard/DashboardStatCard.d.ts +0 -17
  24. package/dist/ui/DashboardStatCard/DashboardStatCard.d.ts.map +1 -1
  25. package/dist/ui/DataList/DataList.d.ts.map +1 -1
  26. package/dist/ui/Divider/Divider.d.ts.map +1 -1
  27. package/dist/ui/Dropdown/Dropdown.d.ts.map +1 -1
  28. package/dist/ui/ExternalLink/ExternalLink.d.ts.map +1 -1
  29. package/dist/ui/FeatureCard/FeatureCard.d.ts.map +1 -1
  30. package/dist/ui/FeatureGrid/FeatureGrid.d.ts.map +1 -1
  31. package/dist/ui/GradientIconContainer/GradientIconContainer.d.ts +0 -13
  32. package/dist/ui/GradientIconContainer/GradientIconContainer.d.ts.map +1 -1
  33. package/dist/ui/Heading/Heading.d.ts.map +1 -1
  34. package/dist/ui/HelperText/HelperText.d.ts.map +1 -1
  35. package/dist/ui/IconContainer/IconContainer.d.ts +0 -13
  36. package/dist/ui/IconContainer/IconContainer.d.ts.map +1 -1
  37. package/dist/ui/IconText/IconText.d.ts.map +1 -1
  38. package/dist/ui/InfiniteScroll/InfiniteScroll.d.ts.map +1 -1
  39. package/dist/ui/InfoBox/InfoBox.d.ts.map +1 -1
  40. package/dist/ui/Input/Input.d.ts.map +1 -1
  41. package/dist/ui/KeyValuePair/KeyValuePair.d.ts.map +1 -1
  42. package/dist/ui/Label/Label.d.ts.map +1 -1
  43. package/dist/ui/Link/Link.d.ts.map +1 -1
  44. package/dist/ui/ListItemWithAction/ListItemWithAction.d.ts.map +1 -1
  45. package/dist/ui/Modal/Modal.d.ts.map +1 -1
  46. package/dist/ui/MultiSelect/MultiSelect.d.ts.map +1 -1
  47. package/dist/ui/NavigationList/NavigationList.d.ts.map +1 -1
  48. package/dist/ui/PageSectionHeader/PageSectionHeader.d.ts.map +1 -1
  49. package/dist/ui/Pagination/Pagination.d.ts.map +1 -1
  50. package/dist/ui/PhoneInput/PhoneInput.d.ts.map +1 -1
  51. package/dist/ui/PopupSelect/PopupSelect.d.ts.map +1 -1
  52. package/dist/ui/Progress/Progress.d.ts +0 -15
  53. package/dist/ui/Progress/Progress.d.ts.map +1 -1
  54. package/dist/ui/ProgressCircle/ProgressCircle.d.ts.map +1 -1
  55. package/dist/ui/PromotionalBanner/PromotionalBanner.d.ts.map +1 -1
  56. package/dist/ui/QuickActions/QuickActions.d.ts.map +1 -1
  57. package/dist/ui/SearchInput/SearchInput.d.ts.map +1 -1
  58. package/dist/ui/SectionHeader/SectionHeader.d.ts.map +1 -1
  59. package/dist/ui/Select/Select.d.ts.map +1 -1
  60. package/dist/ui/SettingsList/SettingsList.d.ts.map +1 -1
  61. package/dist/ui/Sheet/Sheet.d.ts.map +1 -1
  62. package/dist/ui/SideNav/SideNav.d.ts.map +1 -1
  63. package/dist/ui/SmartLink/SmartLink.d.ts.map +1 -1
  64. package/dist/ui/Spinner/Spinner.d.ts.map +1 -1
  65. package/dist/ui/StatDisplay/StatDisplay.d.ts +0 -12
  66. package/dist/ui/StatDisplay/StatDisplay.d.ts.map +1 -1
  67. package/dist/ui/StepList/StepList.d.ts.map +1 -1
  68. package/dist/ui/Table/Table.d.ts.map +1 -1
  69. package/dist/ui/Tabs/Tabs.d.ts.map +1 -1
  70. package/dist/ui/Text/Text.d.ts.map +1 -1
  71. package/dist/ui/TextArea/TextArea.d.ts.map +1 -1
  72. package/dist/ui/TextInputModal/TextInputModal.d.ts.map +1 -1
  73. package/dist/ui/Toast/Toast.d.ts.map +1 -1
  74. package/dist/ui/Tooltip/Tooltip.d.ts +0 -20
  75. package/dist/ui/Tooltip/Tooltip.d.ts.map +1 -1
  76. package/dist/ui/TransferList/TransferList.d.ts.map +1 -1
  77. package/package.json +5 -4
  78. package/src/__tests__/alert.test.tsx +20 -10
  79. package/src/ui/Alert/Alert.tsx +13 -5
  80. package/src/ui/Avatar/Avatar.tsx +6 -5
  81. package/src/ui/Badge/Badge.tsx +61 -26
  82. package/src/ui/Banner/Banner.tsx +36 -25
  83. package/src/ui/Breadcrumb/Breadcrumb.tsx +8 -5
  84. package/src/ui/BreadcrumbNav/BreadcrumbNav.tsx +22 -3
  85. package/src/ui/CTASection/CTASection.tsx +8 -6
  86. package/src/ui/Calendar/Calendar.tsx +35 -6
  87. package/src/ui/Card/Card.tsx +2 -2
  88. package/src/ui/ChainBadge/ChainBadge.tsx +67 -42
  89. package/src/ui/Checkbox/Checkbox.tsx +47 -20
  90. package/src/ui/Code/Code.tsx +51 -21
  91. package/src/ui/CodeDisplay/CodeDisplay.tsx +46 -20
  92. package/src/ui/CollapsibleSection/CollapsibleSection.tsx +7 -3
  93. package/src/ui/Combobox/Combobox.tsx +2 -1
  94. package/src/ui/Command/Command.tsx +2 -1
  95. package/src/ui/DashboardStatCard/DashboardStatCard.tsx +29 -11
  96. package/src/ui/DataList/DataList.tsx +23 -5
  97. package/src/ui/Divider/Divider.tsx +12 -17
  98. package/src/ui/Dropdown/Dropdown.tsx +4 -1
  99. package/src/ui/ExternalLink/ExternalLink.tsx +5 -4
  100. package/src/ui/FeatureCard/FeatureCard.tsx +60 -29
  101. package/src/ui/FeatureGrid/FeatureGrid.tsx +7 -7
  102. package/src/ui/GradientIconContainer/GradientIconContainer.tsx +33 -8
  103. package/src/ui/Heading/Heading.tsx +15 -38
  104. package/src/ui/HelperText/HelperText.tsx +9 -8
  105. package/src/ui/IconContainer/IconContainer.tsx +26 -9
  106. package/src/ui/IconText/IconText.tsx +6 -5
  107. package/src/ui/InfiniteScroll/InfiniteScroll.tsx +2 -1
  108. package/src/ui/InfoBox/InfoBox.tsx +35 -17
  109. package/src/ui/Input/Input.tsx +10 -3
  110. package/src/ui/KeyValuePair/KeyValuePair.tsx +12 -5
  111. package/src/ui/Label/Label.tsx +3 -1
  112. package/src/ui/Link/Link.tsx +6 -5
  113. package/src/ui/ListItemWithAction/ListItemWithAction.tsx +2 -1
  114. package/src/ui/Modal/Modal.tsx +16 -2
  115. package/src/ui/MultiSelect/MultiSelect.tsx +2 -1
  116. package/src/ui/NavigationList/NavigationList.tsx +17 -3
  117. package/src/ui/PageSectionHeader/PageSectionHeader.tsx +2 -1
  118. package/src/ui/Pagination/Pagination.tsx +9 -6
  119. package/src/ui/PhoneInput/PhoneInput.tsx +3 -2
  120. package/src/ui/PopupSelect/PopupSelect.tsx +15 -14
  121. package/src/ui/Progress/Progress.tsx +63 -14
  122. package/src/ui/ProgressCircle/ProgressCircle.tsx +7 -6
  123. package/src/ui/PromotionalBanner/PromotionalBanner.tsx +7 -4
  124. package/src/ui/QuickActions/QuickActions.tsx +13 -9
  125. package/src/ui/SearchInput/SearchInput.tsx +3 -2
  126. package/src/ui/SectionHeader/SectionHeader.tsx +4 -1
  127. package/src/ui/Select/Select.tsx +20 -5
  128. package/src/ui/SettingsList/SettingsList.tsx +4 -1
  129. package/src/ui/Sheet/Sheet.tsx +20 -3
  130. package/src/ui/SideNav/SideNav.tsx +11 -2
  131. package/src/ui/SmartLink/SmartLink.tsx +6 -3
  132. package/src/ui/Spinner/Spinner.tsx +8 -6
  133. package/src/ui/StatDisplay/StatDisplay.tsx +59 -23
  134. package/src/ui/StepList/StepList.tsx +25 -3
  135. package/src/ui/Table/Table.tsx +22 -9
  136. package/src/ui/Tabs/Tabs.tsx +7 -2
  137. package/src/ui/Text/Text.tsx +19 -52
  138. package/src/ui/TextArea/TextArea.tsx +2 -1
  139. package/src/ui/TextInputModal/TextInputModal.tsx +2 -1
  140. package/src/ui/Toast/Toast.tsx +49 -14
  141. package/src/ui/Tooltip/Tooltip.tsx +47 -9
  142. package/src/ui/TransferList/TransferList.tsx +2 -1
@@ -2,6 +2,9 @@ import * as React from 'react';
2
2
  import { useState } from 'react';
3
3
  import { View, Text, Pressable } from 'react-native';
4
4
  import { cn } from '../../lib/utils';
5
+ import { designTokens } from '@sudobility/design';
6
+
7
+ const { typography } = designTokens;
5
8
 
6
9
  export interface CalendarProps {
7
10
  /** Selected date */
@@ -154,10 +157,23 @@ export const Calendar: React.FC<CalendarProps> = ({
154
157
  accessibilityRole='button'
155
158
  accessibilityLabel='Previous month'
156
159
  >
157
- <Text className='text-lg text-gray-700 dark:text-gray-300'>‹</Text>
160
+ <Text
161
+ className={cn(
162
+ typography.size.lg,
163
+ 'text-gray-700 dark:text-gray-300'
164
+ )}
165
+ >
166
+
167
+ </Text>
158
168
  </Pressable>
159
169
 
160
- <Text className='text-base font-semibold text-gray-900 dark:text-white'>
170
+ <Text
171
+ className={cn(
172
+ typography.size.base,
173
+ typography.weight.semibold,
174
+ 'text-gray-900 dark:text-white'
175
+ )}
176
+ >
161
177
  {monthYear}
162
178
  </Text>
163
179
 
@@ -167,7 +183,14 @@ export const Calendar: React.FC<CalendarProps> = ({
167
183
  accessibilityRole='button'
168
184
  accessibilityLabel='Next month'
169
185
  >
170
- <Text className='text-lg text-gray-700 dark:text-gray-300'>›</Text>
186
+ <Text
187
+ className={cn(
188
+ typography.size.lg,
189
+ 'text-gray-700 dark:text-gray-300'
190
+ )}
191
+ >
192
+
193
+ </Text>
171
194
  </Pressable>
172
195
  </View>
173
196
 
@@ -175,7 +198,13 @@ export const Calendar: React.FC<CalendarProps> = ({
175
198
  <View className='flex-row mb-2'>
176
199
  {weekDays.map(day => (
177
200
  <View key={day} className='flex-1 items-center py-2'>
178
- <Text className='text-xs font-medium text-gray-600 dark:text-gray-400'>
201
+ <Text
202
+ className={cn(
203
+ typography.size.xs,
204
+ typography.weight.medium,
205
+ 'text-gray-600 dark:text-gray-400'
206
+ )}
207
+ >
179
208
  {day}
180
209
  </Text>
181
210
  </View>
@@ -223,11 +252,11 @@ export const Calendar: React.FC<CalendarProps> = ({
223
252
  >
224
253
  <Text
225
254
  className={cn(
226
- 'text-sm',
255
+ typography.size.sm,
227
256
  isCurrentMonth
228
257
  ? 'text-gray-900 dark:text-white'
229
258
  : 'text-gray-400 dark:text-gray-600',
230
- isSelected && 'text-white font-semibold'
259
+ isSelected && `text-white ${typography.weight.semibold}`
231
260
  )}
232
261
  >
233
262
  {date.getDate()}
@@ -29,8 +29,8 @@ export interface CardProps extends ViewProps {
29
29
  onClose?: () => void;
30
30
  }
31
31
 
32
- const calloutStyle =
33
- 'bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800';
32
+ // Callout uses the DS info card variant colors
33
+ const calloutStyle = getCardVariantColors('info');
34
34
 
35
35
  const paddingStyles = {
36
36
  none: '',
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { View, Text, type ViewProps } from 'react-native';
3
3
  import { cn } from '../../lib/utils';
4
+ import { colors, designTokens } from '@sudobility/design';
4
5
 
5
6
  export type ChainType = 'evm' | 'solana' | 'bitcoin' | 'cosmos';
6
7
 
@@ -11,44 +12,61 @@ export interface ChainBadgeProps extends ViewProps {
11
12
  showLabel?: boolean;
12
13
  }
13
14
 
14
- const chainConfig: Record<
15
- ChainType,
16
- { label: string; emoji: string; bgColor: string; textColor: string }
17
- > = {
18
- evm: {
19
- label: 'EVM',
20
- emoji: '⟠',
21
- bgColor:
22
- 'bg-blue-50 dark:bg-blue-900/20 border-blue-200 dark:border-blue-800',
23
- textColor: 'text-blue-700 dark:text-blue-300',
24
- },
25
- solana: {
26
- label: 'SOL',
27
- emoji: '◎',
28
- bgColor:
29
- 'bg-purple-50 dark:bg-purple-900/20 border-purple-200 dark:border-purple-800',
30
- textColor: 'text-purple-700 dark:text-purple-300',
31
- },
32
- bitcoin: {
33
- label: 'BTC',
34
- emoji: '₿',
35
- bgColor:
36
- 'bg-orange-50 dark:bg-orange-900/20 border-orange-200 dark:border-orange-800',
37
- textColor: 'text-orange-700 dark:text-orange-300',
38
- },
39
- cosmos: {
40
- label: 'ATOM',
41
- emoji: '',
42
- bgColor:
43
- 'bg-indigo-50 dark:bg-indigo-900/20 border-indigo-200 dark:border-indigo-800',
44
- textColor: 'text-indigo-700 dark:text-indigo-300',
45
- },
15
+ /**
16
+ * Split combined DS badge color strings (which include both bg-* and text-*)
17
+ * into separate bg and text class strings.
18
+ */
19
+ function splitBadgeClasses(base: string, dark: string) {
20
+ const all = `${base} ${dark}`.split(' ');
21
+ return {
22
+ bg: all.filter(c => c.includes('bg-')).join(' '),
23
+ text: all.filter(c => c.includes('text-')).join(' '),
24
+ };
25
+ }
26
+
27
+ // Lazily derive chain colors from DS to avoid ESM issues in tests.
28
+ let _chainColors: ReturnType<typeof buildChainColors> | null = null;
29
+ function getChainColors() {
30
+ if (!_chainColors) _chainColors = buildChainColors();
31
+ return _chainColors;
32
+ }
33
+ function buildChainColors() {
34
+ const badge = colors.component.badge;
35
+ return {
36
+ evm: splitBadgeClasses(badge.ethereum.base, badge.ethereum.dark),
37
+ solana: splitBadgeClasses(badge.solana.base, badge.solana.dark),
38
+ bitcoin: splitBadgeClasses(badge.bitcoin.base, badge.bitcoin.dark),
39
+ // DS has no cosmos badge — use local fallback (indigo)
40
+ cosmos: {
41
+ bg: 'bg-indigo-50 dark:bg-indigo-900/20',
42
+ text: 'text-indigo-700 dark:text-indigo-300',
43
+ },
44
+ };
45
+ }
46
+
47
+ const chainMeta: Record<ChainType, { label: string; emoji: string }> = {
48
+ evm: { label: 'EVM', emoji: '⟠' },
49
+ solana: { label: 'SOL', emoji: '◎' },
50
+ bitcoin: { label: 'BTC', emoji: '₿' },
51
+ cosmos: { label: 'ATOM', emoji: '⚛' },
46
52
  };
47
53
 
48
54
  const sizeConfig = {
49
- sm: { padding: 'px-1.5 py-0.5', text: 'text-xs', gap: 'gap-0.5' },
50
- md: { padding: 'px-2 py-1', text: 'text-sm', gap: 'gap-1' },
51
- lg: { padding: 'px-2.5 py-1.5', text: 'text-base', gap: 'gap-1.5' },
55
+ sm: {
56
+ padding: 'px-1.5 py-0.5',
57
+ text: designTokens.typography.size.xs,
58
+ gap: 'gap-0.5',
59
+ },
60
+ md: {
61
+ padding: 'px-2 py-1',
62
+ text: designTokens.typography.size.sm,
63
+ gap: 'gap-1',
64
+ },
65
+ lg: {
66
+ padding: 'px-2.5 py-1.5',
67
+ text: designTokens.typography.size.base,
68
+ gap: 'gap-1.5',
69
+ },
52
70
  };
53
71
 
54
72
  export const ChainBadge: React.FC<ChainBadgeProps> = ({
@@ -58,27 +76,34 @@ export const ChainBadge: React.FC<ChainBadgeProps> = ({
58
76
  className,
59
77
  ...props
60
78
  }) => {
61
- const chain = chainConfig[chainType];
79
+ const chainColors = getChainColors()[chainType];
80
+ const meta = chainMeta[chainType];
62
81
  const sizeStyles = sizeConfig[size];
63
82
 
64
83
  return (
65
84
  <View
66
85
  className={cn(
67
86
  'flex-row items-center rounded-md border',
68
- chain.bgColor,
87
+ chainColors.bg,
69
88
  sizeStyles.padding,
70
89
  sizeStyles.gap,
71
90
  className
72
91
  )}
73
- accessibilityLabel={`${chain.label} chain`}
92
+ accessibilityLabel={`${meta.label} chain`}
74
93
  {...props}
75
94
  >
76
- <Text className={cn(sizeStyles.text, chain.textColor)}>
77
- {chain.emoji}
95
+ <Text className={cn(sizeStyles.text, chainColors.text)}>
96
+ {meta.emoji}
78
97
  </Text>
79
98
  {showLabel && (
80
- <Text className={cn('font-medium', sizeStyles.text, chain.textColor)}>
81
- {chain.label}
99
+ <Text
100
+ className={cn(
101
+ designTokens.typography.weight.medium,
102
+ sizeStyles.text,
103
+ chainColors.text
104
+ )}
105
+ >
106
+ {meta.label}
82
107
  </Text>
83
108
  )}
84
109
  </View>
@@ -2,6 +2,7 @@ import * as React from 'react';
2
2
  import { useState } from 'react';
3
3
  import { View, Text, Pressable, PressableProps } from 'react-native';
4
4
  import { cn } from '../../lib/utils';
5
+ import { colors, designTokens } from '@sudobility/design';
5
6
 
6
7
  export interface CheckboxProps extends Omit<PressableProps, 'onPress'> {
7
8
  /** Whether the checkbox is checked (controlled mode) */
@@ -54,6 +55,36 @@ export interface CheckboxProps extends Omit<PressableProps, 'onPress'> {
54
55
  * />
55
56
  * ```
56
57
  */
58
+
59
+ // Lazily derive checkbox colors from DS to avoid ESM issues in tests.
60
+ let _checkboxColors: ReturnType<typeof buildCheckboxColors> | null = null;
61
+ function getCheckboxColors() {
62
+ if (!_checkboxColors) _checkboxColors = buildCheckboxColors();
63
+ return _checkboxColors;
64
+ }
65
+ function buildCheckboxColors() {
66
+ // Extract solid bg colors from DS button variants for checked states
67
+ // DS button.primary.base contains "bg-blue-600 ... text-white"
68
+ // We only need the bg-* and border-* portions for checkbox checked state
69
+ function extractCheckedColor(base: string) {
70
+ const parts = base.split(' ');
71
+ const bg =
72
+ parts.find(
73
+ c =>
74
+ c.startsWith('bg-') && !c.includes('hover:') && !c.includes('active:')
75
+ ) || '';
76
+ // For checkbox, border matches bg color
77
+ return `${bg} ${bg.replace('bg-', 'border-')}`;
78
+ }
79
+ const btn = colors.component.button;
80
+ return {
81
+ primary: extractCheckedColor(btn.primary.base),
82
+ success: extractCheckedColor(btn.success.base),
83
+ warning: 'bg-yellow-600 border-yellow-600', // DS has no yellow button; local fallback
84
+ error: extractCheckedColor(btn.destructive.base),
85
+ } as Record<string, string>;
86
+ }
87
+
57
88
  export const Checkbox: React.FC<CheckboxProps> = ({
58
89
  checked: controlledChecked,
59
90
  defaultChecked = false,
@@ -80,43 +111,37 @@ export const Checkbox: React.FC<CheckboxProps> = ({
80
111
  sm: {
81
112
  box: 'w-4 h-4',
82
113
  check: 'w-2 h-2',
83
- text: 'text-sm',
84
- desc: 'text-xs',
114
+ text: designTokens.typography.size.sm,
115
+ desc: designTokens.typography.size.xs,
85
116
  },
86
117
  md: {
87
118
  box: 'w-5 h-5',
88
119
  check: 'w-3 h-3',
89
- text: 'text-base',
90
- desc: 'text-sm',
120
+ text: designTokens.typography.size.base,
121
+ desc: designTokens.typography.size.sm,
91
122
  },
92
123
  lg: {
93
124
  box: 'w-6 h-6',
94
125
  check: 'w-4 h-4',
95
- text: 'text-lg',
96
- desc: 'text-base',
126
+ text: designTokens.typography.size.lg,
127
+ desc: designTokens.typography.size.base,
97
128
  },
98
129
  };
99
130
 
100
131
  const getVariantClasses = () => {
132
+ const checkedColors = getCheckboxColors();
101
133
  if (error) {
102
134
  return checked
103
- ? 'bg-red-600 border-red-600'
135
+ ? checkedColors.error
104
136
  : 'border-red-600 dark:border-red-500';
105
137
  }
106
138
 
139
+ const unchecked = 'border-gray-300 dark:border-gray-600';
107
140
  const variantClasses = {
108
- primary: checked
109
- ? 'bg-blue-600 border-blue-600'
110
- : 'border-gray-300 dark:border-gray-600',
111
- success: checked
112
- ? 'bg-green-600 border-green-600'
113
- : 'border-gray-300 dark:border-gray-600',
114
- warning: checked
115
- ? 'bg-yellow-600 border-yellow-600'
116
- : 'border-gray-300 dark:border-gray-600',
117
- error: checked
118
- ? 'bg-red-600 border-red-600'
119
- : 'border-gray-300 dark:border-gray-600',
141
+ primary: checked ? checkedColors.primary : unchecked,
142
+ success: checked ? checkedColors.success : unchecked,
143
+ warning: checked ? checkedColors.warning : unchecked,
144
+ error: checked ? checkedColors.error : unchecked,
120
145
  };
121
146
 
122
147
  return variantClasses[variant];
@@ -191,7 +216,9 @@ export const Checkbox: React.FC<CheckboxProps> = ({
191
216
  )}
192
217
  </Pressable>
193
218
  {errorMessage && (
194
- <Text className='mt-1 text-sm text-red-600 dark:text-red-400'>
219
+ <Text
220
+ className={`mt-1 ${designTokens.typography.size.sm} text-red-600 dark:text-red-400`}
221
+ >
195
222
  {errorMessage}
196
223
  </Text>
197
224
  )}
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { Text, View } from 'react-native';
3
3
  import { cn } from '../../lib/utils';
4
+ import { colors, designTokens } from '@sudobility/design';
4
5
 
5
6
  export interface CodeProps {
6
7
  /** Code content */
@@ -30,6 +31,45 @@ export interface CodeProps {
30
31
  * </Code>
31
32
  * ```
32
33
  */
34
+
35
+ // Lazily derive code colors from DS to avoid ESM issues in tests.
36
+ let _codeColors: ReturnType<typeof buildCodeColors> | null = null;
37
+ function getCodeColors() {
38
+ if (!_codeColors) _codeColors = buildCodeColors();
39
+ return _codeColors;
40
+ }
41
+ function buildCodeColors() {
42
+ const alert = colors.component.alert;
43
+ // Split combined DS classes into separate bg/text for RN
44
+ function splitClasses(base: string, dark: string) {
45
+ const all = `${base} ${dark}`.split(' ');
46
+ return {
47
+ bg: all.filter(c => c.includes('bg-')).join(' '),
48
+ text: all.filter(c => c.includes('text-')).join(' '),
49
+ };
50
+ }
51
+ const info = splitClasses(alert.info.base, alert.info.dark);
52
+ const success = splitClasses(alert.success.base, alert.success.dark);
53
+ const warning = splitClasses(alert.warning.base, alert.warning.dark);
54
+ const error = splitClasses(alert.error.base, alert.error.dark);
55
+ return {
56
+ bg: {
57
+ default: 'bg-gray-100 dark:bg-gray-800',
58
+ primary: info.bg,
59
+ success: success.bg,
60
+ warning: warning.bg,
61
+ danger: error.bg,
62
+ } as Record<string, string>,
63
+ text: {
64
+ default: 'text-gray-900 dark:text-gray-100',
65
+ primary: info.text,
66
+ success: success.text,
67
+ warning: warning.text,
68
+ danger: error.text,
69
+ } as Record<string, string>,
70
+ };
71
+ }
72
+
33
73
  export const Code: React.FC<CodeProps> = ({
34
74
  children,
35
75
  size = 'md',
@@ -38,28 +78,14 @@ export const Code: React.FC<CodeProps> = ({
38
78
  }) => {
39
79
  // Size configurations
40
80
  const sizeClasses = {
41
- sm: 'text-xs px-1 py-0.5',
42
- md: 'text-sm px-1.5 py-0.5',
43
- lg: 'text-base px-2 py-1',
44
- };
45
-
46
- // Variant configurations - background
47
- const variantBgClasses = {
48
- default: 'bg-gray-100 dark:bg-gray-800',
49
- primary: 'bg-blue-50 dark:bg-blue-900/30',
50
- success: 'bg-green-50 dark:bg-green-900/30',
51
- warning: 'bg-yellow-50 dark:bg-yellow-900/30',
52
- danger: 'bg-red-50 dark:bg-red-900/30',
81
+ sm: `${designTokens.typography.size.xs} px-1 py-0.5`,
82
+ md: `${designTokens.typography.size.sm} px-1.5 py-0.5`,
83
+ lg: `${designTokens.typography.size.base} px-2 py-1`,
53
84
  };
54
85
 
55
- // Variant configurations - text
56
- const variantTextClasses = {
57
- default: 'text-gray-900 dark:text-gray-100',
58
- primary: 'text-blue-700 dark:text-blue-300',
59
- success: 'text-green-700 dark:text-green-300',
60
- warning: 'text-yellow-700 dark:text-yellow-300',
61
- danger: 'text-red-700 dark:text-red-300',
62
- };
86
+ const codeColors = getCodeColors();
87
+ const variantBgClasses = codeColors.bg;
88
+ const variantTextClasses = codeColors.text;
63
89
 
64
90
  return (
65
91
  <View
@@ -71,7 +97,11 @@ export const Code: React.FC<CodeProps> = ({
71
97
  )}
72
98
  >
73
99
  <Text
74
- className={cn('font-mono font-medium', variantTextClasses[variant])}
100
+ className={cn(
101
+ designTokens.typography.family.mono,
102
+ designTokens.typography.weight.medium,
103
+ variantTextClasses[variant]
104
+ )}
75
105
  style={{ fontFamily: 'monospace' }}
76
106
  >
77
107
  {children}
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { View, Text, ScrollView } from 'react-native';
3
3
  import { cn } from '../../lib/utils';
4
+ import { colors, designTokens } from '@sudobility/design';
4
5
 
5
6
  export interface CodeDisplayProps {
6
7
  /** Code or text to display */
@@ -40,6 +41,36 @@ export interface CodeDisplayProps {
40
41
  * </CodeDisplay>
41
42
  * ```
42
43
  */
44
+
45
+ // Lazily derive display colors from DS to avoid ESM issues in tests.
46
+ let _displayColors: ReturnType<typeof buildDisplayColors> | null = null;
47
+ function getDisplayColors() {
48
+ if (!_displayColors) _displayColors = buildDisplayColors();
49
+ return _displayColors;
50
+ }
51
+ function buildDisplayColors() {
52
+ const alert = colors.component.alert;
53
+ function splitClasses(base: string, dark: string) {
54
+ const all = `${base} ${dark}`.split(' ');
55
+ return {
56
+ text: all.filter(c => c.includes('text-')).join(' '),
57
+ bg: all.filter(c => c.includes('bg-')).join(' '),
58
+ };
59
+ }
60
+ const info = splitClasses(alert.info.base, alert.info.dark);
61
+ const success = splitClasses(alert.success.base, alert.success.dark);
62
+ const warning = splitClasses(alert.warning.base, alert.warning.dark);
63
+ return {
64
+ primary: `${info.text} ${info.bg}`,
65
+ // secondary uses purple — no DS mapping, keep local
66
+ secondary:
67
+ 'text-purple-600 dark:text-purple-400 bg-purple-50 dark:bg-purple-900/30',
68
+ success: `${success.text} ${success.bg}`,
69
+ warning: `${warning.text} ${warning.bg}`,
70
+ neutral: 'text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-800',
71
+ } as Record<string, string>;
72
+ }
73
+
43
74
  export const CodeDisplay: React.FC<CodeDisplayProps> = ({
44
75
  children,
45
76
  variant = 'primary',
@@ -49,34 +80,25 @@ export const CodeDisplay: React.FC<CodeDisplayProps> = ({
49
80
  wrap = false,
50
81
  className,
51
82
  }) => {
52
- // Color variant configurations
53
- const variantClasses = {
54
- primary: 'text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/30',
55
- secondary:
56
- 'text-purple-600 dark:text-purple-400 bg-purple-50 dark:bg-purple-900/30',
57
- success:
58
- 'text-green-600 dark:text-green-400 bg-green-50 dark:bg-green-900/30',
59
- warning:
60
- 'text-yellow-700 dark:text-yellow-400 bg-yellow-50 dark:bg-yellow-900/30',
61
- neutral: 'text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-800',
62
- };
83
+ // Color variant configurations from DS
84
+ const variantClasses = getDisplayColors();
63
85
 
64
- // Size configurations
86
+ // Size configurations using DS typography tokens
65
87
  const sizeClasses = {
66
88
  xs: {
67
- text: 'text-xs',
89
+ text: designTokens.typography.size.xs,
68
90
  padding: inline ? 'px-1.5 py-0.5' : 'px-2 py-1',
69
91
  },
70
92
  sm: {
71
- text: 'text-sm',
93
+ text: designTokens.typography.size.sm,
72
94
  padding: inline ? 'px-2 py-0.5' : 'px-3 py-1.5',
73
95
  },
74
96
  md: {
75
- text: 'text-base',
97
+ text: designTokens.typography.size.base,
76
98
  padding: inline ? 'px-2.5 py-1' : 'px-4 py-2',
77
99
  },
78
100
  lg: {
79
- text: 'text-lg',
101
+ text: designTokens.typography.size.lg,
80
102
  padding: inline ? 'px-3 py-1' : 'px-4 py-2',
81
103
  },
82
104
  };
@@ -90,14 +112,18 @@ export const CodeDisplay: React.FC<CodeDisplayProps> = ({
90
112
 
91
113
  const sizeConfig = sizeClasses[size];
92
114
 
93
- // Extract background and text color classes
94
- const [textColorClass, bgClass] = variantClasses[variant].split(' ');
115
+ // Extract background and text color classes from combined variant string
116
+ const variantParts = variantClasses[variant].split(' ');
117
+ const textColorClass = variantParts
118
+ .filter(c => c.includes('text-'))
119
+ .join(' ');
120
+ const bgClass = variantParts.filter(c => c.includes('bg-')).join(' ');
95
121
 
96
122
  if (inline) {
97
123
  return (
98
124
  <Text
99
125
  className={cn(
100
- 'font-mono rounded-lg',
126
+ `${designTokens.typography.family.mono} rounded-lg`,
101
127
  textColorClass,
102
128
  bgClass,
103
129
  sizeConfig.text,
@@ -113,7 +139,7 @@ export const CodeDisplay: React.FC<CodeDisplayProps> = ({
113
139
  const content = (
114
140
  <Text
115
141
  className={cn(
116
- 'font-mono',
142
+ designTokens.typography.family.mono,
117
143
  textColorClass,
118
144
  sizeConfig.text,
119
145
  !inline && alignClasses[align],
@@ -10,6 +10,9 @@ import {
10
10
  UIManager,
11
11
  } from 'react-native';
12
12
  import { cn } from '../../lib/utils';
13
+ import { designTokens } from '@sudobility/design';
14
+
15
+ const { typography } = designTokens;
13
16
 
14
17
  // Enable LayoutAnimation on Android
15
18
  if (
@@ -126,7 +129,8 @@ export const CollapsibleSection: React.FC<CollapsibleSectionProps> = ({
126
129
  >
127
130
  <Text
128
131
  className={cn(
129
- 'text-base font-medium',
132
+ typography.size.base,
133
+ typography.weight.medium,
130
134
  isSelected && !selectedSubsection
131
135
  ? 'text-blue-700 dark:text-blue-300'
132
136
  : 'text-gray-700 dark:text-gray-300'
@@ -145,7 +149,7 @@ export const CollapsibleSection: React.FC<CollapsibleSectionProps> = ({
145
149
  accessibilityLabel={isExpanded ? 'Collapse' : 'Expand'}
146
150
  >
147
151
  <Animated.View style={{ transform: [{ rotate: rotation }] }}>
148
- <Text className='text-gray-500 text-lg'>›</Text>
152
+ <Text className={cn('text-gray-500', typography.size.lg)}>›</Text>
149
153
  </Animated.View>
150
154
  </Pressable>
151
155
  )}
@@ -172,7 +176,7 @@ export const CollapsibleSection: React.FC<CollapsibleSectionProps> = ({
172
176
  >
173
177
  <Text
174
178
  className={cn(
175
- 'text-sm',
179
+ typography.size.sm,
176
180
  selectedSubsection === subsection.id
177
181
  ? 'text-blue-700 dark:text-blue-300'
178
182
  : 'text-gray-600 dark:text-gray-400'
@@ -10,6 +10,7 @@ import {
10
10
  TouchableWithoutFeedback,
11
11
  } from 'react-native';
12
12
  import { cn } from '../../lib/utils';
13
+ import { colors } from '@sudobility/design';
13
14
 
14
15
  export interface ComboboxOption {
15
16
  /** Option value */
@@ -143,7 +144,7 @@ export const Combobox: React.FC<ComboboxProps> = ({
143
144
  value={searchQuery}
144
145
  onChangeText={setSearchQuery}
145
146
  placeholder={searchPlaceholder}
146
- placeholderTextColor='#9ca3af'
147
+ placeholderTextColor={colors.raw.neutral[400]}
147
148
  autoFocus
148
149
  className='px-3 py-2 text-sm bg-gray-50 dark:bg-gray-800 text-gray-900 dark:text-white rounded-md'
149
150
  />
@@ -11,6 +11,7 @@ import {
11
11
  Platform,
12
12
  } from 'react-native';
13
13
  import { cn } from '../../lib/utils';
14
+ import { colors } from '@sudobility/design';
14
15
 
15
16
  export interface CommandItem {
16
17
  /** Item ID */
@@ -159,7 +160,7 @@ export const Command: React.FC<CommandProps> = ({
159
160
  value={searchQuery}
160
161
  onChangeText={setSearchQuery}
161
162
  placeholder={placeholder}
162
- placeholderTextColor='#9ca3af'
163
+ placeholderTextColor={colors.raw.neutral[400]}
163
164
  className='flex-1 text-gray-900 dark:text-white text-base'
164
165
  autoCapitalize='none'
165
166
  autoCorrect={false}