@masumdev/rn-ui 0.1.6 → 0.2.0

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 (316) hide show
  1. package/README.md +47 -1752
  2. package/lib/commonjs/components/Accordion.js +28 -13
  3. package/lib/commonjs/components/Accordion.js.map +1 -1
  4. package/lib/commonjs/components/Alert.js +229 -73
  5. package/lib/commonjs/components/Alert.js.map +1 -1
  6. package/lib/commonjs/components/AlertDialog.js +143 -87
  7. package/lib/commonjs/components/AlertDialog.js.map +1 -1
  8. package/lib/commonjs/components/AspectRatio.js.map +1 -1
  9. package/lib/commonjs/components/Avatar.js +31 -28
  10. package/lib/commonjs/components/Avatar.js.map +1 -1
  11. package/lib/commonjs/components/Badge.js +25 -9
  12. package/lib/commonjs/components/Badge.js.map +1 -1
  13. package/lib/commonjs/components/BottomSheet.js +63 -8
  14. package/lib/commonjs/components/BottomSheet.js.map +1 -1
  15. package/lib/commonjs/components/Breadcrumb.js +31 -9
  16. package/lib/commonjs/components/Breadcrumb.js.map +1 -1
  17. package/lib/commonjs/components/Button.js +22 -6
  18. package/lib/commonjs/components/Button.js.map +1 -1
  19. package/lib/commonjs/components/ButtonGroup.js +2 -4
  20. package/lib/commonjs/components/ButtonGroup.js.map +1 -1
  21. package/lib/commonjs/components/Calendar.js +113 -31
  22. package/lib/commonjs/components/Calendar.js.map +1 -1
  23. package/lib/commonjs/components/Card.js +8 -3
  24. package/lib/commonjs/components/Card.js.map +1 -1
  25. package/lib/commonjs/components/Carousel.js +67 -21
  26. package/lib/commonjs/components/Carousel.js.map +1 -1
  27. package/lib/commonjs/components/Checkbox.js +12 -7
  28. package/lib/commonjs/components/Checkbox.js.map +1 -1
  29. package/lib/commonjs/components/Collapsible.js +47 -36
  30. package/lib/commonjs/components/Collapsible.js.map +1 -1
  31. package/lib/commonjs/components/Combobox.js +110 -48
  32. package/lib/commonjs/components/Combobox.js.map +1 -1
  33. package/lib/commonjs/components/Command.js +121 -77
  34. package/lib/commonjs/components/Command.js.map +1 -1
  35. package/lib/commonjs/components/DropdownMenu.js +78 -25
  36. package/lib/commonjs/components/DropdownMenu.js.map +1 -1
  37. package/lib/commonjs/components/Empty.js +24 -10
  38. package/lib/commonjs/components/Empty.js.map +1 -1
  39. package/lib/commonjs/components/FloatingActionButton.js.map +1 -1
  40. package/lib/commonjs/components/FormField.js +63 -13
  41. package/lib/commonjs/components/FormField.js.map +1 -1
  42. package/lib/commonjs/components/IconButton.js +22 -6
  43. package/lib/commonjs/components/IconButton.js.map +1 -1
  44. package/lib/commonjs/components/Input.js +11 -13
  45. package/lib/commonjs/components/Input.js.map +1 -1
  46. package/lib/commonjs/components/InputGroup.js +19 -10
  47. package/lib/commonjs/components/InputGroup.js.map +1 -1
  48. package/lib/commonjs/components/InputOTP.js +46 -15
  49. package/lib/commonjs/components/InputOTP.js.map +1 -1
  50. package/lib/commonjs/components/Popover.js +90 -23
  51. package/lib/commonjs/components/Popover.js.map +1 -1
  52. package/lib/commonjs/components/Progress.js +108 -7
  53. package/lib/commonjs/components/Progress.js.map +1 -1
  54. package/lib/commonjs/components/RadioGroup.js +109 -51
  55. package/lib/commonjs/components/RadioGroup.js.map +1 -1
  56. package/lib/commonjs/components/Rating.js +109 -95
  57. package/lib/commonjs/components/Rating.js.map +1 -1
  58. package/lib/commonjs/components/Select.js +109 -43
  59. package/lib/commonjs/components/Select.js.map +1 -1
  60. package/lib/commonjs/components/Sheet.js +217 -29
  61. package/lib/commonjs/components/Sheet.js.map +1 -1
  62. package/lib/commonjs/components/Stepper.js +119 -24
  63. package/lib/commonjs/components/Stepper.js.map +1 -1
  64. package/lib/commonjs/components/Switch.js +21 -11
  65. package/lib/commonjs/components/Switch.js.map +1 -1
  66. package/lib/commonjs/components/Tabs.js +159 -28
  67. package/lib/commonjs/components/Tabs.js.map +1 -1
  68. package/lib/commonjs/components/Timeline.js +35 -12
  69. package/lib/commonjs/components/Timeline.js.map +1 -1
  70. package/lib/commonjs/components/Toast.js +163 -38
  71. package/lib/commonjs/components/Toast.js.map +1 -1
  72. package/lib/commonjs/components/index.js +19 -0
  73. package/lib/commonjs/components/index.js.map +1 -1
  74. package/lib/commonjs/components/types.js +53 -0
  75. package/lib/commonjs/components/types.js.map +1 -1
  76. package/lib/commonjs/theme/tokens.js +7 -7
  77. package/lib/commonjs/theme/tokens.js.map +1 -1
  78. package/lib/commonjs/utils/haptics.js +42 -0
  79. package/lib/commonjs/utils/haptics.js.map +1 -0
  80. package/lib/commonjs/utils/index.js +7 -0
  81. package/lib/commonjs/utils/index.js.map +1 -1
  82. package/lib/module/components/Accordion.js +28 -13
  83. package/lib/module/components/Accordion.js.map +1 -1
  84. package/lib/module/components/Alert.js +229 -73
  85. package/lib/module/components/Alert.js.map +1 -1
  86. package/lib/module/components/AlertDialog.js +144 -88
  87. package/lib/module/components/AlertDialog.js.map +1 -1
  88. package/lib/module/components/AspectRatio.js.map +1 -1
  89. package/lib/module/components/Avatar.js +31 -28
  90. package/lib/module/components/Avatar.js.map +1 -1
  91. package/lib/module/components/Badge.js +25 -9
  92. package/lib/module/components/Badge.js.map +1 -1
  93. package/lib/module/components/BottomSheet.js +64 -4
  94. package/lib/module/components/BottomSheet.js.map +1 -1
  95. package/lib/module/components/Breadcrumb.js +31 -9
  96. package/lib/module/components/Breadcrumb.js.map +1 -1
  97. package/lib/module/components/Button.js +22 -6
  98. package/lib/module/components/Button.js.map +1 -1
  99. package/lib/module/components/ButtonGroup.js +3 -5
  100. package/lib/module/components/ButtonGroup.js.map +1 -1
  101. package/lib/module/components/Calendar.js +114 -32
  102. package/lib/module/components/Calendar.js.map +1 -1
  103. package/lib/module/components/Card.js +8 -3
  104. package/lib/module/components/Card.js.map +1 -1
  105. package/lib/module/components/Carousel.js +67 -21
  106. package/lib/module/components/Carousel.js.map +1 -1
  107. package/lib/module/components/Checkbox.js +12 -7
  108. package/lib/module/components/Checkbox.js.map +1 -1
  109. package/lib/module/components/Collapsible.js +49 -38
  110. package/lib/module/components/Collapsible.js.map +1 -1
  111. package/lib/module/components/Combobox.js +110 -48
  112. package/lib/module/components/Combobox.js.map +1 -1
  113. package/lib/module/components/Command.js +121 -77
  114. package/lib/module/components/Command.js.map +1 -1
  115. package/lib/module/components/DropdownMenu.js +79 -26
  116. package/lib/module/components/DropdownMenu.js.map +1 -1
  117. package/lib/module/components/Empty.js +24 -10
  118. package/lib/module/components/Empty.js.map +1 -1
  119. package/lib/module/components/FloatingActionButton.js.map +1 -1
  120. package/lib/module/components/FormField.js +63 -14
  121. package/lib/module/components/FormField.js.map +1 -1
  122. package/lib/module/components/IconButton.js +22 -6
  123. package/lib/module/components/IconButton.js.map +1 -1
  124. package/lib/module/components/Input.js +12 -14
  125. package/lib/module/components/Input.js.map +1 -1
  126. package/lib/module/components/InputGroup.js +19 -10
  127. package/lib/module/components/InputGroup.js.map +1 -1
  128. package/lib/module/components/InputOTP.js +46 -15
  129. package/lib/module/components/InputOTP.js.map +1 -1
  130. package/lib/module/components/Popover.js +90 -24
  131. package/lib/module/components/Popover.js.map +1 -1
  132. package/lib/module/components/Progress.js +109 -9
  133. package/lib/module/components/Progress.js.map +1 -1
  134. package/lib/module/components/RadioGroup.js +108 -51
  135. package/lib/module/components/RadioGroup.js.map +1 -1
  136. package/lib/module/components/Rating.js +109 -95
  137. package/lib/module/components/Rating.js.map +1 -1
  138. package/lib/module/components/Select.js +111 -45
  139. package/lib/module/components/Select.js.map +1 -1
  140. package/lib/module/components/Sheet.js +216 -24
  141. package/lib/module/components/Sheet.js.map +1 -1
  142. package/lib/module/components/Stepper.js +120 -25
  143. package/lib/module/components/Stepper.js.map +1 -1
  144. package/lib/module/components/Switch.js +21 -11
  145. package/lib/module/components/Switch.js.map +1 -1
  146. package/lib/module/components/Tabs.js +158 -29
  147. package/lib/module/components/Tabs.js.map +1 -1
  148. package/lib/module/components/Timeline.js +35 -12
  149. package/lib/module/components/Timeline.js.map +1 -1
  150. package/lib/module/components/Toast.js +164 -38
  151. package/lib/module/components/Toast.js.map +1 -1
  152. package/lib/module/components/index.js +3 -2
  153. package/lib/module/components/index.js.map +1 -1
  154. package/lib/module/components/types.js +53 -0
  155. package/lib/module/components/types.js.map +1 -1
  156. package/lib/module/theme/tokens.js +7 -7
  157. package/lib/module/theme/tokens.js.map +1 -1
  158. package/lib/module/utils/haptics.js +38 -0
  159. package/lib/module/utils/haptics.js.map +1 -0
  160. package/lib/module/utils/index.js +1 -0
  161. package/lib/module/utils/index.js.map +1 -1
  162. package/lib/typescript/commonjs/components/Accordion.d.ts +6 -3
  163. package/lib/typescript/commonjs/components/Accordion.d.ts.map +1 -1
  164. package/lib/typescript/commonjs/components/Alert.d.ts +4 -4
  165. package/lib/typescript/commonjs/components/Alert.d.ts.map +1 -1
  166. package/lib/typescript/commonjs/components/AlertDialog.d.ts +5 -4
  167. package/lib/typescript/commonjs/components/AlertDialog.d.ts.map +1 -1
  168. package/lib/typescript/commonjs/components/AspectRatio.d.ts.map +1 -1
  169. package/lib/typescript/commonjs/components/Avatar.d.ts +9 -4
  170. package/lib/typescript/commonjs/components/Avatar.d.ts.map +1 -1
  171. package/lib/typescript/commonjs/components/Badge.d.ts +5 -8
  172. package/lib/typescript/commonjs/components/Badge.d.ts.map +1 -1
  173. package/lib/typescript/commonjs/components/BottomSheet.d.ts +13 -4
  174. package/lib/typescript/commonjs/components/BottomSheet.d.ts.map +1 -1
  175. package/lib/typescript/commonjs/components/Breadcrumb.d.ts +6 -5
  176. package/lib/typescript/commonjs/components/Breadcrumb.d.ts.map +1 -1
  177. package/lib/typescript/commonjs/components/Button.d.ts +6 -12
  178. package/lib/typescript/commonjs/components/Button.d.ts.map +1 -1
  179. package/lib/typescript/commonjs/components/ButtonGroup.d.ts.map +1 -1
  180. package/lib/typescript/commonjs/components/Calendar.d.ts +9 -1
  181. package/lib/typescript/commonjs/components/Calendar.d.ts.map +1 -1
  182. package/lib/typescript/commonjs/components/Card.d.ts +3 -2
  183. package/lib/typescript/commonjs/components/Card.d.ts.map +1 -1
  184. package/lib/typescript/commonjs/components/Carousel.d.ts +4 -1
  185. package/lib/typescript/commonjs/components/Carousel.d.ts.map +1 -1
  186. package/lib/typescript/commonjs/components/Checkbox.d.ts +3 -3
  187. package/lib/typescript/commonjs/components/Checkbox.d.ts.map +1 -1
  188. package/lib/typescript/commonjs/components/Collapsible.d.ts.map +1 -1
  189. package/lib/typescript/commonjs/components/Combobox.d.ts +11 -6
  190. package/lib/typescript/commonjs/components/Combobox.d.ts.map +1 -1
  191. package/lib/typescript/commonjs/components/Command.d.ts +3 -0
  192. package/lib/typescript/commonjs/components/Command.d.ts.map +1 -1
  193. package/lib/typescript/commonjs/components/DropdownMenu.d.ts +4 -2
  194. package/lib/typescript/commonjs/components/DropdownMenu.d.ts.map +1 -1
  195. package/lib/typescript/commonjs/components/Empty.d.ts +7 -4
  196. package/lib/typescript/commonjs/components/Empty.d.ts.map +1 -1
  197. package/lib/typescript/commonjs/components/FloatingActionButton.d.ts +2 -5
  198. package/lib/typescript/commonjs/components/FloatingActionButton.d.ts.map +1 -1
  199. package/lib/typescript/commonjs/components/FormField.d.ts +12 -4
  200. package/lib/typescript/commonjs/components/FormField.d.ts.map +1 -1
  201. package/lib/typescript/commonjs/components/IconButton.d.ts +4 -7
  202. package/lib/typescript/commonjs/components/IconButton.d.ts.map +1 -1
  203. package/lib/typescript/commonjs/components/Input.d.ts +2 -1
  204. package/lib/typescript/commonjs/components/Input.d.ts.map +1 -1
  205. package/lib/typescript/commonjs/components/InputGroup.d.ts +3 -2
  206. package/lib/typescript/commonjs/components/InputGroup.d.ts.map +1 -1
  207. package/lib/typescript/commonjs/components/InputOTP.d.ts +9 -4
  208. package/lib/typescript/commonjs/components/InputOTP.d.ts.map +1 -1
  209. package/lib/typescript/commonjs/components/Popover.d.ts +1 -1
  210. package/lib/typescript/commonjs/components/Popover.d.ts.map +1 -1
  211. package/lib/typescript/commonjs/components/Progress.d.ts +15 -2
  212. package/lib/typescript/commonjs/components/Progress.d.ts.map +1 -1
  213. package/lib/typescript/commonjs/components/RadioGroup.d.ts +3 -2
  214. package/lib/typescript/commonjs/components/RadioGroup.d.ts.map +1 -1
  215. package/lib/typescript/commonjs/components/Rating.d.ts +3 -23
  216. package/lib/typescript/commonjs/components/Rating.d.ts.map +1 -1
  217. package/lib/typescript/commonjs/components/Select.d.ts +5 -4
  218. package/lib/typescript/commonjs/components/Select.d.ts.map +1 -1
  219. package/lib/typescript/commonjs/components/Sheet.d.ts +25 -6
  220. package/lib/typescript/commonjs/components/Sheet.d.ts.map +1 -1
  221. package/lib/typescript/commonjs/components/Stepper.d.ts +5 -3
  222. package/lib/typescript/commonjs/components/Stepper.d.ts.map +1 -1
  223. package/lib/typescript/commonjs/components/Switch.d.ts +3 -3
  224. package/lib/typescript/commonjs/components/Switch.d.ts.map +1 -1
  225. package/lib/typescript/commonjs/components/Tabs.d.ts +21 -4
  226. package/lib/typescript/commonjs/components/Tabs.d.ts.map +1 -1
  227. package/lib/typescript/commonjs/components/Timeline.d.ts +9 -3
  228. package/lib/typescript/commonjs/components/Timeline.d.ts.map +1 -1
  229. package/lib/typescript/commonjs/components/Toast.d.ts +3 -0
  230. package/lib/typescript/commonjs/components/Toast.d.ts.map +1 -1
  231. package/lib/typescript/commonjs/components/index.d.ts +7 -6
  232. package/lib/typescript/commonjs/components/index.d.ts.map +1 -1
  233. package/lib/typescript/commonjs/components/types.d.ts +110 -0
  234. package/lib/typescript/commonjs/components/types.d.ts.map +1 -1
  235. package/lib/typescript/commonjs/utils/haptics.d.ts +6 -0
  236. package/lib/typescript/commonjs/utils/haptics.d.ts.map +1 -0
  237. package/lib/typescript/commonjs/utils/index.d.ts +1 -0
  238. package/lib/typescript/commonjs/utils/index.d.ts.map +1 -1
  239. package/lib/typescript/module/components/Accordion.d.ts +6 -3
  240. package/lib/typescript/module/components/Accordion.d.ts.map +1 -1
  241. package/lib/typescript/module/components/Alert.d.ts +4 -4
  242. package/lib/typescript/module/components/Alert.d.ts.map +1 -1
  243. package/lib/typescript/module/components/AlertDialog.d.ts +5 -4
  244. package/lib/typescript/module/components/AlertDialog.d.ts.map +1 -1
  245. package/lib/typescript/module/components/AspectRatio.d.ts.map +1 -1
  246. package/lib/typescript/module/components/Avatar.d.ts +9 -4
  247. package/lib/typescript/module/components/Avatar.d.ts.map +1 -1
  248. package/lib/typescript/module/components/Badge.d.ts +5 -8
  249. package/lib/typescript/module/components/Badge.d.ts.map +1 -1
  250. package/lib/typescript/module/components/BottomSheet.d.ts +13 -4
  251. package/lib/typescript/module/components/BottomSheet.d.ts.map +1 -1
  252. package/lib/typescript/module/components/Breadcrumb.d.ts +6 -5
  253. package/lib/typescript/module/components/Breadcrumb.d.ts.map +1 -1
  254. package/lib/typescript/module/components/Button.d.ts +6 -12
  255. package/lib/typescript/module/components/Button.d.ts.map +1 -1
  256. package/lib/typescript/module/components/ButtonGroup.d.ts.map +1 -1
  257. package/lib/typescript/module/components/Calendar.d.ts +9 -1
  258. package/lib/typescript/module/components/Calendar.d.ts.map +1 -1
  259. package/lib/typescript/module/components/Card.d.ts +3 -2
  260. package/lib/typescript/module/components/Card.d.ts.map +1 -1
  261. package/lib/typescript/module/components/Carousel.d.ts +4 -1
  262. package/lib/typescript/module/components/Carousel.d.ts.map +1 -1
  263. package/lib/typescript/module/components/Checkbox.d.ts +3 -3
  264. package/lib/typescript/module/components/Checkbox.d.ts.map +1 -1
  265. package/lib/typescript/module/components/Collapsible.d.ts.map +1 -1
  266. package/lib/typescript/module/components/Combobox.d.ts +11 -6
  267. package/lib/typescript/module/components/Combobox.d.ts.map +1 -1
  268. package/lib/typescript/module/components/Command.d.ts +3 -0
  269. package/lib/typescript/module/components/Command.d.ts.map +1 -1
  270. package/lib/typescript/module/components/DropdownMenu.d.ts +4 -2
  271. package/lib/typescript/module/components/DropdownMenu.d.ts.map +1 -1
  272. package/lib/typescript/module/components/Empty.d.ts +7 -4
  273. package/lib/typescript/module/components/Empty.d.ts.map +1 -1
  274. package/lib/typescript/module/components/FloatingActionButton.d.ts +2 -5
  275. package/lib/typescript/module/components/FloatingActionButton.d.ts.map +1 -1
  276. package/lib/typescript/module/components/FormField.d.ts +12 -4
  277. package/lib/typescript/module/components/FormField.d.ts.map +1 -1
  278. package/lib/typescript/module/components/IconButton.d.ts +4 -7
  279. package/lib/typescript/module/components/IconButton.d.ts.map +1 -1
  280. package/lib/typescript/module/components/Input.d.ts +2 -1
  281. package/lib/typescript/module/components/Input.d.ts.map +1 -1
  282. package/lib/typescript/module/components/InputGroup.d.ts +3 -2
  283. package/lib/typescript/module/components/InputGroup.d.ts.map +1 -1
  284. package/lib/typescript/module/components/InputOTP.d.ts +9 -4
  285. package/lib/typescript/module/components/InputOTP.d.ts.map +1 -1
  286. package/lib/typescript/module/components/Popover.d.ts +1 -1
  287. package/lib/typescript/module/components/Popover.d.ts.map +1 -1
  288. package/lib/typescript/module/components/Progress.d.ts +15 -2
  289. package/lib/typescript/module/components/Progress.d.ts.map +1 -1
  290. package/lib/typescript/module/components/RadioGroup.d.ts +3 -2
  291. package/lib/typescript/module/components/RadioGroup.d.ts.map +1 -1
  292. package/lib/typescript/module/components/Rating.d.ts +3 -23
  293. package/lib/typescript/module/components/Rating.d.ts.map +1 -1
  294. package/lib/typescript/module/components/Select.d.ts +5 -4
  295. package/lib/typescript/module/components/Select.d.ts.map +1 -1
  296. package/lib/typescript/module/components/Sheet.d.ts +25 -6
  297. package/lib/typescript/module/components/Sheet.d.ts.map +1 -1
  298. package/lib/typescript/module/components/Stepper.d.ts +5 -3
  299. package/lib/typescript/module/components/Stepper.d.ts.map +1 -1
  300. package/lib/typescript/module/components/Switch.d.ts +3 -3
  301. package/lib/typescript/module/components/Switch.d.ts.map +1 -1
  302. package/lib/typescript/module/components/Tabs.d.ts +21 -4
  303. package/lib/typescript/module/components/Tabs.d.ts.map +1 -1
  304. package/lib/typescript/module/components/Timeline.d.ts +9 -3
  305. package/lib/typescript/module/components/Timeline.d.ts.map +1 -1
  306. package/lib/typescript/module/components/Toast.d.ts +3 -0
  307. package/lib/typescript/module/components/Toast.d.ts.map +1 -1
  308. package/lib/typescript/module/components/index.d.ts +7 -6
  309. package/lib/typescript/module/components/index.d.ts.map +1 -1
  310. package/lib/typescript/module/components/types.d.ts +110 -0
  311. package/lib/typescript/module/components/types.d.ts.map +1 -1
  312. package/lib/typescript/module/utils/haptics.d.ts +6 -0
  313. package/lib/typescript/module/utils/haptics.d.ts.map +1 -0
  314. package/lib/typescript/module/utils/index.d.ts +1 -0
  315. package/lib/typescript/module/utils/index.d.ts.map +1 -1
  316. package/package.json +10 -1
package/README.md CHANGED
@@ -1,95 +1,56 @@
1
1
  # @masumdev/rn-ui
2
2
 
3
- Reusable React Native UI kit with typed theme tokens, flat light/dark mode, pluggable persistence, pluggable fonts, and composable core components.
3
+ > A modern, flat-designed React Native & Expo UI kit with 55+ typed components, dynamic light/dark theme engine, zero-shadow defaults, and pluggable architecture.
4
4
 
5
- `@masumdev/rn-ui` is designed for Expo and React Native apps that want a consistent flat UI system without tying the library to app-specific choices such as navigation, storage, icon packs, haptics, or analytics.
5
+ [![npm version](https://img.shields.io/npm/v/@masumdev/rn-ui.svg)](https://www.npmjs.com/package/@masumdev/rn-ui)
6
+ [![license](https://img.shields.io/npm/l/@masumdev/rn-ui.svg)](./LICENSE)
6
7
 
7
- ## What You Get
8
+ ---
8
9
 
9
- - Flat, border-based components with no shadow/elevation by default.
10
- - Light, dark, and system color-scheme support.
11
- - Typed theme tokens for colors, fonts, typography, spacing, radius, shadows, and component sizing.
12
- - Pluggable theme persistence through a tiny storage adapter.
13
- - Pluggable fonts through theme tokens.
14
- - Pluggable icons through render functions or React nodes.
15
- - Reanimated-powered component interactions.
16
- - Mobile-first primitives for forms, feedback, overlays, data display, and local navigation UI.
10
+ ## 📚 Full Documentation
17
11
 
18
- ## Requirements
12
+ Comprehensive guides, component previews, prop tables, and interactive examples are available in our official documentation:
19
13
 
20
- Minimum runtime expectations:
14
+ 👉 **[Explore Full Documentation & Component Catalog](https://react-native-library-docs.netlify.app/rn-ui)**
21
15
 
22
- - React Native app or Expo app.
23
- - React and React Native installed by the app.
24
- - `react-native-reanimated` and `react-native-worklets`.
25
- - `react-native-gesture-handler` and `GestureHandlerRootView` at the app root for gesture-driven components such as `Slider` and Gorhom-based sheets.
16
+ - 📖 **[Installation Guide](https://react-native-library-docs.netlify.app/rn-ui/installation)**
17
+ - 🎨 **[Theming & Dark Mode](https://react-native-library-docs.netlify.app/rn-ui/theming)**
18
+ - 🧩 **[55+ Component Catalog](https://react-native-library-docs.netlify.app/rn-ui/components)**
19
+ - 🛠️ **[Building Custom Components](https://react-native-library-docs.netlify.app/rn-ui/custom-components)**
20
+ - 📜 **[Architectural Rules](./RULES.md)**
21
+ - 🚀 **[Changelog](https://react-native-library-docs.netlify.app/rn-ui/changelog)**
26
22
 
27
- This package currently ships a single root export that includes every component. Because `Calendar` and `BottomSheet` are exported from the root package, install their peer dependencies too when consuming the package from npm:
23
+ ---
28
24
 
29
- - `react-native-calendars`
30
- - `@gorhom/bottom-sheet`
25
+ ## ✨ Features
31
26
 
32
- Future versions may split optional integrations into subpath exports so these can become truly optional.
27
+ - **Flat Aesthetic**: Border-based, clean UI primitives with zero elevation/shadow by default.
28
+ - **Dynamic Theme Engine**: Light, dark, and system preference support via `ThemeProvider`.
29
+ - **55+ Typed Components**: Forms, feedback, overlays, navigation, data display, and chat UI primitives.
30
+ - **Pluggable Architecture**: Zero lock-in for fonts, icons, navigation, storage, or haptics.
31
+ - **Reanimated Powered**: Smooth 60fps micro-animations powered by `react-native-reanimated`.
32
+ - **Strict Type Safety**: 100% TypeScript with zero `any` types and shared base UI prop interfaces.
33
33
 
34
- ## Install
34
+ ---
35
35
 
36
- ### Expo
36
+ ## 📦 Quick Install
37
37
 
38
+ ### Expo
38
39
  ```sh
39
40
  npx expo install react-native-reanimated react-native-worklets react-native-gesture-handler react-native-calendars
40
41
  bun add @masumdev/rn-ui @gorhom/bottom-sheet
41
42
  ```
42
43
 
43
- If you use npm instead of Bun:
44
-
45
- ```sh
46
- npx expo install react-native-reanimated react-native-worklets react-native-gesture-handler react-native-calendars
47
- npm install @masumdev/rn-ui @gorhom/bottom-sheet
48
- ```
49
-
50
44
  ### React Native CLI
51
-
52
- Install the package and peer dependencies:
53
-
54
45
  ```sh
55
46
  bun add @masumdev/rn-ui react-native-reanimated react-native-worklets react-native-gesture-handler react-native-calendars @gorhom/bottom-sheet
56
47
  ```
57
48
 
58
- For iOS, run pods after installing native dependencies:
59
-
60
- ```sh
61
- cd ios
62
- pod install
63
- cd ..
64
- ```
65
-
66
- ## Setup
67
-
68
- ### 1. Add GestureHandlerRootView
69
-
70
- Wrap the app root with `GestureHandlerRootView`. This is required for gesture-driven components and `@gorhom/bottom-sheet`.
49
+ ---
71
50
 
72
- Expo Router example:
73
-
74
- ```tsx
75
- import { Stack } from "expo-router";
76
- import { GestureHandlerRootView } from "react-native-gesture-handler";
77
- import { ThemeProvider, ToastProvider } from "@masumdev/rn-ui";
78
-
79
- export default function RootLayout() {
80
- return (
81
- <GestureHandlerRootView style={{ flex: 1 }}>
82
- <ThemeProvider defaultColorScheme="system">
83
- <ToastProvider placement="bottom">
84
- <Stack screenOptions={{ headerShown: false }} />
85
- </ToastProvider>
86
- </ThemeProvider>
87
- </GestureHandlerRootView>
88
- );
89
- }
90
- ```
51
+ ## Quick Setup
91
52
 
92
- Plain React Native example:
53
+ Wrap your application root with `GestureHandlerRootView` and `ThemeProvider`:
93
54
 
94
55
  ```tsx
95
56
  import { GestureHandlerRootView } from "react-native-gesture-handler";
@@ -99,7 +60,7 @@ export default function App() {
99
60
  return (
100
61
  <GestureHandlerRootView style={{ flex: 1 }}>
101
62
  <ThemeProvider defaultColorScheme="system">
102
- <ToastProvider>
63
+ <ToastProvider placement="bottom">
103
64
  <RootNavigator />
104
65
  </ToastProvider>
105
66
  </ThemeProvider>
@@ -108,1705 +69,39 @@ export default function App() {
108
69
  }
109
70
  ```
110
71
 
111
- ### 2. Configure Reanimated
112
-
113
- Expo SDKs usually create the correct Babel setup, but if your app manages Babel manually, keep the Reanimated plugin last.
114
-
115
- ```js
116
- module.exports = function (api) {
117
- api.cache(true);
118
-
119
- return {
120
- presets: ["babel-preset-expo"],
121
- plugins: ["react-native-reanimated/plugin"],
122
- };
123
- };
124
- ```
125
-
126
- ### 3. Wrap Once With ThemeProvider
127
-
128
- `defaultColorScheme` accepts:
129
-
130
- - `light`
131
- - `dark`
132
- - `system`
133
-
134
- `system` follows the device color scheme through React Native `useColorScheme()`.
135
-
136
- `ThemeProvider` should live once near the app root. Components read tokens through context, so nested providers are only needed if a subtree intentionally uses a different theme.
137
-
138
- ### 4. Add ToastProvider When Using Toast
139
-
140
- `useToast()` requires `ToastProvider` above the screen/component that calls it.
141
-
142
- ```tsx
143
- import { ToastProvider } from "@masumdev/rn-ui";
144
-
145
- <ToastProvider placement="bottom">
146
- <AppScreens />
147
- </ToastProvider>;
148
- ```
72
+ ---
149
73
 
150
- ## Usage
74
+ ## 🚀 Basic Usage
151
75
 
152
76
  ```tsx
153
- import { Badge, Box, Button, Card, Text, useTheme } from "@masumdev/rn-ui";
77
+ import React from "react";
78
+ import { Box, Card, Text, Badge, Button, useTheme } from "@masumdev/rn-ui";
154
79
 
155
- export function Example() {
156
- const { setColorScheme, toggleColorScheme } = useTheme();
80
+ export function ExampleScreen() {
81
+ const { toggleColorScheme } = useTheme();
157
82
 
158
83
  return (
159
- <Box flex={1} bg="background" p="lg" gap="md">
160
- <Card>
161
- <Badge tone="success">Active</Badge>
162
- <Text variant="h3">Reusable UI</Text>
163
- <Text color="textMuted">
164
- Theme tokens keep spacing, color, typography, and radius consistent.
84
+ <Box flex={1} bg="background" p="lg" gap="md" justify="center">
85
+ <Card elevated>
86
+ <Box row justify="space-between" align="center">
87
+ <Text variant="h3">@masumdev/rn-ui</Text>
88
+ <Badge tone="success">Active</Badge>
89
+ </Box>
90
+ <Text color="textMuted" style={{ marginTop: 8 }}>
91
+ Flat, token-driven React Native components built for speed and type-safety.
165
92
  </Text>
166
93
  </Card>
167
94
 
168
- <Button fullWidth onPress={toggleColorScheme}>
169
- Toggle Theme
170
- </Button>
171
-
172
- <Button variant="outline" onPress={() => setColorScheme("system")}>
173
- Follow System
95
+ <Button tone="primary" variant="filled" fullWidth onPress={toggleColorScheme}>
96
+ Toggle Theme Mode
174
97
  </Button>
175
98
  </Box>
176
99
  );
177
100
  }
178
101
  ```
179
102
 
180
- ## Custom Theme
181
-
182
- Override only the tokens you need. The library deep-merges your values with the default light and dark themes.
183
-
184
- When changing `primary`, also set `primarySoft`, `primaryStrong`, and `onPrimary` so filled buttons, soft badges, sliders, switches, focus states, and selected controls stay readable in both modes.
185
-
186
- ```tsx
187
- import { ThemeProvider } from "@masumdev/rn-ui";
188
-
189
- const themes = {
190
- light: {
191
- colors: {
192
- background: "#F6FBFC",
193
- surface: "#FFFFFF",
194
- text: "#06202A",
195
- textMuted: "#476371",
196
- primary: "#06B6D4",
197
- primarySoft: "#CFFAFE",
198
- primaryStrong: "#0891B2",
199
- onPrimary: "#06202A",
200
- accent: "#F43F5E",
201
- accentSoft: "#FFE4E6",
202
- border: "#B8D4DD",
203
- borderMuted: "#D8E8EE",
204
- },
205
- fonts: {
206
- regular: "OutfitRegular",
207
- medium: "OutfitMedium",
208
- semibold: "OutfitSemiBold",
209
- bold: "OutfitBold",
210
- },
211
- typography: {
212
- body: {
213
- fontSize: 16,
214
- },
215
- label: {
216
- letterSpacing: 0.2,
217
- },
218
- },
219
- radii: {
220
- lg: 14,
221
- xl: 18,
222
- },
223
- },
224
- dark: {
225
- colors: {
226
- background: "#06141B",
227
- surface: "#0B202A",
228
- text: "#F2FBFD",
229
- textMuted: "#B7CDD5",
230
- primary: "#67E8F9",
231
- primarySoft: "#164E63",
232
- primaryStrong: "#A5F3FC",
233
- onPrimary: "#06202A",
234
- accent: "#FB7185",
235
- accentSoft: "#4C1220",
236
- border: "#2A5260",
237
- borderMuted: "#173441",
238
- },
239
- },
240
- };
241
-
242
- export function App() {
243
- return (
244
- <ThemeProvider defaultColorScheme="system" themes={themes}>
245
- <RootNavigator />
246
- </ThemeProvider>
247
- );
248
- }
249
- ```
250
-
251
- Common tokens:
252
-
253
- - `colors.background`: screen background.
254
- - `colors.surface`: cards, menus, sheets, and panels.
255
- - `colors.text`, `textMuted`, `textSubtle`: text hierarchy.
256
- - `colors.primary`, `primarySoft`, `primaryStrong`, `onPrimary`: main action color system.
257
- - `colors.border`, `borderMuted`, `divider`: flat border system.
258
- - `spacing`: named spacing scale used by layout primitives.
259
- - `radii`: corner radius scale.
260
- - `typography`: text variants used by `Text`.
261
- - `components`: component-specific sizes such as `button`, `iconButton`, `switch`, `slider`, and `floatingActionButton`.
262
-
263
- ## Fonts
264
-
265
- Fonts are pluggable. `rn-ui` does not load font files by itself, so it works with Expo Font, local TTF files, React Native CLI font linking, or any other font-loading setup.
266
-
267
- Load the font in your app, then pass the registered font names through the `fonts` token.
268
-
269
- ```tsx
270
- import { useFonts } from "expo-font";
271
- import { ThemeProvider } from "@masumdev/rn-ui";
272
-
273
- const themes = {
274
- light: {
275
- fonts: {
276
- regular: "OutfitRegular",
277
- medium: "OutfitMedium",
278
- semibold: "OutfitSemiBold",
279
- bold: "OutfitBold",
280
- mono: "SpaceMono",
281
- },
282
- },
283
- dark: {
284
- fonts: {
285
- regular: "OutfitRegular",
286
- medium: "OutfitMedium",
287
- semibold: "OutfitSemiBold",
288
- bold: "OutfitBold",
289
- mono: "SpaceMono",
290
- },
291
- },
292
- };
293
-
294
- export function App() {
295
- const [loaded] = useFonts({
296
- OutfitRegular: require("./assets/fonts/Outfit-Regular.ttf"),
297
- OutfitMedium: require("./assets/fonts/Outfit-Medium.ttf"),
298
- OutfitSemiBold: require("./assets/fonts/Outfit-SemiBold.ttf"),
299
- OutfitBold: require("./assets/fonts/Outfit-Bold.ttf"),
300
- });
301
-
302
- if (!loaded) return null;
303
-
304
- return (
305
- <ThemeProvider themes={themes}>
306
- <RootNavigator />
307
- </ThemeProvider>
308
- );
309
- }
310
- ```
311
-
312
- Default mapping:
313
-
314
- - `display`, `h1`, `h2` use `fonts.bold`
315
- - `h3`, `title`, `subtitle` use `fonts.semibold`
316
- - `label`, `labelSmall` use `fonts.semibold` or `fonts.medium`
317
- - `body`, `bodySmall`, `caption` use `fonts.regular`
318
-
319
- You can still override one typography variant directly:
320
-
321
- ```tsx
322
- const themes = {
323
- light: {
324
- typography: {
325
- h1: {
326
- fontFamily: "CustomDisplayBold",
327
- fontSize: 34,
328
- lineHeight: 42,
329
- },
330
- },
331
- },
332
- };
333
- ```
334
-
335
- ## Persisting Theme Choice
336
-
337
- The core package does not depend on AsyncStorage, SQLite, Expo SecureStore, MMKV, or Zustand. Pass a small adapter from your app.
338
-
339
- `ThemeProvider` waits for storage hydration by default, so the app can avoid rendering light mode before the saved dark mode is loaded.
340
-
341
- ### Expo SecureStore
342
-
343
- ```tsx
344
- import * as SecureStore from "expo-secure-store";
345
- import { ThemeProvider } from "@masumdev/rn-ui";
346
-
347
- const storage = {
348
- getItem: (key: string) => SecureStore.getItemAsync(key),
349
- setItem: (key: string, value: string) => SecureStore.setItemAsync(key, value),
350
- };
351
-
352
- export function App() {
353
- return (
354
- <ThemeProvider storage={storage} defaultColorScheme="system">
355
- <RootNavigator />
356
- </ThemeProvider>
357
- );
358
- }
359
- ```
360
-
361
- ### AsyncStorage
362
-
363
- ```tsx
364
- import AsyncStorage from "@react-native-async-storage/async-storage";
365
- import { ThemeProvider } from "@masumdev/rn-ui";
366
-
367
- const storage = {
368
- getItem: (key: string) => AsyncStorage.getItem(key),
369
- setItem: (key: string, value: string) => AsyncStorage.setItem(key, value),
370
- };
371
-
372
- export function App() {
373
- return (
374
- <ThemeProvider storage={storage} defaultColorScheme="system">
375
- <RootNavigator />
376
- </ThemeProvider>
377
- );
378
- }
379
- ```
380
-
381
- Expo Go support depends on whether the chosen storage native module is available in the runtime. In the native playground, SecureStore is used because it works cleanly with the Expo workflow.
382
-
383
- ## Logging
384
-
385
- The library does not force logging. Apps can decide how noisy persistence logs should be.
386
-
387
- Recommended app pattern:
388
-
389
- ```tsx
390
- const ENABLE_THEME_DEBUG_LOGS = false;
391
-
392
- const debugTheme = (...args: unknown[]) => {
393
- if (__DEV__ && ENABLE_THEME_DEBUG_LOGS) {
394
- console.debug("[rn-ui]", ...args);
395
- }
396
- };
397
-
398
- const errorTheme = (...args: unknown[]) => {
399
- console.error("[rn-ui]", ...args);
400
- };
401
- ```
402
-
403
- Use debug logs for successful hydrate/save messages and error logs for failed storage operations.
404
-
405
- ## Components
406
-
407
- Current core components:
408
-
409
- - `Box`
410
- - `Text`
411
- - `BottomSheet`
412
- - `Accordion`
413
- - `Alert`
414
- - `AlertDialog`
415
- - `Button`
416
- - `IconButton`
417
- - `Badge`
418
- - `Card`
419
- - `Divider`
420
- - `AspectRatio`
421
- - `Attachment`
422
- - `Avatar`
423
- - `Bubble`
424
- - `ButtonGroup`
425
- - `Calendar`
426
- - `Carousel`
427
- - `Checkbox`
428
- - `Collapsible`
429
- - `Combobox`
430
- - `ContextMenu`
431
- - `DropdownMenu`
432
- - `Empty`
433
- - `HoverCard`
434
- - `Input`
435
- - `InputGroup`
436
- - `InputOTP`
437
- - `Item`
438
- - `KeyboardAvoiding`
439
- - `Label`
440
- - `FormField`
441
- - `Switch`
442
- - `RadioGroup`
443
- - `Slider`
444
- - `Rating`
445
- - `Progress`
446
- - `Skeleton`
447
- - `Tabs`
448
- - `Stepper`
449
- - `Sheet`
450
- - `Toast`
451
- - `Textarea`
452
- - `Select`
453
- - `Command`
454
- - `Popover`
455
- - `Pagination`
456
- - `Breadcrumb`
457
- - `Table`
458
- - `DataList`
459
- - `Timeline`
460
- - `MetricCard`
461
- - `FloatingActionButton`
462
-
463
- Icons are intentionally not tied to Ionicons or Expo. Pass any React node or render function.
464
-
465
- ```tsx
466
- import { Button } from "@masumdev/rn-ui";
467
- import { Ionicons } from "@expo/vector-icons";
468
-
469
- <Button
470
- leftIcon={({ color, size }) => (
471
- <Ionicons name="add" color={color} size={size} />
472
- )}
473
- >
474
- Create
475
- </Button>;
476
- ```
477
-
478
- ### Accordion
479
-
480
- Use `Accordion` for expandable flat bordered sections. It supports controlled and uncontrolled state.
481
-
482
- ```tsx
483
- import { Accordion, Text } from "@masumdev/rn-ui";
484
-
485
- <Accordion
486
- defaultOpenIds={["theme"]}
487
- items={[
488
- {
489
- id: "theme",
490
- title: "Theme tokens",
491
- subtitle: "Colors, fonts, spacing, and radius",
492
- content: "Accordion follows the same flat token-driven style.",
493
- },
494
- {
495
- id: "icons",
496
- title: "Generic icons",
497
- content: <Text color="textMuted">Icons can be render functions.</Text>,
498
- },
499
- ]}
500
- />;
501
- ```
502
-
503
- Controlled:
504
-
505
- ```tsx
506
- const [openIds, setOpenIds] = React.useState(["theme"]);
507
-
508
- <Accordion
509
- openIds={openIds}
510
- onOpenChange={setOpenIds}
511
- allowMultiple
512
- items={items}
513
- />;
514
- ```
515
-
516
- Animation:
517
-
518
- - Default animation uses Reanimated.
519
- - Uses the package Reanimated peer dependency.
520
- - Content animates height and opacity.
521
- - Indicator animates rotation.
522
- - Pass `animated={false}` to disable animation.
523
- - Pass `animationDuration` to tune timing.
524
-
525
- ```tsx
526
- <Accordion animationDuration={220} defaultOpenIds={["theme"]} items={items} />
527
- ```
528
-
529
- Custom animation can be plugged in through `animationComponents`:
530
-
531
- ```tsx
532
- import type {
533
- AccordionAnimatedContentProps,
534
- AccordionAnimatedIndicatorProps,
535
- } from "@masumdev/rn-ui";
536
-
537
- function CustomAccordionContent(props: AccordionAnimatedContentProps) {
538
- return <YourAnimatedContent {...props} />;
539
- }
540
-
541
- function CustomAccordionIndicator(props: AccordionAnimatedIndicatorProps) {
542
- return <YourAnimatedIndicator {...props} />;
543
- }
544
-
545
- <Accordion
546
- items={items}
547
- animationComponents={{
548
- Content: CustomAccordionContent,
549
- Indicator: CustomAccordionIndicator,
550
- }}
551
- />;
552
- ```
553
-
554
- ### Button
555
-
556
- Use `Button` for text and icon actions. `variant` controls visual treatment, while `tone` controls semantic color.
557
-
558
- ```tsx
559
- <Button variant="filled" tone="primary">
560
- Continue
561
- </Button>
562
-
563
- <Button variant="outline" tone="secondary">
564
- Cancel
565
- </Button>
566
-
567
- <Button tone="danger">Delete</Button>
568
- ```
569
-
570
- `variant="danger"` is still accepted for older usage, but new code should prefer `tone="danger"` so variants stay visual-only.
571
-
572
- ### IconButton
573
-
574
- Use `IconButton` for icon-only actions. Use `tone` for semantic token colors, or `color` for a token name/custom color override.
575
-
576
- ```tsx
577
- <IconButton
578
- icon={({ color, size }) => <Settings color={color} size={size} />}
579
- variant="outline"
580
- tone="secondary"
581
- />
582
-
583
- <IconButton
584
- icon={({ color, size }) => <Trash color={color} size={size} />}
585
- tone="danger"
586
- />
587
- ```
588
-
589
- ### BottomSheet
590
-
591
- Use `BottomSheet` for a theme-aware wrapper around `@gorhom/bottom-sheet`. The app must install Gorhom and its runtime peers.
592
-
593
- ```sh
594
- bun add @gorhom/bottom-sheet react-native-gesture-handler
595
- ```
596
-
597
- Wrap the app root with `GestureHandlerRootView` at app level:
598
-
599
- ```tsx
600
- import { GestureHandlerRootView } from "react-native-gesture-handler";
601
-
602
- <GestureHandlerRootView style={{ flex: 1 }}>
603
- <ThemeProvider>
604
- <App />
605
- </ThemeProvider>
606
- </GestureHandlerRootView>;
607
- ```
608
-
609
- If the app uses Reanimated 4, add the Worklets Babel plugin in the app config:
610
-
611
- ```js
612
- module.exports = function (api) {
613
- api.cache(true);
614
-
615
- return {
616
- presets: ["babel-preset-expo"],
617
- plugins: ["react-native-reanimated/plugin"],
618
- };
619
- };
620
- ```
621
-
622
- Use the themed wrapper:
623
-
624
- ```tsx
625
- import {
626
- BottomSheet,
627
- BottomSheetView,
628
- Button,
629
- Text,
630
- type BottomSheetMethods,
631
- } from '@masumdev/rn-ui';
632
-
633
- const bottomSheetRef = React.useRef<BottomSheetMethods>(null);
634
- const snapPoints = React.useMemo(() => ['35%', '70%'], []);
635
-
636
- <Button onPress={() => bottomSheetRef.current?.snapToIndex(0)}>
637
- Open Sheet
638
- </Button>
639
-
640
- <BottomSheet
641
- ref={bottomSheetRef}
642
- index={-1}
643
- snapPoints={snapPoints}
644
- enablePanDownToClose
645
- >
646
- <BottomSheetView>
647
- <Text variant="title">Theme-aware sheet</Text>
648
- </BottomSheetView>
649
- </BottomSheet>
650
- ```
651
-
652
- The wrapper maps theme tokens to Gorhom props:
653
-
654
- - `backgroundStyle` uses `colors.surface`, `colors.border`, and `radii.xxl`
655
- - `handleIndicatorStyle` uses `colors.border`
656
- - `style` keeps shadow/elevation at zero
657
- - `backdropComponent` defaults to a themed `BottomSheetBackdrop`
658
-
659
- Useful wrapper props:
660
-
661
- - `withBackdrop`
662
- - `backdropOpacity`
663
- - `backdropAppearsOnIndex`
664
- - `backdropDisappearsOnIndex`
665
- - `backdropPressBehavior`
666
- - `backdropStyle`
667
-
668
- Gorhom primitives are re-exported for convenience: `BottomSheetView`, `BottomSheetScrollView`, `BottomSheetFlatList`, `BottomSheetSectionList`, `BottomSheetTextInput`, `BottomSheetModal`, `BottomSheetModalProvider`, `useBottomSheet`, and `useBottomSheetModal`.
669
-
670
- ### Alert
671
-
672
- Use `Alert` for inline feedback. It supports semantic tones, flat variants, generic icons, optional action, and optional close control.
673
-
674
- ```tsx
675
- import { Alert } from "@masumdev/rn-ui";
676
-
677
- <Alert tone="info" title="Information">
678
- This message uses theme tokens and adapts to light or dark mode.
679
- </Alert>;
680
- ```
681
-
682
- With icon and action:
683
-
684
- ```tsx
685
- <Alert
686
- tone="success"
687
- variant="outline"
688
- icon={({ color, size }) => <Icon name="check" color={color} size={size} />}
689
- action={{
690
- label: "View details",
691
- onPress: openDetails,
692
- }}
693
- >
694
- Your changes were saved.
695
- </Alert>
696
- ```
697
-
698
- Dismissible alert:
699
-
700
- ```tsx
701
- <Alert
702
- tone="warning"
703
- title="Unsaved changes"
704
- dismissible
705
- closeIcon={({ color, size }) => <Icon name="x" color={color} size={size} />}
706
- >
707
- This alert removes itself when the close button is pressed.
708
- </Alert>
709
- ```
710
-
711
- `icon`, `action.icon`, and `closeIcon` are all pluggable through `RenderIcon`.
712
-
713
- Dismiss animations use Reanimated by default. Use `animated={false}` to disable or `animationDuration` to tune timing.
714
-
715
- ```tsx
716
- <Alert dismissible animationDuration={220}>
717
- Animated dismissible alert.
718
- </Alert>
719
- ```
720
-
721
- Action icons can be fully overridden, including custom open/close animation owned by the app:
722
-
723
- ```tsx
724
- <Alert
725
- action={{
726
- label: expanded ? "Hide details" : "View details",
727
- icon: ({ color, size }) => (
728
- <AnimatedChevron expanded={expanded} color={color} size={size} />
729
- ),
730
- onPress: () => setExpanded((value) => !value),
731
- }}
732
- >
733
- Alert content.
734
- </Alert>
735
- ```
736
-
737
- ### AlertDialog
738
-
739
- Use `AlertDialog` for modal confirmation and blocking feedback. It uses React Native `Modal` and Reanimated by default.
740
-
741
- ```tsx
742
- const [visible, setVisible] = React.useState(false);
743
-
744
- <Button onPress={() => setVisible(true)}>Delete</Button>
745
-
746
- <AlertDialog
747
- visible={visible}
748
- tone="danger"
749
- title="Delete item?"
750
- description="This action cannot be undone."
751
- confirmText="Delete"
752
- cancelText="Cancel"
753
- onConfirm={deleteItem}
754
- onCancel={() => setVisible(false)}
755
- onClose={() => setVisible(false)}
756
- />
757
- ```
758
-
759
- With pluggable icons:
760
-
761
- ```tsx
762
- <AlertDialog
763
- visible={visible}
764
- icon={({ color, size }) => <Trash color={color} size={size} />}
765
- closeIcon={({ color, size }) => <X color={color} size={size} />}
766
- onClose={() => setVisible(false)}
767
- />
768
- ```
769
-
770
- Useful props:
771
-
772
- - `dismissOnBackdropPress`
773
- - `confirmLoading`
774
- - `confirmDisabled`
775
- - `cancelDisabled`
776
- - `animated`
777
- - `animationDuration`
778
- - `modalProps`
779
-
780
- Android notes:
781
-
782
- - `AlertDialog` enables `statusBarTranslucent`, `navigationBarTranslucent`, and `hardwareAccelerated` by default so the backdrop can cover modern Android system UI areas more consistently.
783
- - If an app uses custom edge-to-edge or navigation bar handling, override native modal behavior through `modalProps`.
784
- - Android navigation bar behavior is controlled by system UI, not by the modal backdrop view. If the app needs to hide or style the navigation bar while a dialog is open, handle it at app level with the system UI solution already used by that app. `rn-ui` does not depend on Expo navigation-bar APIs.
785
-
786
- ### AspectRatio
787
-
788
- Use `AspectRatio` to display layout/media with a specific proportion. The child element automatically stretches to fill the container.
789
-
790
- ```tsx
791
- import { AspectRatio } from "@masumdev/rn-ui";
792
- import { Image } from "react-native";
793
-
794
- <AspectRatio ratio={16 / 9} radius="md">
795
- <Image
796
- source={{
797
- uri: "https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe",
798
- }}
799
- style={{ resizeMode: "cover" }}
800
- />
801
- </AspectRatio>;
802
- ```
803
-
804
- ### Attachment
805
-
806
- Use `Attachment` to represent file/image uploads or documents. Supports grid-like `card` previews and full-width list `row` views with status indicators.
807
-
808
- ```tsx
809
- import { Attachment } from '@masumdev/rn-ui';
810
-
811
- // Card layout (Image preview)
812
- <Attachment
813
- layout="card"
814
- name="workspace.png"
815
- description="PNG • 820 KB"
816
- thumbnail="https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe"
817
- onRemove={removeFile}
818
- />
819
-
820
- // Row layout (Document preview)
821
- <Attachment
822
- layout="row"
823
- name="sales-dashboard.pdf"
824
- description="Uploading • 64%"
825
- descriptionTone="info"
826
- loading
827
- onRemove={removeFile}
828
- />
829
- ```
830
-
831
- `descriptionTone` accepts `default`, `info`, `success`, `warning`, and `danger`. Use it instead of deriving visual state from description copy. `thumbnail`, `fileIcon`, and `closeIcon` are pluggable through `RenderIcon`.
832
-
833
- ### Avatar
834
-
835
- Use `Avatar` to display user profile images. Supports sizes (`sm`, `default`, `lg`), custom fallback placeholders, activity badges, and overlapping avatar groups.
836
-
837
- ```tsx
838
- import {
839
- Avatar,
840
- AvatarImage,
841
- AvatarFallback,
842
- AvatarBadge,
843
- AvatarGroup,
844
- AvatarGroupCount,
845
- } from '@masumdev/rn-ui';
846
-
847
- // Individual Avatar with Badge
848
- <Avatar size="lg">
849
- <AvatarImage source={{ uri: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb' }} />
850
- <AvatarFallback>JD</AvatarFallback>
851
- <AvatarBadge bg={colors.success} />
852
- </Avatar>
853
-
854
- // Avatar Group
855
- <AvatarGroup size="default">
856
- <Avatar>
857
- <AvatarImage source={{ uri: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb' }} />
858
- <AvatarFallback>JD</AvatarFallback>
859
- </Avatar>
860
- <Avatar>
861
- <AvatarImage source={{ uri: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d' }} />
862
- <AvatarFallback>AM</AvatarFallback>
863
- </Avatar>
864
- <AvatarGroupCount count={5} />
865
- </AvatarGroup>
866
- ```
867
-
868
- ### Bubble
869
-
870
- Use `BubbleGroup`, `Bubble`, `BubbleContent`, and `BubbleReactions` to display conversation bubbles (chat messages) with support for variants, alignments, and overlay reaction tags.
871
-
872
- ```tsx
873
- import {
874
- BubbleGroup,
875
- Bubble,
876
- BubbleContent,
877
- BubbleReactions,
878
- Text,
879
- } from "@masumdev/rn-ui";
880
-
881
- <BubbleGroup>
882
- {/* Incoming message */}
883
- <Bubble align="start" variant="secondary">
884
- <BubbleContent>Hello! How can I help you today?</BubbleContent>
885
- </Bubble>
886
-
887
- {/* Outgoing message with reactions */}
888
- <Bubble align="end" variant="default">
889
- <BubbleContent>I'd like to customize the colors of my theme.</BubbleContent>
890
- <BubbleReactions side="bottom" align="end">
891
- <Text style={{ fontSize: 11 }}>👍 1</Text>
892
- </BubbleReactions>
893
- </Bubble>
894
- </BubbleGroup>;
895
- ```
896
-
897
- ### ButtonGroup
898
-
899
- Use `ButtonGroup` to group buttons, static text containers, and separators horizontally or vertically with unified borders and border radii.
900
-
901
- ```tsx
902
- import {
903
- ButtonGroup,
904
- ButtonGroupText,
905
- ButtonGroupSeparator,
906
- Button,
907
- } from "@masumdev/rn-ui";
908
-
909
- <ButtonGroup orientation="horizontal">
910
- <ButtonGroupText>Prefix</ButtonGroupText>
911
- <Button variant="outline">Action A</Button>
912
- <ButtonGroupSeparator />
913
- <Button variant="outline">Action B</Button>
914
- </ButtonGroup>;
915
- ```
916
-
917
- ### Calendar
918
-
919
- Use `Calendar` to render date pickers and handle single date or range select.
920
-
921
- ```tsx
922
- import { Calendar } from "@masumdev/rn-ui";
923
-
924
- <Calendar
925
- markedDates={{
926
- "2026-07-12": { selected: true, startingDay: true },
927
- "2026-07-13": { selected: true, color: "muted" },
928
- "2026-07-14": { selected: true, endingDay: true },
929
- }}
930
- />;
931
- ```
932
-
933
- ### Carousel
934
-
935
- Use `Carousel` for horizontally scrollable card decks. Pagination is on by default and next/previous icons are pluggable.
936
-
937
- ```tsx
938
- import {
939
- Carousel,
940
- CarouselContent,
941
- CarouselItem,
942
- CarouselPrevious,
943
- CarouselNext,
944
- } from "@masumdev/rn-ui";
945
-
946
- <Carousel itemWidth={280}>
947
- <CarouselContent>
948
- <CarouselItem>
949
- <Card>
950
- <Text>Slide one</Text>
951
- </Card>
952
- </CarouselItem>
953
- <CarouselItem>
954
- <Card>
955
- <Text>Slide two</Text>
956
- </Card>
957
- </CarouselItem>
958
- </CarouselContent>
959
- <CarouselPrevious
960
- icon={({ color, size }) => <ChevronLeft color={color} size={size} />}
961
- />
962
- <CarouselNext
963
- icon={({ color, size }) => <ChevronRight color={color} size={size} />}
964
- />
965
- </Carousel>;
966
- ```
967
-
968
- ### Checkbox
969
-
970
- Use `Checkbox` for controlled boolean state. The check icon is pluggable.
971
-
972
- ```tsx
973
- <Checkbox
974
- checked={checked}
975
- onCheckedChange={setChecked}
976
- icon={({ color, size }) => <Check color={color} size={size} />}
977
- />
978
- ```
979
-
980
- ### Collapsible
981
-
982
- Use `Collapsible` for composable expandable content.
983
-
984
- ```tsx
985
- <Collapsible defaultOpen>
986
- <CollapsibleTrigger>
987
- <Text variant="label">Toggle details</Text>
988
- </CollapsibleTrigger>
989
- <CollapsibleContent>
990
- <Text color="textMuted">Hidden content.</Text>
991
- </CollapsibleContent>
992
- </Collapsible>
993
- ```
994
-
995
- ### Combobox
996
-
997
- Use `Combobox` for searchable selection. It uses React Native `Modal` by default, stays flat by default, and exposes `modalProps`, `overlayStyle`, `chevronIcon`, and `checkIcon` for app-level customization.
998
-
999
- ```tsx
1000
- <Combobox value={value} onValueChange={setValue}>
1001
- <ComboboxInput
1002
- placeholder="Select framework"
1003
- chevronIcon={({ color, size }) => (
1004
- <ChevronsUpDown color={color} size={size} />
1005
- )}
1006
- />
1007
- <ComboboxContent>
1008
- <ComboboxList>
1009
- <ComboboxItem value="expo" label="Expo">
1010
- Expo
1011
- </ComboboxItem>
1012
- <ComboboxItem value="react-native" label="React Native">
1013
- React Native
1014
- </ComboboxItem>
1015
- <ComboboxEmpty>No results.</ComboboxEmpty>
1016
- </ComboboxList>
1017
- </ComboboxContent>
1018
- </Combobox>
1019
- ```
1020
-
1021
- ### ContextMenu
1022
-
1023
- Use `ContextMenu` for long-press menus. It uses React Native `Modal` by default and keeps system UI behavior app-overridable through `modalProps`.
1024
-
1025
- ```tsx
1026
- <ContextMenu>
1027
- <ContextMenuTrigger>
1028
- <Button variant="outline">Long press</Button>
1029
- </ContextMenuTrigger>
1030
- <ContextMenuContent>
1031
- <ContextMenuLabel>Actions</ContextMenuLabel>
1032
- <ContextMenuItem onPress={editItem}>Edit</ContextMenuItem>
1033
- <ContextMenuCheckboxItem checked={pinned} onCheckedChange={setPinned}>
1034
- Pinned
1035
- </ContextMenuCheckboxItem>
1036
- <ContextMenuSeparator />
1037
- <ContextMenuItem variant="destructive" onPress={deleteItem}>
1038
- Delete
1039
- </ContextMenuItem>
1040
- </ContextMenuContent>
1041
- </ContextMenu>
1042
- ```
1043
-
1044
- ### DropdownMenu
1045
-
1046
- Use `DropdownMenu` for tap-triggered action menus. It uses React Native `Modal`, Reanimated entry animation, flat bordered styling, alignment control, checkbox items, shortcuts, and app-overridable modal/backdrop props.
1047
-
1048
- ```tsx
1049
- <DropdownMenu>
1050
- <DropdownMenuTrigger style={triggerStyle}>
1051
- <Text variant="label">Open menu</Text>
1052
- </DropdownMenuTrigger>
1053
- <DropdownMenuContent align="start">
1054
- <DropdownMenuLabel>Actions</DropdownMenuLabel>
1055
- <DropdownMenuItem onPress={refreshList}>
1056
- Refresh
1057
- <DropdownMenuShortcut>R</DropdownMenuShortcut>
1058
- </DropdownMenuItem>
1059
- <DropdownMenuCheckboxItem checked={compact} onCheckedChange={setCompact}>
1060
- Compact mode
1061
- </DropdownMenuCheckboxItem>
1062
- <DropdownMenuSeparator />
1063
- <DropdownMenuItem variant="destructive" onPress={deleteItem}>
1064
- Delete
1065
- </DropdownMenuItem>
1066
- </DropdownMenuContent>
1067
- </DropdownMenu>
1068
- ```
1069
-
1070
- Useful props:
1071
-
1072
- - `open`, `defaultOpen`, and `onOpenChange`
1073
- - `align="start" | "end"`
1074
- - `width`, `maxHeight`, and `sideOffset`
1075
- - `modalProps` and `overlayStyle`
1076
- - `checkIcon` on `DropdownMenuCheckboxItem`
1077
-
1078
- Avoid nesting another `Pressable` or `Button` directly inside `DropdownMenuTrigger`; style the trigger itself or render non-pressable visual children inside it.
1079
-
1080
- ### Empty
1081
-
1082
- Use `Empty` for empty states such as no projects, no data, or no search results. It is composable and mirrors the web pattern with React Native primitives.
1083
-
1084
- ```tsx
1085
- <Empty>
1086
- <EmptyHeader>
1087
- <EmptyMedia variant="icon">
1088
- <FileText color={colors.text} size={16} />
1089
- </EmptyMedia>
1090
- <EmptyTitle>Expo React Native</EmptyTitle>
1091
- <EmptyDescription>
1092
- Expo React Native by Ma'sum. Crafted for consistent mobile UI in 2026.
1093
- </EmptyDescription>
1094
- </EmptyHeader>
1095
-
1096
- <EmptyContent>
1097
- <Box row center gap="sm">
1098
- <Button size="sm">Explore 2026</Button>
1099
- <Button size="sm" variant="outline" tone="secondary">
1100
- by Ma'sum
1101
- </Button>
1102
- </Box>
1103
- <Button size="sm" variant="ghost" tone="secondary">
1104
- Expo React Native
1105
- </Button>
1106
- </EmptyContent>
1107
- </Empty>
1108
- ```
1109
-
1110
- Parts:
1111
-
1112
- - `Empty`
1113
- - `EmptyHeader`
1114
- - `EmptyMedia`
1115
- - `EmptyTitle`
1116
- - `EmptyDescription`
1117
- - `EmptyContent`
1118
-
1119
- ### HoverCard
1120
-
1121
- Use `HoverCard` for richer contextual previews. On mobile, the default trigger is `longPress`.
1122
-
1123
- ```tsx
1124
- <HoverCard openDelay={10} closeDelay={100}>
1125
- <HoverCardTrigger style={triggerStyle}>
1126
- <Text variant="label" color="primary">
1127
- Expo React Native
1128
- </Text>
1129
- </HoverCardTrigger>
1130
- <HoverCardContent>
1131
- <Box gap="xs">
1132
- <Text variant="label">Expo React Native</Text>
1133
- <Text variant="bodySmall" color="textMuted">
1134
- Expo React Native by Ma'sum.
1135
- </Text>
1136
- <Text variant="caption" color="textSubtle">
1137
- Highlight 2026
1138
- </Text>
1139
- </Box>
1140
- </HoverCardContent>
1141
- </HoverCard>
1142
- ```
1143
-
1144
- Useful props:
1145
-
1146
- - `open`, `defaultOpen`, and `onOpenChange`
1147
- - `openDelay` and `closeDelay`
1148
- - `triggerMode="longPress" | "press" | "manual"`
1149
- - `align="start" | "center" | "end"`
1150
- - `width`, `maxHeight`, `sideOffset`, `modalProps`, and `overlayStyle`
1151
-
1152
- ### Input
1153
-
1154
- Use `Input` for token-based text fields. It wraps React Native `TextInput`, supports light/dark mode, and keeps the default style flat with a clear border.
1155
-
1156
- ```tsx
1157
- const [value, setValue] = React.useState("Expo React Native by Ma'sum");
1158
-
1159
- <Input
1160
- value={value}
1161
- onChangeText={setValue}
1162
- placeholder="Expo React Native by Ma'sum"
1163
- />
1164
-
1165
- <Input
1166
- type="email"
1167
- placeholder="expo-react-native@masum.dev"
1168
- />
1169
-
1170
- <Input
1171
- invalid
1172
- value="Expo React Native by Ma'sum, 2026"
1173
- onChangeText={() => undefined}
1174
- />
1175
- ```
1176
-
1177
- Useful props:
1178
-
1179
- - `type="text" | "email" | "number" | "password" | "tel" | "url"`
1180
- - `size="sm" | "md" | "lg"`
1181
- - `invalid`, `disabled`, and `fullWidth`
1182
- - All standard React Native `TextInputProps`
1183
-
1184
- ### InputGroup
1185
-
1186
- Use `InputGroup` when an input needs inline addons, result counts, small actions, or a multiline grouped field.
1187
-
1188
- ```tsx
1189
- <InputGroup>
1190
- <InputGroupAddon>
1191
- <Search color={colors.textMuted} size={16} />
1192
- </InputGroupAddon>
1193
- <InputGroupInput placeholder="Search..." />
1194
- <InputGroupAddon align="inline-end">
1195
- <InputGroupText>12 results</InputGroupText>
1196
- </InputGroupAddon>
1197
- </InputGroup>
1198
-
1199
- <InputGroup>
1200
- <InputGroupInput placeholder="Enter password" secureTextEntry />
1201
- <InputGroupAddon align="inline-end">
1202
- <EyeOff color={colors.textMuted} size={16} />
1203
- </InputGroupAddon>
1204
- </InputGroup>
1205
-
1206
- <InputGroup orientation="block">
1207
- <InputGroupAddon align="block-start">
1208
- <InputGroupText>Expo React Native by Ma'sum</InputGroupText>
1209
- </InputGroupAddon>
1210
- <InputGroupTextarea placeholder="Highlight 2026" />
1211
- <InputGroupAddon align="block-end">
1212
- <InputGroupButton size="xs">Send</InputGroupButton>
1213
- </InputGroupAddon>
1214
- </InputGroup>
1215
-
1216
- <InputGroup orientation="block">
1217
- <InputGroupInput placeholder="Enter amount" />
1218
- <InputGroupAddon align="block-end">
1219
- <InputGroupText>USD</InputGroupText>
1220
- </InputGroupAddon>
1221
- </InputGroup>
1222
- ```
1223
-
1224
- Parts:
1225
-
1226
- - `InputGroup`
1227
- - `InputGroupAddon`
1228
- - `InputGroupButton`
1229
- - `InputGroupText`
1230
- - `InputGroupInput`
1231
- - `InputGroupTextarea`
1232
-
1233
- Useful props:
1234
-
1235
- - `orientation="inline" | "block"`
1236
- - `InputGroupAddon align="inline-start" | "inline-end" | "block-start" | "block-end"`
1237
- - `InputGroupButton size="xs" | "sm" | "icon-xs" | "icon-sm"`
1238
- - `invalid` and `disabled` can be set on the group or input control
1239
-
1240
- ### InputOTP
1241
-
1242
- Use `InputOTP` for one-time passcode fields. The root owns the hidden native `TextInput`; slots render the visual code boxes.
1243
-
1244
- ```tsx
1245
- const [otp, setOtp] = React.useState("");
1246
-
1247
- <InputOTP value={otp} onChangeText={setOtp} maxLength={6}>
1248
- <InputOTPGroup>
1249
- <InputOTPSlot index={0} />
1250
- <InputOTPSlot index={1} />
1251
- <InputOTPSlot index={2} />
1252
- <InputOTPSeparator />
1253
- <InputOTPSlot index={3} />
1254
- <InputOTPSlot index={4} />
1255
- <InputOTPSlot index={5} />
1256
- </InputOTPGroup>
1257
- </InputOTP>
1258
-
1259
- <InputOTP maxLength={4} invalid>
1260
- <InputOTPGroup>
1261
- <InputOTPSlot index={0} />
1262
- <InputOTPSlot index={1} />
1263
- <InputOTPSlot index={2} />
1264
- <InputOTPSlot index={3} />
1265
- </InputOTPGroup>
1266
- </InputOTP>
1267
- ```
1268
-
1269
- Parts:
1270
-
1271
- - `InputOTP`
1272
- - `InputOTPGroup`
1273
- - `InputOTPSlot`
1274
- - `InputOTPSeparator`
1275
-
1276
- Useful props:
1277
-
1278
- - `value`, `defaultValue`, and `onChangeText`
1279
- - `maxLength`, `disabled`, `invalid`, and `autoFocus`
1280
- - `textInputProps` for native `TextInput` overrides
1281
-
1282
- ### Item
1283
-
1284
- Use `Item` primitives for reusable list rows and grouped content.
1285
-
1286
- ```tsx
1287
- <ItemGroup>
1288
- <Item variant="outline">
1289
- <ItemMedia variant="icon">
1290
- <Inbox color={colors.primary} size={20} />
1291
- </ItemMedia>
1292
- <ItemContent>
1293
- <ItemTitle>Expo React Native</ItemTitle>
1294
- <ItemDescription>
1295
- Reusable item row by Ma'sum for consistent 2026 mobile lists.
1296
- </ItemDescription>
1297
- </ItemContent>
1298
- <ItemActions>
1299
- <Badge tone="success" variant="soft">
1300
- Active
1301
- </Badge>
1302
- </ItemActions>
1303
- </Item>
1304
-
1305
- <ItemSeparator />
1306
-
1307
- <Item variant="muted" size="sm">
1308
- <ItemHeader>
1309
- <ItemTitle>Theme tokens</ItemTitle>
1310
- <Badge tone="info" variant="outline">
1311
- 2026
1312
- </Badge>
1313
- </ItemHeader>
1314
- <ItemContent>
1315
- <ItemDescription>
1316
- Header and footer areas stay full width.
1317
- </ItemDescription>
1318
- </ItemContent>
1319
- <ItemFooter>
1320
- <Text variant="caption" color="textMuted">
1321
- by Ma'sum
1322
- </Text>
1323
- <Button size="xs" variant="ghost" tone="secondary">
1324
- View
1325
- </Button>
1326
- </ItemFooter>
1327
- </Item>
1328
- </ItemGroup>
1329
- ```
1330
-
1331
- Parts:
1332
-
1333
- - `ItemGroup`
1334
- - `Item`
1335
- - `ItemMedia`
1336
- - `ItemContent`
1337
- - `ItemTitle`
1338
- - `ItemDescription`
1339
- - `ItemActions`
1340
- - `ItemHeader`
1341
- - `ItemFooter`
1342
- - `ItemSeparator`
1343
-
1344
- Useful props:
1345
-
1346
- - `Item variant="default" | "outline" | "muted"`
1347
- - `Item size="default" | "sm" | "xs"`
1348
- - `ItemMedia variant="default" | "icon" | "image"`
1349
-
1350
- ### Toast
1351
-
1352
- Wrap the app once with `ToastProvider`, then use `useToast()` from any screen.
1353
-
1354
- ```tsx
1355
- <ThemeProvider>
1356
- <ToastProvider placement="top">
1357
- <App />
1358
- </ToastProvider>
1359
- </ThemeProvider>
1360
- ```
1361
-
1362
- ```tsx
1363
- const toast = useToast();
1364
-
1365
- toast.show({
1366
- title: "Expo React Native",
1367
- description: "Toast by Ma'sum for 2026 mobile UI.",
1368
- tone: "success",
1369
- icon: ({ color, size }) => <Check color={color} size={size} />,
1370
- action: {
1371
- label: "Undo",
1372
- onPress: handleUndo,
1373
- },
1374
- });
1375
- ```
1376
-
1377
- Parts and APIs:
1378
-
1379
- - `ToastProvider`
1380
- - `useToast`
1381
- - `ToastViewport`
1382
- - `Toast`
1383
- - `ToastContent`
1384
- - `ToastTitle`
1385
- - `ToastDescription`
1386
- - `ToastAction`
1387
- - `ToastClose`
1388
-
1389
- Useful props:
1390
-
1391
- - `ToastProvider placement="top" | "bottom"`
1392
- - `offset` to control distance from the top/bottom edge; Android top placement accounts for `StatusBar.currentHeight`, and Android bottom placement leaves extra room for navigation controls by default
1393
- - `duration`, `maxToasts`, `swipeToDismiss`, `viewportStyle`, and `renderToast`
1394
- - `toast.show({ title, description, tone, icon, closeIcon, action, duration })`
1395
- - `toast.dismiss(id?)` and `toast.update(id, options)`
1396
-
1397
- ### Form And Controls
1398
-
1399
- Use these primitives for common form, preference, loading, and local navigation UI.
1400
-
1401
- ```tsx
1402
- <FormField required>
1403
- <FormLabel>Expo React Native</FormLabel>
1404
- <FormControl>
1405
- <Input placeholder="Expo React Native by Ma'sum" />
1406
- </FormControl>
1407
- <FormDescription>Consistent field copy.</FormDescription>
1408
- <FormMessage>Shown when the field is invalid.</FormMessage>
1409
- </FormField>
1410
-
1411
- <Label required requiredIndicator=" (required)">
1412
- Expo React Native
1413
- </Label>
1414
-
1415
- <Switch value={enabled} onValueChange={setEnabled} />
1416
- <Switch value={enabled} onValueChange={setEnabled} size="lg" tone="success" />
1417
-
1418
- <RadioGroup value={value} onValueChange={setValue}>
1419
- <RadioGroupItem value="expo" label="Expo React Native" />
1420
- </RadioGroup>
1421
-
1422
- <Slider
1423
- value={64}
1424
- tone="accent"
1425
- onValueChange={setValue}
1426
- onSlidingComplete={saveValue}
1427
- />
1428
- <Progress value={64} />
1429
- <Skeleton style={{ height: 16, width: "72%" }} />
1430
-
1431
- <Tabs value={tab} onValueChange={setTab}>
1432
- <TabsList>
1433
- <TabsTrigger value="preview">Preview</TabsTrigger>
1434
- <TabsTrigger value="tokens">Tokens</TabsTrigger>
1435
- </TabsList>
1436
- <TabsContent value="preview">
1437
- <Text>Expo React Native by Ma'sum</Text>
1438
- </TabsContent>
1439
- </Tabs>
1440
-
1441
- <Stepper value={2} onValueChange={setValue} min={0} max={9} />
1442
- ```
1443
-
1444
- Parts and APIs:
1445
-
1446
- - `Label` with `required`, `requiredIndicator`, and `requiredIndicatorStyle`
1447
- - `FormField`, `FormLabel`, `FormControl`, `FormDescription`, `FormMessage`, and `useFormField`
1448
- - `Switch` with `size`, `tone`, `activeIcon`, `inactiveIcon`, `thumbContent`, `activeThumbContent`, `inactiveThumbContent`, `renderThumb`, `trackStyle`, and `thumbStyle`
1449
- - `RadioGroup` and `RadioGroupItem`
1450
- - `Slider` with `tone`, `step`, tap-to-seek, hold feedback, smooth drag gestures, `trackStyle`, `activeTrackStyle`, and `thumbStyle`
1451
- - `Rating` with `shape` (`star`, `heart`, `thumb`, `fire`, `smile`, `shield`), `precision` (`full`, `half`, `exact`, float number), `size`, `tone`, `color`, `emptyColor`, `readOnly`, `allowClear`, `showValue`, `renderItem`, `icon`, tap & drag gestures, and dual-layer partial fill clipping
1452
- - `Progress`
1453
- - `Skeleton`
1454
- - `Tabs`, `TabsList`, `TabsTrigger`, and `TabsContent`
1455
- - `Stepper`
1456
-
1457
- `Switch` is a custom Reanimated control, not the platform `Switch`. It keeps a
1458
- simple controlled API while rendering a flat bordered track, animated thumb,
1459
- theme-aware tone, and optional thumb icons.
1460
-
1461
- Use `thumbContent` for a simple ReactNode inside the thumb, or
1462
- `activeThumbContent` / `inactiveThumbContent` when the content should change
1463
- between states. Each content prop also accepts a render function with
1464
- `{ checked, disabled, invalid, color, size }`.
1465
-
1466
- `Slider` uses React Native Gesture Handler and Reanimated for tap-to-seek,
1467
- press/hold feedback, smooth horizontal dragging, and spring snapping on release.
1468
- Apps must keep `GestureHandlerRootView` at the native root, which is also
1469
- required by BottomSheet.
1470
-
1471
- `Rating` provides high-precision tap & drag gesture interaction for review and feedback scores.
1472
- It supports preset vector shapes (`star`, `heart`, `thumb`, `fire`, `smile`, `shield`), custom `RenderIcon` components, and custom `renderItem` functions.
1473
- Partial fill calculations use dual-layer overflow container clipping for 100% accurate fractional display (such as 3.4 or 4.5).
1474
- Precision options include `"full"` (1), `"half"` (0.5), `"exact"` (0.1), or custom float numbers.
1475
-
1476
-
1477
- ### Sheet
1478
-
1479
- Use `Sheet` as a higher-level wrapper around the package BottomSheet integration.
1480
-
1481
- ```tsx
1482
- <Sheet ref={sheetRef} snapPoints={["35%", "70%"]}>
1483
- <SheetContent>
1484
- <SheetHeader>
1485
- <SheetTitle>Expo React Native Sheet</SheetTitle>
1486
- <SheetDescription>by Ma'sum, 2026.</SheetDescription>
1487
- </SheetHeader>
1488
- <SheetFooter>
1489
- <Button onPress={() => sheetRef.current?.close()}>Close</Button>
1490
- </SheetFooter>
1491
- </SheetContent>
1492
- </Sheet>
1493
- ```
1494
-
1495
- `Sheet` defaults to `index={-1}`, `animateOnMount={false}`, and
1496
- `enablePanDownToClose` so it stays closed on initial screen render and only
1497
- opens when the app calls methods such as `snapToIndex(0)`.
1498
-
1499
- Parts:
1500
-
1501
- - `Sheet`
1502
- - `SheetContent`
1503
- - `SheetHeader`
1504
- - `SheetTitle`
1505
- - `SheetDescription`
1506
- - `SheetFooter`
1507
-
1508
- ### Data And Overlays
1509
-
1510
- Use these primitives for multiline fields, mobile selection, command sheets, anchored content, and compact data display.
1511
-
1512
- ```tsx
1513
- <Textarea placeholder="Write Expo React Native notes by Ma'sum..." />
1514
-
1515
- <Select
1516
- value={value}
1517
- onValueChange={setValue}
1518
- options={[{ value: "expo", label: "Expo React Native" }]}
1519
- />
1520
-
1521
- <Command
1522
- visible={visible}
1523
- onClose={close}
1524
- items={[{ value: "theme", label: "Theme tokens" }]}
1525
- onSelect={handleSelect}
1526
- />
1527
-
1528
- <Popover>
1529
- <PopoverTrigger>
1530
- <Text>Open Popover</Text>
1531
- </PopoverTrigger>
1532
- <PopoverContent>
1533
- <Text>Expo React Native by Ma'sum</Text>
1534
- </PopoverContent>
1535
- </Popover>
1536
-
1537
- <Pagination page={1} pageCount={5} onPageChange={setPage} />
1538
-
1539
- <Breadcrumb>
1540
- <BreadcrumbLink>Expo</BreadcrumbLink>
1541
- <BreadcrumbSeparator />
1542
- <BreadcrumbPage>Ma'sum</BreadcrumbPage>
1543
- </Breadcrumb>
1544
-
1545
- <Table>
1546
- <TableRow>
1547
- <TableHead>Name</TableHead>
1548
- <TableHead>Status</TableHead>
1549
- </TableRow>
1550
- <TableRow>
1551
- <TableCell>Expo React Native</TableCell>
1552
- <TableCell>Active</TableCell>
1553
- </TableRow>
1554
- </Table>
1555
-
1556
- <DataList>
1557
- <DataListItem>
1558
- <DataListLabel>Framework</DataListLabel>
1559
- <DataListValue>Expo React Native</DataListValue>
1560
- </DataListItem>
1561
- </DataList>
1562
-
1563
- <Timeline>
1564
- <TimelineItem active>
1565
- <TimelineTitle>Theme tokens</TimelineTitle>
1566
- <TimelineDescription>Flat border system by Ma'sum.</TimelineDescription>
1567
- </TimelineItem>
1568
- </Timeline>
1569
-
1570
- <MetricCard label="Expo React Native" value="2026" />
1571
-
1572
- <FloatingActionButton
1573
- icon={({ color, size }) => <Plus color={color} size={size} />}
1574
- label="Create"
1575
- tone="primary"
1576
- />
1577
- ```
1578
-
1579
- Parts and APIs:
1580
-
1581
- - `Textarea`
1582
- - `Select`
1583
- - `Command`
1584
- - `Popover`, `PopoverTrigger`, and `PopoverContent`
1585
- - `Pagination`
1586
- - `Breadcrumb`, `BreadcrumbItem`, `BreadcrumbLink`, `BreadcrumbPage`, and `BreadcrumbSeparator`
1587
- - `Table`, `TableRow`, `TableHead`, and `TableCell`
1588
- - `DataList`, `DataListItem`, `DataListLabel`, and `DataListValue`
1589
- - `Timeline`, `TimelineItem`, `TimelineTitle`, and `TimelineDescription`
1590
- - `MetricCard`
1591
- - `FloatingActionButton`
1592
-
1593
- `TableHead` defaults to a transparent flat header with a subtle divider, so it
1594
- inherits the surrounding card/surface color instead of rendering a mismatched
1595
- filled header background.
1596
-
1597
- ### KeyboardAvoiding
1598
-
1599
- Use `KeyboardAvoiding` for form screens that need keyboard-safe layout. It wraps React Native `KeyboardAvoidingView` and can optionally include a themed `ScrollView`.
1600
-
1601
- ```tsx
1602
- <KeyboardAvoiding scroll p="lg" gap="md">
1603
- <Text variant="title">Expo React Native</Text>
1604
- <Input placeholder="Expo React Native by Ma'sum" />
1605
- <Button>Highlight 2026</Button>
1606
- </KeyboardAvoiding>
1607
-
1608
- <KeyboardAvoiding enabled={false}>
1609
- <Input placeholder="Managed by the app keyboard layer" />
1610
- </KeyboardAvoiding>
1611
- ```
1612
-
1613
- For Android Expo apps, set the app window to resize so the keyboard can move content predictably:
1614
-
1615
- ```json
1616
- {
1617
- "expo": {
1618
- "android": {
1619
- "softwareKeyboardLayoutMode": "resize"
1620
- }
1621
- }
1622
- }
1623
- ```
1624
-
1625
- Useful props:
1626
-
1627
- - `scroll` to render a keyboard-friendly `ScrollView`
1628
- - `bg`, `p`, `px`, `py`, and `gap` for token-based layout
1629
- - `fullHeight` to control whether the wrapper uses `flex: 1`
1630
- - `enabled={false}` to disable keyboard avoiding when the app uses another keyboard library
1631
- - `keyboardVerticalOffset`, `behavior`, and `enabled` from React Native `KeyboardAvoidingView`
1632
- - `scrollViewProps` for `keyboardShouldPersistTaps`, `contentInsetAdjustmentBehavior`, and other `ScrollView` options
1633
-
1634
- ## Common Setup Issues
1635
-
1636
- ### Gesture components do not respond
1637
-
1638
- Make sure `GestureHandlerRootView` wraps the native app root.
1639
-
1640
- ```tsx
1641
- import { GestureHandlerRootView } from "react-native-gesture-handler";
1642
-
1643
- <GestureHandlerRootView style={{ flex: 1 }}>
1644
- <App />
1645
- </GestureHandlerRootView>;
1646
- ```
1647
-
1648
- This affects `Slider`, Gorhom `BottomSheet`, and any future gesture-driven component.
1649
-
1650
- ### Reanimated animations do not run
1651
-
1652
- Verify the app has installed:
1653
-
1654
- ```sh
1655
- bun add react-native-reanimated react-native-worklets
1656
- ```
1657
-
1658
- For manual Babel config, keep the Reanimated plugin last:
1659
-
1660
- ```js
1661
- plugins: ["react-native-reanimated/plugin"];
1662
- ```
1663
-
1664
- Restart Metro after changing Babel/Reanimated setup.
1665
-
1666
- ### Toast does not show
1667
-
1668
- `useToast()` needs `ToastProvider` above the component that calls it.
1669
-
1670
- ```tsx
1671
- <ThemeProvider>
1672
- <ToastProvider>
1673
- <App />
1674
- </ToastProvider>
1675
- </ThemeProvider>
1676
- ```
1677
-
1678
- ### Dark mode resets after reload
1679
-
1680
- Pass a `storage` adapter to `ThemeProvider` and control `colorScheme` in the app if you need app-owned persistence.
1681
-
1682
- ```tsx
1683
- <ThemeProvider
1684
- storage={storage}
1685
- storageKey="rn-ui-color-scheme"
1686
- defaultColorScheme="system"
1687
- >
1688
- <App />
1689
- </ThemeProvider>
1690
- ```
1691
-
1692
- If the app uses Expo Go, choose storage supported by Expo Go, such as `expo-secure-store`.
1693
-
1694
- ### Missing peer dependency errors
1695
-
1696
- Because the package currently exports all components from one root entry, install the peer dependencies listed in the install section even if your first screen only uses a few components. Missing peers usually show up as Metro import errors for packages such as:
1697
-
1698
- - `react-native-reanimated`
1699
- - `react-native-worklets`
1700
- - `react-native-gesture-handler`
1701
- - `react-native-calendars`
1702
- - `@gorhom/bottom-sheet`
1703
-
1704
- ### Expo Go vs development builds
1705
-
1706
- `rn-ui` avoids app-specific native system UI modules. Components should work in Expo Go as long as their peer dependencies are available in the Expo runtime. If an app chooses extra native modules outside this package, such as custom system bar libraries, those modules may require a development build.
1707
-
1708
- ## Publishing Notes
1709
-
1710
- The npm package publishes compiled files from `dist`, `README.md`, and `LICENSE`.
1711
-
1712
- Before publishing:
1713
-
1714
- ```sh
1715
- bun run --filter @masumdev/rn-ui build
1716
- cd packages/rn-ui
1717
- npm pack --dry-run
1718
- npm publish --access public
1719
- ```
1720
-
1721
- The published package exposes:
1722
-
1723
- - CommonJS: `dist/index.js`
1724
- - ESM: `dist/index.mjs`
1725
- - Types: `dist/index.d.ts`
1726
-
1727
- ## Folder Structure
1728
-
1729
- ```txt
1730
- src/
1731
- components/
1732
- Accordion.tsx
1733
- Alert.tsx
1734
- AlertDialog.tsx
1735
- AspectRatio.tsx
1736
- Attachment.tsx
1737
- Avatar.tsx
1738
- BottomSheet.tsx
1739
- Bubble.tsx
1740
- ButtonGroup.tsx
1741
- Calendar.tsx
1742
- Carousel.tsx
1743
- Checkbox.tsx
1744
- Collapsible.tsx
1745
- Combobox.tsx
1746
- ContextMenu.tsx
1747
- Command.tsx
1748
- DataList.tsx
1749
- DropdownMenu.tsx
1750
- Empty.tsx
1751
- FloatingActionButton.tsx
1752
- HoverCard.tsx
1753
- Input.tsx
1754
- InputGroup.tsx
1755
- InputOTP.tsx
1756
- Item.tsx
1757
- KeyboardAvoiding.tsx
1758
- Label.tsx
1759
- MetricCard.tsx
1760
- Pagination.tsx
1761
- Popover.tsx
1762
- FormField.tsx
1763
- Progress.tsx
1764
- RadioGroup.tsx
1765
- Sheet.tsx
1766
- Skeleton.tsx
1767
- Slider.tsx
1768
- Stepper.tsx
1769
- Switch.tsx
1770
- Tabs.tsx
1771
- Table.tsx
1772
- Textarea.tsx
1773
- Timeline.tsx
1774
- Toast.tsx
1775
- Badge.tsx
1776
- Box.tsx
1777
- Button.tsx
1778
- Card.tsx
1779
- Divider.tsx
1780
- IconButton.tsx
1781
- Text.tsx
1782
- index.ts
1783
- theme/
1784
- ThemeProvider.tsx
1785
- createTheme.ts
1786
- index.ts
1787
- tokens.ts
1788
- types.ts
1789
- useTheme.ts
1790
- useThemeStyles.ts
1791
- utils/
1792
- color.ts
1793
- index.ts
1794
- index.ts
1795
- ```
1796
-
1797
- ## Design Notes
1798
-
1799
- - The default visual style is flat: no shadow/elevation by default, stronger borders, semantic surfaces, and consistent rounded corners.
1800
- - Default primary color uses a modern indigo palette: `#4F46E5` in light mode and `#818CF8` in dark mode.
1801
- - Use semantic colors such as `background`, `surface`, `text`, `primary`, `danger`, and `border` instead of hardcoded hex values.
1802
- - Use `spacing`, `radii`, `fonts`, `typography`, and `components` tokens from `useTheme()` or `useThemeStyles()`.
1803
- - Use `components.borderWidth` for default, strong, focus, ring, and hairline border sizing.
1804
- - Use `components.switch` for switch width, height, thumb size, and icon size.
1805
- - Use `components.slider` for slider height, track height, thumb sizing, and hit slop.
1806
- - Keep app-specific storage, fonts, icons, and haptics outside the UI core.
1807
- - Add new components through `components/` and export them from `components/index.ts`.
1808
- - When changing package APIs, tokens, default visuals, persistence behavior, or app integration examples, update this README in the same change.
103
+ ---
1809
104
 
1810
- ## Development Rules
105
+ ## 📄 License
1811
106
 
1812
- See [`RULES.md`](./RULES.md) for file structure rules, code style rules, component conventions, usage patterns, logging rules, and verification checklist.
107
+ MIT © [Ma'sum](https://github.com/masumrpg)