@urbint/cl 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/.cursor/rules +313 -0
  2. package/.rnstorybook/index.ts +11 -0
  3. package/.rnstorybook/main.ts +8 -0
  4. package/.rnstorybook/preview.tsx +14 -0
  5. package/.rnstorybook/storybook.requires.ts +49 -0
  6. package/.storybook/main.ts +16 -0
  7. package/.storybook/preview.ts +32 -0
  8. package/.storybook/vitest.setup.ts +7 -0
  9. package/App.tsx +422 -0
  10. package/README.md +229 -0
  11. package/app.json +33 -0
  12. package/assets/adaptive-icon.png +0 -0
  13. package/assets/favicon.png +0 -0
  14. package/assets/icon.png +0 -0
  15. package/assets/splash-icon.png +0 -0
  16. package/babel.config.js +16 -0
  17. package/docs/components/CodeBlock.tsx +80 -0
  18. package/docs/components/PropTable.tsx +93 -0
  19. package/docs/components/Sidebar.tsx +199 -0
  20. package/docs/components/index.ts +8 -0
  21. package/docs/data/colorTokens.ts +70 -0
  22. package/docs/data/componentData.tsx +1685 -0
  23. package/docs/data/index.ts +7 -0
  24. package/docs/index.ts +19 -0
  25. package/docs/navigation.ts +94 -0
  26. package/docs/pages/ColorsPage.tsx +226 -0
  27. package/docs/pages/ComponentPage.tsx +235 -0
  28. package/docs/pages/InstallationPage.tsx +232 -0
  29. package/docs/pages/IntroductionPage.tsx +163 -0
  30. package/docs/pages/ThemingPage.tsx +251 -0
  31. package/docs/pages/index.ts +10 -0
  32. package/docs/theme.ts +64 -0
  33. package/docs/types.ts +54 -0
  34. package/index.ts +8 -0
  35. package/llms.txt +1893 -0
  36. package/mcp-config.example.json +10 -0
  37. package/mcp-server/README.md +192 -0
  38. package/mcp-server/package-lock.json +1707 -0
  39. package/mcp-server/package.json +38 -0
  40. package/mcp-server/src/index.ts +1136 -0
  41. package/mcp-server/src/registry/components.ts +1446 -0
  42. package/mcp-server/src/registry/index.ts +3 -0
  43. package/mcp-server/src/registry/tokens.ts +256 -0
  44. package/mcp-server/tsconfig.json +19 -0
  45. package/package.json +92 -0
  46. package/src/components/Accordion/Accordion.stories.tsx +226 -0
  47. package/src/components/Accordion/Accordion.tsx +255 -0
  48. package/src/components/Accordion/index.ts +12 -0
  49. package/src/components/ActionSheet/ActionSheet.stories.tsx +393 -0
  50. package/src/components/ActionSheet/ActionSheet.tsx +258 -0
  51. package/src/components/ActionSheet/index.ts +2 -0
  52. package/src/components/Alert/Alert.stories.tsx +165 -0
  53. package/src/components/Alert/Alert.tsx +164 -0
  54. package/src/components/Alert/index.ts +2 -0
  55. package/src/components/AlertDialog/AlertDialog.stories.tsx +330 -0
  56. package/src/components/AlertDialog/AlertDialog.tsx +234 -0
  57. package/src/components/AlertDialog/index.ts +2 -0
  58. package/src/components/Avatar/Avatar.stories.tsx +154 -0
  59. package/src/components/Avatar/Avatar.tsx +219 -0
  60. package/src/components/Avatar/index.ts +2 -0
  61. package/src/components/Badge/Badge.stories.tsx +146 -0
  62. package/src/components/Badge/Badge.tsx +125 -0
  63. package/src/components/Badge/index.ts +2 -0
  64. package/src/components/Box/Box.stories.tsx +192 -0
  65. package/src/components/Box/Box.tsx +184 -0
  66. package/src/components/Box/index.ts +2 -0
  67. package/src/components/Button/Button.stories.tsx +157 -0
  68. package/src/components/Button/Button.tsx +180 -0
  69. package/src/components/Button/index.ts +2 -0
  70. package/src/components/Card/Card.stories.tsx +145 -0
  71. package/src/components/Card/Card.tsx +169 -0
  72. package/src/components/Card/index.ts +11 -0
  73. package/src/components/Center/Center.stories.tsx +215 -0
  74. package/src/components/Center/Center.tsx +29 -0
  75. package/src/components/Center/index.ts +2 -0
  76. package/src/components/Checkbox/Checkbox.stories.tsx +94 -0
  77. package/src/components/Checkbox/Checkbox.tsx +242 -0
  78. package/src/components/Checkbox/index.ts +2 -0
  79. package/src/components/DatePicker/DatePicker.stories.tsx +623 -0
  80. package/src/components/DatePicker/DatePicker.tsx +1228 -0
  81. package/src/components/DatePicker/index.ts +8 -0
  82. package/src/components/Divider/Divider.stories.tsx +224 -0
  83. package/src/components/Divider/Divider.tsx +73 -0
  84. package/src/components/Divider/index.ts +2 -0
  85. package/src/components/Drawer/Drawer.stories.tsx +414 -0
  86. package/src/components/Drawer/Drawer.tsx +342 -0
  87. package/src/components/Drawer/index.ts +11 -0
  88. package/src/components/Fab/Fab.stories.tsx +360 -0
  89. package/src/components/Fab/Fab.tsx +185 -0
  90. package/src/components/Fab/index.ts +2 -0
  91. package/src/components/FormControl/FormControl.stories.tsx +276 -0
  92. package/src/components/FormControl/FormControl.tsx +185 -0
  93. package/src/components/FormControl/index.ts +12 -0
  94. package/src/components/Grid/Grid.stories.tsx +244 -0
  95. package/src/components/Grid/Grid.tsx +93 -0
  96. package/src/components/Grid/index.ts +2 -0
  97. package/src/components/HStack/HStack.stories.tsx +230 -0
  98. package/src/components/HStack/HStack.tsx +80 -0
  99. package/src/components/HStack/index.ts +2 -0
  100. package/src/components/Heading/Heading.stories.tsx +111 -0
  101. package/src/components/Heading/Heading.tsx +85 -0
  102. package/src/components/Heading/index.ts +2 -0
  103. package/src/components/Icon/Icon.stories.tsx +320 -0
  104. package/src/components/Icon/Icon.tsx +117 -0
  105. package/src/components/Icon/index.ts +2 -0
  106. package/src/components/Image/Image.stories.tsx +357 -0
  107. package/src/components/Image/Image.tsx +168 -0
  108. package/src/components/Image/index.ts +2 -0
  109. package/src/components/Input/Input.stories.tsx +164 -0
  110. package/src/components/Input/Input.tsx +274 -0
  111. package/src/components/Input/index.ts +2 -0
  112. package/src/components/Link/Link.stories.tsx +187 -0
  113. package/src/components/Link/Link.tsx +104 -0
  114. package/src/components/Link/index.ts +2 -0
  115. package/src/components/Menu/Menu.stories.tsx +363 -0
  116. package/src/components/Menu/Menu.tsx +238 -0
  117. package/src/components/Menu/index.ts +2 -0
  118. package/src/components/Modal/Modal.stories.tsx +156 -0
  119. package/src/components/Modal/Modal.tsx +280 -0
  120. package/src/components/Modal/index.ts +11 -0
  121. package/src/components/Popover/Popover.stories.tsx +330 -0
  122. package/src/components/Popover/Popover.tsx +315 -0
  123. package/src/components/Popover/index.ts +11 -0
  124. package/src/components/Portal/Portal.stories.tsx +376 -0
  125. package/src/components/Portal/Portal.tsx +100 -0
  126. package/src/components/Portal/index.ts +2 -0
  127. package/src/components/Pressable/Pressable.stories.tsx +338 -0
  128. package/src/components/Pressable/Pressable.tsx +71 -0
  129. package/src/components/Pressable/index.ts +2 -0
  130. package/src/components/Progress/Progress.stories.tsx +131 -0
  131. package/src/components/Progress/Progress.tsx +219 -0
  132. package/src/components/Progress/index.ts +2 -0
  133. package/src/components/Radio/Radio.stories.tsx +101 -0
  134. package/src/components/Radio/Radio.tsx +234 -0
  135. package/src/components/Radio/index.ts +2 -0
  136. package/src/components/Select/Select.stories.tsx +908 -0
  137. package/src/components/Select/Select.tsx +659 -0
  138. package/src/components/Select/index.ts +8 -0
  139. package/src/components/Skeleton/Skeleton.stories.tsx +154 -0
  140. package/src/components/Skeleton/Skeleton.tsx +192 -0
  141. package/src/components/Skeleton/index.ts +8 -0
  142. package/src/components/Slider/Slider.stories.tsx +363 -0
  143. package/src/components/Slider/Slider.tsx +209 -0
  144. package/src/components/Slider/index.ts +2 -0
  145. package/src/components/Spinner/Spinner.stories.tsx +108 -0
  146. package/src/components/Spinner/Spinner.tsx +121 -0
  147. package/src/components/Spinner/index.ts +2 -0
  148. package/src/components/Switch/Switch.stories.tsx +116 -0
  149. package/src/components/Switch/Switch.tsx +172 -0
  150. package/src/components/Switch/index.ts +2 -0
  151. package/src/components/Table/Table.stories.tsx +417 -0
  152. package/src/components/Table/Table.tsx +233 -0
  153. package/src/components/Table/index.ts +2 -0
  154. package/src/components/Text/Text.stories.tsx +93 -0
  155. package/src/components/Text/Text.tsx +119 -0
  156. package/src/components/Text/index.ts +2 -0
  157. package/src/components/Textarea/Textarea.stories.tsx +280 -0
  158. package/src/components/Textarea/Textarea.tsx +212 -0
  159. package/src/components/Textarea/index.ts +2 -0
  160. package/src/components/Toast/Toast.stories.tsx +446 -0
  161. package/src/components/Toast/Toast.tsx +221 -0
  162. package/src/components/Toast/index.ts +2 -0
  163. package/src/components/Tooltip/Tooltip.stories.tsx +354 -0
  164. package/src/components/Tooltip/Tooltip.tsx +261 -0
  165. package/src/components/Tooltip/index.ts +2 -0
  166. package/src/components/VStack/VStack.stories.tsx +183 -0
  167. package/src/components/VStack/VStack.tsx +76 -0
  168. package/src/components/VStack/index.ts +2 -0
  169. package/src/components/index.ts +62 -0
  170. package/src/hooks/index.ts +7 -0
  171. package/src/hooks/useControllableState.ts +41 -0
  172. package/src/hooks/useDisclosure.ts +51 -0
  173. package/src/index.ts +22 -0
  174. package/src/stories/Button.stories.tsx +53 -0
  175. package/src/stories/Button.tsx +101 -0
  176. package/src/stories/Configure.mdx +364 -0
  177. package/src/stories/Header.stories.tsx +33 -0
  178. package/src/stories/Header.tsx +75 -0
  179. package/src/stories/Page.stories.tsx +25 -0
  180. package/src/stories/Page.tsx +154 -0
  181. package/src/stories/assets/accessibility.png +0 -0
  182. package/src/stories/assets/accessibility.svg +1 -0
  183. package/src/stories/assets/addon-library.png +0 -0
  184. package/src/stories/assets/assets.png +0 -0
  185. package/src/stories/assets/avif-test-image.avif +0 -0
  186. package/src/stories/assets/context.png +0 -0
  187. package/src/stories/assets/discord.svg +1 -0
  188. package/src/stories/assets/docs.png +0 -0
  189. package/src/stories/assets/figma-plugin.png +0 -0
  190. package/src/stories/assets/github.svg +1 -0
  191. package/src/stories/assets/share.png +0 -0
  192. package/src/stories/assets/styling.png +0 -0
  193. package/src/stories/assets/testing.png +0 -0
  194. package/src/stories/assets/theming.png +0 -0
  195. package/src/stories/assets/tutorials.svg +1 -0
  196. package/src/stories/assets/youtube.svg +1 -0
  197. package/src/styles/index.ts +7 -0
  198. package/src/styles/tokens.ts +318 -0
  199. package/src/styles/unistyles.ts +254 -0
  200. package/src/utils/createContext.tsx +25 -0
  201. package/src/utils/index.ts +7 -0
  202. package/src/utils/mergeRefs.ts +21 -0
  203. package/tsconfig.json +26 -0
  204. package/urbint-cl-1.0.0.tgz +0 -0
  205. package/vitest.config.ts +37 -0
  206. package/vitest.shims.d.ts +1 -0
@@ -0,0 +1,338 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { Pressable } from './Pressable';
3
+ import { VStack } from '../VStack';
4
+ import { HStack } from '../HStack';
5
+ import { Text } from '../Text';
6
+ import { Box } from '../Box';
7
+ import { colors, spacing, borderRadius, elevation } from '../../styles/tokens';
8
+
9
+ const meta: Meta<typeof Pressable> = {
10
+ title: 'Action/Pressable',
11
+ component: Pressable,
12
+ argTypes: {
13
+ pressedOpacity: { control: { type: 'range', min: 0, max: 1, step: 0.1 } },
14
+ pressedScale: { control: { type: 'range', min: 0.8, max: 1, step: 0.02 } },
15
+ },
16
+ args: {
17
+ pressedOpacity: 0.7,
18
+ },
19
+ };
20
+
21
+ export default meta;
22
+
23
+ type Story = StoryObj<typeof Pressable>;
24
+
25
+ export const Default: Story = {
26
+ render: (args) => (
27
+ <Pressable {...args} onPress={() => console.log('Pressed')}>
28
+ <Box p={spacing.lg} bg={colors.brand.blue} rounded="md">
29
+ <Text style={{ color: 'white' }}>Press Me</Text>
30
+ </Box>
31
+ </Pressable>
32
+ ),
33
+ };
34
+
35
+ export const OpacityFeedback: Story = {
36
+ render: () => (
37
+ <VStack space={spacing.lg}>
38
+ <Text weight="semiBold">Opacity Feedback</Text>
39
+ <HStack space={spacing.lg}>
40
+ <VStack space={spacing.xs} alignItems="center">
41
+ <Pressable pressedOpacity={0.3} onPress={() => console.log('Pressed')}>
42
+ <Box p={spacing.lg} bg={colors.brand.blue} rounded="md">
43
+ <Text style={{ color: 'white' }}>0.3</Text>
44
+ </Box>
45
+ </Pressable>
46
+ <Text size="sm" color={colors.text.secondary}>opacity: 0.3</Text>
47
+ </VStack>
48
+ <VStack space={spacing.xs} alignItems="center">
49
+ <Pressable pressedOpacity={0.5} onPress={() => console.log('Pressed')}>
50
+ <Box p={spacing.lg} bg={colors.brand.blue} rounded="md">
51
+ <Text style={{ color: 'white' }}>0.5</Text>
52
+ </Box>
53
+ </Pressable>
54
+ <Text size="sm" color={colors.text.secondary}>opacity: 0.5</Text>
55
+ </VStack>
56
+ <VStack space={spacing.xs} alignItems="center">
57
+ <Pressable pressedOpacity={0.7} onPress={() => console.log('Pressed')}>
58
+ <Box p={spacing.lg} bg={colors.brand.blue} rounded="md">
59
+ <Text style={{ color: 'white' }}>0.7</Text>
60
+ </Box>
61
+ </Pressable>
62
+ <Text size="sm" color={colors.text.secondary}>opacity: 0.7</Text>
63
+ </VStack>
64
+ <VStack space={spacing.xs} alignItems="center">
65
+ <Pressable pressedOpacity={1} onPress={() => console.log('Pressed')}>
66
+ <Box p={spacing.lg} bg={colors.brand.blue} rounded="md">
67
+ <Text style={{ color: 'white' }}>1.0</Text>
68
+ </Box>
69
+ </Pressable>
70
+ <Text size="sm" color={colors.text.secondary}>opacity: 1.0</Text>
71
+ </VStack>
72
+ </HStack>
73
+ </VStack>
74
+ ),
75
+ };
76
+
77
+ export const ScaleFeedback: Story = {
78
+ render: () => (
79
+ <VStack space={spacing.lg}>
80
+ <Text weight="semiBold">Scale Feedback</Text>
81
+ <HStack space={spacing.lg}>
82
+ <VStack space={spacing.xs} alignItems="center">
83
+ <Pressable pressedScale={0.9} pressedOpacity={1} onPress={() => console.log('Pressed')}>
84
+ <Box p={spacing.lg} bg={colors.feedback.success.content} rounded="md">
85
+ <Text style={{ color: 'white' }}>0.9</Text>
86
+ </Box>
87
+ </Pressable>
88
+ <Text size="sm" color={colors.text.secondary}>scale: 0.9</Text>
89
+ </VStack>
90
+ <VStack space={spacing.xs} alignItems="center">
91
+ <Pressable pressedScale={0.95} pressedOpacity={1} onPress={() => console.log('Pressed')}>
92
+ <Box p={spacing.lg} bg={colors.feedback.success.content} rounded="md">
93
+ <Text style={{ color: 'white' }}>0.95</Text>
94
+ </Box>
95
+ </Pressable>
96
+ <Text size="sm" color={colors.text.secondary}>scale: 0.95</Text>
97
+ </VStack>
98
+ <VStack space={spacing.xs} alignItems="center">
99
+ <Pressable pressedScale={0.98} pressedOpacity={1} onPress={() => console.log('Pressed')}>
100
+ <Box p={spacing.lg} bg={colors.feedback.success.content} rounded="md">
101
+ <Text style={{ color: 'white' }}>0.98</Text>
102
+ </Box>
103
+ </Pressable>
104
+ <Text size="sm" color={colors.text.secondary}>scale: 0.98</Text>
105
+ </VStack>
106
+ </HStack>
107
+ </VStack>
108
+ ),
109
+ };
110
+
111
+ export const CombinedFeedback: Story = {
112
+ render: () => (
113
+ <VStack space={spacing.lg}>
114
+ <Text weight="semiBold">Combined Opacity + Scale</Text>
115
+ <Pressable
116
+ pressedOpacity={0.8}
117
+ pressedScale={0.95}
118
+ onPress={() => console.log('Pressed')}
119
+ >
120
+ <Box p={20} bg={colors.badge.purple} rounded="lg">
121
+ <Text style={{ color: 'white' }}>Press for combined effect</Text>
122
+ </Box>
123
+ </Pressable>
124
+ </VStack>
125
+ ),
126
+ };
127
+
128
+ export const CustomPressedStyle: Story = {
129
+ render: () => (
130
+ <VStack space={spacing.lg}>
131
+ <Text weight="semiBold">Custom Pressed Style</Text>
132
+ <Pressable
133
+ pressedOpacity={1}
134
+ pressedStyle={{ backgroundColor: colors.brand.blue }}
135
+ onPress={() => console.log('Pressed')}
136
+ >
137
+ <Box p={spacing.lg} bg={colors.brand.blue} rounded="md">
138
+ <Text style={{ color: 'white' }}>Background changes on press</Text>
139
+ </Box>
140
+ </Pressable>
141
+ </VStack>
142
+ ),
143
+ };
144
+
145
+ export const CardPressable: Story = {
146
+ render: () => (
147
+ <VStack space={spacing.lg}>
148
+ <Text weight="semiBold">Pressable Cards</Text>
149
+ <VStack space={spacing.md}>
150
+ <Pressable
151
+ pressedOpacity={0.9}
152
+ pressedScale={0.98}
153
+ onPress={() => console.log('Card 1 pressed')}
154
+ >
155
+ <Box p={spacing.lg} bg={colors.white} rounded="lg" shadow="10">
156
+ <VStack space={spacing.sm}>
157
+ <Text weight="semiBold">Clickable Card</Text>
158
+ <Text size="sm" color={colors.text.secondary}>
159
+ Press this card to navigate somewhere
160
+ </Text>
161
+ </VStack>
162
+ </Box>
163
+ </Pressable>
164
+ <Pressable
165
+ pressedOpacity={0.9}
166
+ pressedScale={0.98}
167
+ onPress={() => console.log('Card 2 pressed')}
168
+ >
169
+ <Box p={spacing.lg} bg={colors.white} rounded="lg" shadow="10">
170
+ <VStack space={spacing.sm}>
171
+ <Text weight="semiBold">Another Card</Text>
172
+ <Text size="sm" color={colors.text.secondary}>
173
+ This card also responds to press
174
+ </Text>
175
+ </VStack>
176
+ </Box>
177
+ </Pressable>
178
+ </VStack>
179
+ </VStack>
180
+ ),
181
+ };
182
+
183
+ export const ListItems: Story = {
184
+ render: () => (
185
+ <VStack space={spacing.lg}>
186
+ <Text weight="semiBold">Pressable List Items</Text>
187
+ <Box bg={colors.white} rounded="lg" shadow="10" overflow="hidden">
188
+ {['Notifications', 'Privacy', 'Security', 'Help & Support'].map((item, index, arr) => (
189
+ <Pressable
190
+ key={item}
191
+ pressedOpacity={1}
192
+ pressedStyle={{ backgroundColor: colors.background.secondary }}
193
+ onPress={() => console.log(`${item} pressed`)}
194
+ >
195
+ <Box p={spacing.lg} borderBottomWidth={index < arr.length - 1 ? 1 : 0} borderColor={colors.border.default}>
196
+ <HStack justifyContent="space-between" alignItems="center">
197
+ <Text>{item}</Text>
198
+ <Text color={colors.text.disabled}>›</Text>
199
+ </HStack>
200
+ </Box>
201
+ </Pressable>
202
+ ))}
203
+ </Box>
204
+ </VStack>
205
+ ),
206
+ };
207
+
208
+ export const IconButtons: Story = {
209
+ render: () => (
210
+ <VStack space={spacing.lg}>
211
+ <Text weight="semiBold">Icon Button Style</Text>
212
+ <HStack space={spacing.sm}>
213
+ <Pressable
214
+ pressedOpacity={0.6}
215
+ pressedScale={0.9}
216
+ onPress={() => console.log('Like')}
217
+ >
218
+ <Box p={spacing.md} bg={colors.feedback.error.background} rounded="full">
219
+ <Text>❤️</Text>
220
+ </Box>
221
+ </Pressable>
222
+ <Pressable
223
+ pressedOpacity={0.6}
224
+ pressedScale={0.9}
225
+ onPress={() => console.log('Comment')}
226
+ >
227
+ <Box p={spacing.md} bg={colors.feedback.info.background} rounded="full">
228
+ <Text>💬</Text>
229
+ </Box>
230
+ </Pressable>
231
+ <Pressable
232
+ pressedOpacity={0.6}
233
+ pressedScale={0.9}
234
+ onPress={() => console.log('Share')}
235
+ >
236
+ <Box p={spacing.md} bg={colors.feedback.success.background} rounded="full">
237
+ <Text>🔗</Text>
238
+ </Box>
239
+ </Pressable>
240
+ <Pressable
241
+ pressedOpacity={0.6}
242
+ pressedScale={0.9}
243
+ onPress={() => console.log('Bookmark')}
244
+ >
245
+ <Box p={spacing.md} bg={colors.feedback.warning.background} rounded="full">
246
+ <Text>🔖</Text>
247
+ </Box>
248
+ </Pressable>
249
+ </HStack>
250
+ </VStack>
251
+ ),
252
+ };
253
+
254
+ export const Tags: Story = {
255
+ render: () => (
256
+ <VStack space={spacing.lg}>
257
+ <Text weight="semiBold">Pressable Tags</Text>
258
+ <HStack space={spacing.sm} wrap>
259
+ {['React', 'TypeScript', 'JavaScript', 'Node.js', 'GraphQL'].map((tag) => (
260
+ <Pressable
261
+ key={tag}
262
+ pressedOpacity={0.7}
263
+ pressedScale={0.95}
264
+ onPress={() => console.log(`${tag} selected`)}
265
+ >
266
+ <Box px={spacing.md} py={6} bg={colors.brand.blue + '20'} rounded="full">
267
+ <Text size="sm" color={colors.brand.blue}>{tag}</Text>
268
+ </Box>
269
+ </Pressable>
270
+ ))}
271
+ </HStack>
272
+ </VStack>
273
+ ),
274
+ };
275
+
276
+ export const AvatarPressable: Story = {
277
+ render: () => (
278
+ <VStack space={spacing.lg}>
279
+ <Text weight="semiBold">Pressable Avatars</Text>
280
+ <HStack space={-8}>
281
+ {['A', 'B', 'C', 'D', '+2'].map((letter, i) => (
282
+ <Pressable
283
+ key={i}
284
+ pressedScale={1.1}
285
+ pressedOpacity={1}
286
+ onPress={() => console.log(`Avatar ${letter} pressed`)}
287
+ >
288
+ <Box
289
+ w={40}
290
+ h={40}
291
+ rounded="full"
292
+ bg={letter === '+2' ? colors.border.default : colors.brand.blue + '30'}
293
+ alignItems="center"
294
+ justifyContent="center"
295
+ borderWidth={2}
296
+ borderColor="white"
297
+ >
298
+ <Text weight="semiBold" size="sm">{letter}</Text>
299
+ </Box>
300
+ </Pressable>
301
+ ))}
302
+ </HStack>
303
+ </VStack>
304
+ ),
305
+ };
306
+
307
+ export const MediaCard: Story = {
308
+ render: () => (
309
+ <VStack space={spacing.lg}>
310
+ <Text weight="semiBold">Media Card</Text>
311
+ <Pressable
312
+ pressedOpacity={0.95}
313
+ pressedScale={0.98}
314
+ onPress={() => console.log('Play video')}
315
+ >
316
+ <Box w={300} bg="#1e293b" rounded="lg" overflow="hidden">
317
+ <Box h={170} bg="#0f172a" alignItems="center" justifyContent="center">
318
+ <Box
319
+ w={50}
320
+ h={50}
321
+ rounded="full"
322
+ bg="rgba(255,255,255,0.9)"
323
+ alignItems="center"
324
+ justifyContent="center"
325
+ >
326
+ <Text size="lg">▶</Text>
327
+ </Box>
328
+ </Box>
329
+ <Box p={12}>
330
+ <Text style={{ color: 'white' }} weight="semiBold">Video Title</Text>
331
+ <Text size="sm" style={{ color: '#94a3b8' }}>12.5K views • 2 days ago</Text>
332
+ </Box>
333
+ </Box>
334
+ </Pressable>
335
+ </VStack>
336
+ ),
337
+ };
338
+
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Pressable Component
3
+ * Enhanced pressable with feedback states
4
+ */
5
+
6
+ import React, { forwardRef, useState } from 'react';
7
+ import {
8
+ Pressable as RNPressable,
9
+ PressableProps as RNPressableProps,
10
+ View,
11
+ ViewStyle,
12
+ StyleSheet,
13
+ } from 'react-native';
14
+
15
+ export interface PressableProps extends Omit<RNPressableProps, 'style'> {
16
+ /** Style */
17
+ style?: ViewStyle;
18
+ /** Opacity when pressed */
19
+ pressedOpacity?: number;
20
+ /** Scale when pressed */
21
+ pressedScale?: number;
22
+ /** Custom pressed style */
23
+ pressedStyle?: ViewStyle;
24
+ }
25
+
26
+ export const Pressable = forwardRef<View, PressableProps>(
27
+ (
28
+ {
29
+ style,
30
+ pressedOpacity = 0.7,
31
+ pressedScale,
32
+ pressedStyle,
33
+ onPressIn,
34
+ onPressOut,
35
+ children,
36
+ ...props
37
+ },
38
+ ref
39
+ ) => {
40
+ const [isPressed, setIsPressed] = useState(false);
41
+
42
+ const handlePressIn = (e: any) => {
43
+ setIsPressed(true);
44
+ onPressIn?.(e);
45
+ };
46
+
47
+ const handlePressOut = (e: any) => {
48
+ setIsPressed(false);
49
+ onPressOut?.(e);
50
+ };
51
+
52
+ return (
53
+ <RNPressable
54
+ ref={ref}
55
+ onPressIn={handlePressIn}
56
+ onPressOut={handlePressOut}
57
+ style={[
58
+ style,
59
+ isPressed && { opacity: pressedOpacity },
60
+ isPressed && pressedScale && { transform: [{ scale: pressedScale }] },
61
+ isPressed && pressedStyle,
62
+ ]}
63
+ {...props}
64
+ >
65
+ {children}
66
+ </RNPressable>
67
+ );
68
+ }
69
+ );
70
+
71
+ Pressable.displayName = 'Pressable';
@@ -0,0 +1,2 @@
1
+ export { Pressable, type PressableProps } from './Pressable';
2
+
@@ -0,0 +1,131 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { View, StyleSheet } from 'react-native';
3
+ import { Progress } from './Progress';
4
+ import { VStack } from '../VStack';
5
+ import { HStack } from '../HStack';
6
+ import { Text } from '../Text';
7
+ import { colors, spacing, borderRadius } from '../../styles/tokens';
8
+
9
+ /**
10
+ * Story container with design system tokens
11
+ */
12
+ const StoryContainer: React.FC<{ children: React.ReactNode }> = ({ children }) => (
13
+ <View style={styles.container}>{children}</View>
14
+ );
15
+
16
+ const meta: Meta<typeof Progress> = {
17
+ title: 'Components/Progress',
18
+ component: Progress,
19
+ decorators: [
20
+ (Story) => (
21
+ <StoryContainer>
22
+ <Story />
23
+ </StoryContainer>
24
+ ),
25
+ ],
26
+ args: {
27
+ value: 65,
28
+ },
29
+ };
30
+
31
+ export default meta;
32
+
33
+ type Story = StoryObj<typeof Progress>;
34
+
35
+ export const Default: Story = {};
36
+
37
+ export const Sizes: Story = {
38
+ render: () => (
39
+ <VStack space={spacing.lg}>
40
+ <Text weight="semiBold">Progress Sizes</Text>
41
+ <Progress value={50} size="sm" />
42
+ <Progress value={50} size="md" />
43
+ <Progress value={50} size="lg" />
44
+ </VStack>
45
+ ),
46
+ };
47
+
48
+ export const ColorSchemes: Story = {
49
+ render: () => (
50
+ <VStack space={spacing.lg}>
51
+ <Text weight="semiBold">Color Schemes</Text>
52
+ <Progress value={75} colorScheme="primary" />
53
+ <Progress value={75} colorScheme="success" />
54
+ <Progress value={75} colorScheme="warning" />
55
+ <Progress value={75} colorScheme="danger" />
56
+ </VStack>
57
+ ),
58
+ };
59
+
60
+ export const WithLabel: Story = {
61
+ render: () => (
62
+ <VStack space={spacing.lg}>
63
+ <Text weight="semiBold">With Label</Text>
64
+ <Progress value={45} showLabel />
65
+ <Progress value={80} showLabel size="lg" labelPosition="inside" />
66
+ </VStack>
67
+ ),
68
+ };
69
+
70
+ export const Indeterminate: Story = {
71
+ render: () => (
72
+ <VStack space={spacing.lg}>
73
+ <Text weight="semiBold">Indeterminate Progress</Text>
74
+ <Progress isIndeterminate />
75
+ </VStack>
76
+ ),
77
+ };
78
+
79
+ export const Circular: Story = {
80
+ render: () => (
81
+ <VStack space={spacing.lg}>
82
+ <Text weight="semiBold">Circular Progress</Text>
83
+ <HStack space={spacing.lg}>
84
+ <Progress variant="circular" value={25} size="sm" showLabel />
85
+ <Progress variant="circular" value={50} size="md" showLabel />
86
+ <Progress variant="circular" value={75} size="lg" showLabel />
87
+ </HStack>
88
+ </VStack>
89
+ ),
90
+ };
91
+
92
+ export const UsageExample: Story = {
93
+ render: () => (
94
+ <VStack space={spacing.lg}>
95
+ <Text weight="semiBold">File Upload Progress</Text>
96
+ <VStack space={spacing.xs}>
97
+ <HStack justifyContent="space-between">
98
+ <Text variant="caption">document.pdf</Text>
99
+ <Text variant="caption" color={colors.feedback.success.content}>Complete</Text>
100
+ </HStack>
101
+ <Progress value={100} colorScheme="success" size="sm" />
102
+ </VStack>
103
+ <VStack space={spacing.xs}>
104
+ <HStack justifyContent="space-between">
105
+ <Text variant="caption">image.png</Text>
106
+ <Text variant="caption">65%</Text>
107
+ </HStack>
108
+ <Progress value={65} size="sm" />
109
+ </VStack>
110
+ <VStack space={spacing.xs}>
111
+ <HStack justifyContent="space-between">
112
+ <Text variant="caption">video.mp4</Text>
113
+ <Text variant="caption">Starting...</Text>
114
+ </HStack>
115
+ <Progress isIndeterminate size="sm" />
116
+ </VStack>
117
+ </VStack>
118
+ ),
119
+ };
120
+
121
+ /**
122
+ * Styles using design system tokens
123
+ */
124
+ const styles = StyleSheet.create({
125
+ container: {
126
+ padding: spacing.lg,
127
+ backgroundColor: colors.background.default,
128
+ borderRadius: borderRadius.lg,
129
+ },
130
+ });
131
+