@studio-piot/native-ui 0.2.5 → 0.16.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 (338) hide show
  1. package/README.md +22 -18
  2. package/dist/components/Button/Button.d.ts +20 -4
  3. package/dist/components/Button/Button.d.ts.map +1 -1
  4. package/dist/components/Button/Button.js +34 -21
  5. package/dist/components/Button/Button.js.map +1 -1
  6. package/dist/components/Button/buttonAppearance.d.ts +20 -0
  7. package/dist/components/Button/buttonAppearance.d.ts.map +1 -0
  8. package/dist/components/Button/buttonAppearance.js +28 -0
  9. package/dist/components/Button/buttonAppearance.js.map +1 -0
  10. package/dist/components/Button/buttonThemeRoles.d.ts +6 -0
  11. package/dist/components/Button/buttonThemeRoles.d.ts.map +1 -0
  12. package/dist/components/Button/buttonThemeRoles.js +8 -0
  13. package/dist/components/Button/buttonThemeRoles.js.map +1 -0
  14. package/dist/components/Button/index.d.ts +3 -1
  15. package/dist/components/Button/index.d.ts.map +1 -1
  16. package/dist/components/Button/index.js +4 -1
  17. package/dist/components/Button/index.js.map +1 -1
  18. package/dist/components/Choice/Choice.d.ts +8 -0
  19. package/dist/components/Choice/Choice.d.ts.map +1 -0
  20. package/dist/components/Choice/Choice.js +60 -0
  21. package/dist/components/Choice/Choice.js.map +1 -0
  22. package/dist/components/Choice/choiceLayout.d.ts +7 -0
  23. package/dist/components/Choice/choiceLayout.d.ts.map +1 -0
  24. package/dist/components/Choice/choiceLayout.js +13 -0
  25. package/dist/components/Choice/choiceLayout.js.map +1 -0
  26. package/dist/components/Choice/choiceThemeRoles.d.ts +8 -0
  27. package/dist/components/Choice/choiceThemeRoles.d.ts.map +1 -0
  28. package/dist/components/Choice/choiceThemeRoles.js +10 -0
  29. package/dist/components/Choice/choiceThemeRoles.js.map +1 -0
  30. package/dist/components/Choice/index.d.ts +5 -0
  31. package/dist/components/Choice/index.d.ts.map +1 -0
  32. package/dist/components/Choice/index.js +10 -0
  33. package/dist/components/Choice/index.js.map +1 -0
  34. package/dist/components/Choice/types.d.ts +26 -0
  35. package/dist/components/Choice/types.d.ts.map +1 -0
  36. package/dist/components/Choice/types.js +3 -0
  37. package/dist/components/Choice/types.js.map +1 -0
  38. package/dist/components/ErrorBanner/ErrorBanner.d.ts +1 -1
  39. package/dist/components/ErrorBanner/ErrorBanner.d.ts.map +1 -1
  40. package/dist/components/ErrorBanner/ErrorBanner.js +19 -19
  41. package/dist/components/ErrorBanner/ErrorBanner.js.map +1 -1
  42. package/dist/components/ErrorBanner/errorBannerContext.d.ts +23 -3
  43. package/dist/components/ErrorBanner/errorBannerContext.d.ts.map +1 -1
  44. package/dist/components/ErrorBanner/errorBannerContext.js +9 -5
  45. package/dist/components/ErrorBanner/errorBannerContext.js.map +1 -1
  46. package/dist/components/ErrorBanner/errorBannerLayout.d.ts +18 -0
  47. package/dist/components/ErrorBanner/errorBannerLayout.d.ts.map +1 -0
  48. package/dist/components/ErrorBanner/errorBannerLayout.js +54 -0
  49. package/dist/components/ErrorBanner/errorBannerLayout.js.map +1 -0
  50. package/dist/components/ErrorBanner/icons.d.ts +7 -5
  51. package/dist/components/ErrorBanner/icons.d.ts.map +1 -1
  52. package/dist/components/ErrorBanner/icons.js +8 -4
  53. package/dist/components/ErrorBanner/icons.js.map +1 -1
  54. package/dist/components/ErrorBanner/index.d.ts +1 -1
  55. package/dist/components/ErrorBanner/index.d.ts.map +1 -1
  56. package/dist/components/ErrorBanner/index.js.map +1 -1
  57. package/dist/components/Form/Form.d.ts +9 -1
  58. package/dist/components/Form/Form.d.ts.map +1 -1
  59. package/dist/components/Form/Form.js +56 -78
  60. package/dist/components/Form/Form.js.map +1 -1
  61. package/dist/components/Form/FormCloseButton.d.ts +3 -1
  62. package/dist/components/Form/FormCloseButton.d.ts.map +1 -1
  63. package/dist/components/Form/FormCloseButton.js +5 -4
  64. package/dist/components/Form/FormCloseButton.js.map +1 -1
  65. package/dist/components/Form/FormErrorBanner.d.ts +15 -0
  66. package/dist/components/Form/FormErrorBanner.d.ts.map +1 -0
  67. package/dist/components/Form/FormErrorBanner.js +30 -0
  68. package/dist/components/Form/FormErrorBanner.js.map +1 -0
  69. package/dist/components/Form/FormSubmitFooter.d.ts +17 -0
  70. package/dist/components/Form/FormSubmitFooter.d.ts.map +1 -0
  71. package/dist/components/Form/FormSubmitFooter.js +32 -0
  72. package/dist/components/Form/FormSubmitFooter.js.map +1 -0
  73. package/dist/components/Form/formThemeRoles.d.ts +7 -0
  74. package/dist/components/Form/formThemeRoles.d.ts.map +1 -0
  75. package/dist/components/Form/formThemeRoles.js +9 -0
  76. package/dist/components/Form/formThemeRoles.js.map +1 -0
  77. package/dist/components/Form/index.d.ts +1 -0
  78. package/dist/components/Form/index.d.ts.map +1 -1
  79. package/dist/components/Form/index.js +3 -1
  80. package/dist/components/Form/index.js.map +1 -1
  81. package/dist/components/Form/types.d.ts +14 -10
  82. package/dist/components/Form/types.d.ts.map +1 -1
  83. package/dist/components/FormSheet/FormSheet.d.ts +10 -0
  84. package/dist/components/FormSheet/FormSheet.d.ts.map +1 -0
  85. package/dist/components/FormSheet/FormSheet.js +153 -0
  86. package/dist/components/FormSheet/FormSheet.js.map +1 -0
  87. package/dist/components/FormSheet/formSheetLayout.d.ts +32 -0
  88. package/dist/components/FormSheet/formSheetLayout.d.ts.map +1 -0
  89. package/dist/components/FormSheet/formSheetLayout.js +43 -0
  90. package/dist/components/FormSheet/formSheetLayout.js.map +1 -0
  91. package/dist/components/FormSheet/formSheetThemeRoles.d.ts +8 -0
  92. package/dist/components/FormSheet/formSheetThemeRoles.d.ts.map +1 -0
  93. package/dist/components/FormSheet/formSheetThemeRoles.js +10 -0
  94. package/dist/components/FormSheet/formSheetThemeRoles.js.map +1 -0
  95. package/dist/components/FormSheet/index.d.ts +5 -0
  96. package/dist/components/FormSheet/index.d.ts.map +1 -0
  97. package/dist/components/FormSheet/index.js +10 -0
  98. package/dist/components/FormSheet/index.js.map +1 -0
  99. package/dist/components/FormSheet/types.d.ts +64 -0
  100. package/dist/components/FormSheet/types.d.ts.map +1 -0
  101. package/dist/components/FormSheet/types.js +3 -0
  102. package/dist/components/FormSheet/types.js.map +1 -0
  103. package/dist/components/HeaderButton/HeaderCapsule.d.ts +4 -0
  104. package/dist/components/HeaderButton/HeaderCapsule.d.ts.map +1 -0
  105. package/dist/components/HeaderButton/HeaderCapsule.js +32 -0
  106. package/dist/components/HeaderButton/HeaderCapsule.js.map +1 -0
  107. package/dist/components/HeaderButton/HeaderGroup.d.ts +4 -0
  108. package/dist/components/HeaderButton/HeaderGroup.d.ts.map +1 -0
  109. package/dist/components/HeaderButton/HeaderGroup.js +23 -0
  110. package/dist/components/HeaderButton/HeaderGroup.js.map +1 -0
  111. package/dist/components/HeaderButton/HeaderIcon.d.ts +4 -0
  112. package/dist/components/HeaderButton/HeaderIcon.d.ts.map +1 -0
  113. package/dist/components/HeaderButton/HeaderIcon.js +28 -0
  114. package/dist/components/HeaderButton/HeaderIcon.js.map +1 -0
  115. package/dist/components/HeaderButton/headerButtonLayout.d.ts +21 -0
  116. package/dist/components/HeaderButton/headerButtonLayout.d.ts.map +1 -0
  117. package/dist/components/HeaderButton/headerButtonLayout.js +34 -0
  118. package/dist/components/HeaderButton/headerButtonLayout.js.map +1 -0
  119. package/dist/components/HeaderButton/headerButtonThemeRoles.d.ts +5 -0
  120. package/dist/components/HeaderButton/headerButtonThemeRoles.d.ts.map +1 -0
  121. package/dist/components/HeaderButton/headerButtonThemeRoles.js +7 -0
  122. package/dist/components/HeaderButton/headerButtonThemeRoles.js.map +1 -0
  123. package/dist/components/HeaderButton/index.d.ts +7 -0
  124. package/dist/components/HeaderButton/index.d.ts.map +1 -0
  125. package/dist/components/HeaderButton/index.js +14 -0
  126. package/dist/components/HeaderButton/index.js.map +1 -0
  127. package/dist/components/HeaderButton/types.d.ts +40 -0
  128. package/dist/components/HeaderButton/types.d.ts.map +1 -0
  129. package/dist/components/HeaderButton/types.js +3 -0
  130. package/dist/components/HeaderButton/types.js.map +1 -0
  131. package/dist/components/HeaderWash/HeaderWash.d.ts +10 -0
  132. package/dist/components/HeaderWash/HeaderWash.d.ts.map +1 -0
  133. package/dist/components/HeaderWash/HeaderWash.js +19 -0
  134. package/dist/components/HeaderWash/HeaderWash.js.map +1 -0
  135. package/dist/components/HeaderWash/headerWashGradient.d.ts +8 -0
  136. package/dist/components/HeaderWash/headerWashGradient.d.ts.map +1 -0
  137. package/dist/components/HeaderWash/headerWashGradient.js +21 -0
  138. package/dist/components/HeaderWash/headerWashGradient.js.map +1 -0
  139. package/dist/components/HeaderWash/index.d.ts +2 -0
  140. package/dist/components/HeaderWash/index.d.ts.map +1 -0
  141. package/dist/components/HeaderWash/index.js +6 -0
  142. package/dist/components/HeaderWash/index.js.map +1 -0
  143. package/dist/components/Page/Page.d.ts +13 -0
  144. package/dist/components/Page/Page.d.ts.map +1 -0
  145. package/dist/components/Page/Page.js +49 -0
  146. package/dist/components/Page/Page.js.map +1 -0
  147. package/dist/components/Page/PageBleed.d.ts +9 -0
  148. package/dist/components/Page/PageBleed.d.ts.map +1 -0
  149. package/dist/components/Page/PageBleed.js +12 -0
  150. package/dist/components/Page/PageBleed.js.map +1 -0
  151. package/dist/components/Page/index.d.ts +5 -0
  152. package/dist/components/Page/index.d.ts.map +1 -0
  153. package/dist/components/Page/index.js +10 -0
  154. package/dist/components/Page/index.js.map +1 -0
  155. package/dist/components/Page/pageContext.d.ts +4 -0
  156. package/dist/components/Page/pageContext.d.ts.map +1 -0
  157. package/dist/components/Page/pageContext.js +11 -0
  158. package/dist/components/Page/pageContext.js.map +1 -0
  159. package/dist/components/Page/pageInsets.d.ts +26 -0
  160. package/dist/components/Page/pageInsets.d.ts.map +1 -0
  161. package/dist/components/Page/pageInsets.js +37 -0
  162. package/dist/components/Page/pageInsets.js.map +1 -0
  163. package/dist/components/Page/pageLayout.d.ts +5 -0
  164. package/dist/components/Page/pageLayout.d.ts.map +1 -0
  165. package/dist/components/Page/pageLayout.js +8 -0
  166. package/dist/components/Page/pageLayout.js.map +1 -0
  167. package/dist/components/Page/pageThemeRoles.d.ts +5 -0
  168. package/dist/components/Page/pageThemeRoles.d.ts.map +1 -0
  169. package/dist/components/Page/pageThemeRoles.js +7 -0
  170. package/dist/components/Page/pageThemeRoles.js.map +1 -0
  171. package/dist/components/Page/types.d.ts +22 -0
  172. package/dist/components/Page/types.d.ts.map +1 -0
  173. package/dist/components/Page/types.js +3 -0
  174. package/dist/components/Page/types.js.map +1 -0
  175. package/dist/components/Select/Select.d.ts +1 -1
  176. package/dist/components/Select/Select.d.ts.map +1 -1
  177. package/dist/components/Select/Select.js +8 -9
  178. package/dist/components/Select/Select.js.map +1 -1
  179. package/dist/components/Select/selectThemeRoles.d.ts +2 -0
  180. package/dist/components/Select/selectThemeRoles.d.ts.map +1 -1
  181. package/dist/components/Select/selectThemeRoles.js +2 -0
  182. package/dist/components/Select/selectThemeRoles.js.map +1 -1
  183. package/dist/components/Select/types.d.ts +4 -0
  184. package/dist/components/Select/types.d.ts.map +1 -1
  185. package/dist/components/TabAccessoryButton/TabAccessoryButton.d.ts +8 -0
  186. package/dist/components/TabAccessoryButton/TabAccessoryButton.d.ts.map +1 -0
  187. package/dist/components/TabAccessoryButton/TabAccessoryButton.js +77 -0
  188. package/dist/components/TabAccessoryButton/TabAccessoryButton.js.map +1 -0
  189. package/dist/components/TabAccessoryButton/index.d.ts +5 -0
  190. package/dist/components/TabAccessoryButton/index.d.ts.map +1 -0
  191. package/dist/components/TabAccessoryButton/index.js +11 -0
  192. package/dist/components/TabAccessoryButton/index.js.map +1 -0
  193. package/dist/components/TabAccessoryButton/tabAccessoryLayout.d.ts +27 -0
  194. package/dist/components/TabAccessoryButton/tabAccessoryLayout.d.ts.map +1 -0
  195. package/dist/components/TabAccessoryButton/tabAccessoryLayout.js +38 -0
  196. package/dist/components/TabAccessoryButton/tabAccessoryLayout.js.map +1 -0
  197. package/dist/components/TabAccessoryButton/tabAccessoryThemeRoles.d.ts +14 -0
  198. package/dist/components/TabAccessoryButton/tabAccessoryThemeRoles.d.ts.map +1 -0
  199. package/dist/components/TabAccessoryButton/tabAccessoryThemeRoles.js +19 -0
  200. package/dist/components/TabAccessoryButton/tabAccessoryThemeRoles.js.map +1 -0
  201. package/dist/components/TabAccessoryButton/types.d.ts +27 -0
  202. package/dist/components/TabAccessoryButton/types.d.ts.map +1 -0
  203. package/dist/components/TabAccessoryButton/types.js +3 -0
  204. package/dist/components/TabAccessoryButton/types.js.map +1 -0
  205. package/dist/components/index.d.ts +9 -3
  206. package/dist/components/index.d.ts.map +1 -1
  207. package/dist/components/index.js +30 -1
  208. package/dist/components/index.js.map +1 -1
  209. package/dist/index.d.ts +11 -4
  210. package/dist/index.d.ts.map +1 -1
  211. package/dist/index.js +34 -2
  212. package/dist/index.js.map +1 -1
  213. package/dist/layout/HeaderInsetProbe.d.ts +15 -0
  214. package/dist/layout/HeaderInsetProbe.d.ts.map +1 -0
  215. package/dist/layout/HeaderInsetProbe.js +28 -0
  216. package/dist/layout/HeaderInsetProbe.js.map +1 -0
  217. package/dist/layout/headerInset.d.ts +26 -0
  218. package/dist/layout/headerInset.d.ts.map +1 -0
  219. package/dist/layout/headerInset.js +29 -0
  220. package/dist/layout/headerInset.js.map +1 -0
  221. package/dist/layout/index.d.ts +1 -0
  222. package/dist/layout/index.d.ts.map +1 -1
  223. package/dist/layout/index.js +3 -1
  224. package/dist/layout/index.js.map +1 -1
  225. package/dist/layout/sheet.d.ts +3 -0
  226. package/dist/layout/sheet.d.ts.map +1 -0
  227. package/dist/layout/sheet.js +6 -0
  228. package/dist/layout/sheet.js.map +1 -0
  229. package/dist/theme/ThemeProvider.d.ts +4 -1
  230. package/dist/theme/ThemeProvider.d.ts.map +1 -1
  231. package/dist/theme/ThemeProvider.js +5 -2
  232. package/dist/theme/ThemeProvider.js.map +1 -1
  233. package/dist/theme/index.d.ts +2 -0
  234. package/dist/theme/index.d.ts.map +1 -1
  235. package/dist/theme/index.js +6 -1
  236. package/dist/theme/index.js.map +1 -1
  237. package/dist/theme/resolveThemeSpacing.d.ts +12 -0
  238. package/dist/theme/resolveThemeSpacing.d.ts.map +1 -0
  239. package/dist/theme/resolveThemeSpacing.js +14 -0
  240. package/dist/theme/resolveThemeSpacing.js.map +1 -0
  241. package/dist/theme/types.d.ts +2 -0
  242. package/dist/theme/types.d.ts.map +1 -1
  243. package/dist/theme/useThemeSpacing.d.ts +4 -0
  244. package/dist/theme/useThemeSpacing.d.ts.map +1 -0
  245. package/dist/theme/useThemeSpacing.js +11 -0
  246. package/dist/theme/useThemeSpacing.js.map +1 -0
  247. package/docs/components/button.md +92 -38
  248. package/docs/components/choice.md +88 -0
  249. package/docs/components/error-banner.md +46 -3
  250. package/docs/components/form-sheet.md +140 -0
  251. package/docs/components/form.md +80 -45
  252. package/docs/components/header-button.md +310 -0
  253. package/docs/components/header-wash.md +40 -0
  254. package/docs/components/page.md +183 -0
  255. package/docs/components/select.md +2 -2
  256. package/docs/components/tab-accessory-button.md +146 -0
  257. package/docs/specifications/Liquid Glass header buttons in Expo Router.md +327 -0
  258. package/package.json +1 -1
  259. package/src/components/Button/Button.tsx +82 -38
  260. package/src/components/Button/buttonAppearance.test.ts +44 -0
  261. package/src/components/Button/buttonAppearance.ts +38 -0
  262. package/src/components/Button/buttonThemeRoles.test.ts +10 -0
  263. package/src/components/Button/buttonThemeRoles.ts +6 -0
  264. package/src/components/Button/index.ts +12 -1
  265. package/src/components/Choice/Choice.tsx +109 -0
  266. package/src/components/Choice/choiceLayout.test.ts +14 -0
  267. package/src/components/Choice/choiceLayout.ts +9 -0
  268. package/src/components/Choice/choiceThemeRoles.test.ts +14 -0
  269. package/src/components/Choice/choiceThemeRoles.ts +8 -0
  270. package/src/components/Choice/index.ts +4 -0
  271. package/src/components/Choice/types.ts +26 -0
  272. package/src/components/ErrorBanner/ErrorBanner.tsx +32 -22
  273. package/src/components/ErrorBanner/errorBannerContext.tsx +31 -6
  274. package/src/components/ErrorBanner/errorBannerLayout.test.ts +49 -0
  275. package/src/components/ErrorBanner/errorBannerLayout.ts +59 -0
  276. package/src/components/ErrorBanner/icons.tsx +25 -6
  277. package/src/components/ErrorBanner/index.ts +1 -0
  278. package/src/components/Form/Form.tsx +77 -173
  279. package/src/components/Form/FormCloseButton.tsx +12 -4
  280. package/src/components/Form/FormErrorBanner.tsx +57 -0
  281. package/src/components/Form/FormSubmitFooter.tsx +70 -0
  282. package/src/components/Form/formThemeRoles.test.ts +13 -0
  283. package/src/components/Form/formThemeRoles.ts +7 -0
  284. package/src/components/Form/index.ts +1 -0
  285. package/src/components/Form/types.ts +14 -10
  286. package/src/components/FormSheet/FormSheet.tsx +279 -0
  287. package/src/components/FormSheet/formSheetLayout.test.ts +66 -0
  288. package/src/components/FormSheet/formSheetLayout.ts +55 -0
  289. package/src/components/FormSheet/formSheetThemeRoles.test.ts +14 -0
  290. package/src/components/FormSheet/formSheetThemeRoles.ts +8 -0
  291. package/src/components/FormSheet/index.ts +7 -0
  292. package/src/components/FormSheet/types.ts +66 -0
  293. package/src/components/HeaderButton/HeaderCapsule.tsx +63 -0
  294. package/src/components/HeaderButton/HeaderGroup.tsx +36 -0
  295. package/src/components/HeaderButton/HeaderIcon.tsx +56 -0
  296. package/src/components/HeaderButton/headerButtonLayout.test.ts +47 -0
  297. package/src/components/HeaderButton/headerButtonLayout.ts +36 -0
  298. package/src/components/HeaderButton/headerButtonThemeRoles.test.ts +9 -0
  299. package/src/components/HeaderButton/headerButtonThemeRoles.ts +5 -0
  300. package/src/components/HeaderButton/index.ts +14 -0
  301. package/src/components/HeaderButton/types.ts +40 -0
  302. package/src/components/HeaderWash/HeaderWash.tsx +20 -0
  303. package/src/components/HeaderWash/headerWashGradient.test.ts +22 -0
  304. package/src/components/{Form/withAlpha.ts → HeaderWash/headerWashGradient.ts} +9 -0
  305. package/src/components/HeaderWash/index.ts +1 -0
  306. package/src/components/Page/Page.tsx +80 -0
  307. package/src/components/Page/PageBleed.tsx +14 -0
  308. package/src/components/Page/index.ts +4 -0
  309. package/src/components/Page/pageContext.ts +8 -0
  310. package/src/components/Page/pageInsets.test.ts +73 -0
  311. package/src/components/Page/pageInsets.ts +52 -0
  312. package/src/components/Page/pageThemeRoles.test.ts +9 -0
  313. package/src/components/Page/pageThemeRoles.ts +5 -0
  314. package/src/components/Page/types.ts +26 -0
  315. package/src/components/Select/Select.tsx +11 -4
  316. package/src/components/Select/selectThemeRoles.test.ts +5 -0
  317. package/src/components/Select/selectThemeRoles.ts +2 -0
  318. package/src/components/Select/types.ts +4 -0
  319. package/src/components/TabAccessoryButton/TabAccessoryButton.tsx +150 -0
  320. package/src/components/TabAccessoryButton/index.ts +12 -0
  321. package/src/components/TabAccessoryButton/tabAccessoryLayout.test.ts +42 -0
  322. package/src/components/TabAccessoryButton/tabAccessoryLayout.ts +43 -0
  323. package/src/components/TabAccessoryButton/tabAccessoryThemeRoles.test.ts +28 -0
  324. package/src/components/TabAccessoryButton/tabAccessoryThemeRoles.ts +22 -0
  325. package/src/components/TabAccessoryButton/types.ts +27 -0
  326. package/src/components/index.ts +64 -2
  327. package/src/index.ts +61 -2
  328. package/src/layout/headerInset.test.ts +60 -0
  329. package/src/layout/headerInset.ts +41 -0
  330. package/src/layout/index.ts +1 -0
  331. package/src/layout/sheet.ts +2 -0
  332. package/src/theme/ThemeProvider.tsx +9 -1
  333. package/src/theme/index.ts +6 -0
  334. package/src/theme/resolveThemeSpacing.test.ts +29 -0
  335. package/src/theme/resolveThemeSpacing.ts +21 -0
  336. package/src/theme/types.ts +3 -0
  337. package/src/theme/useThemeSpacing.ts +8 -0
  338. package/src/components/Form/withAlpha.test.ts +0 -13
@@ -1,23 +1,46 @@
1
+ import type { ReactNode } from "react";
1
2
  import {
2
3
  ActivityIndicator,
4
+ Pressable,
3
5
  StyleSheet,
4
6
  Text,
5
- TouchableOpacity,
7
+ View,
6
8
  type StyleProp,
7
9
  type TextStyle,
8
10
  type ViewStyle,
9
11
  } from "react-native";
12
+ import { useResolvedFieldColor } from "../Field/useResolvedFieldColor";
13
+ import {
14
+ buttonColors,
15
+ buttonOpacity,
16
+ type ButtonVariant,
17
+ } from "./buttonAppearance";
10
18
  import { buttonRadiusValue, type ButtonRadius } from "./buttonRadius";
19
+ import { BUTTON_THEME_ROLES } from "./buttonThemeRoles";
20
+
21
+ export const BUTTON_ICON_SIZE = 20;
22
+
23
+ /** Renders the icon in the button's content colour, e.g. an expo-symbols `SymbolView`. */
24
+ export type ButtonIcon = (props: { color: string; size: number }) => ReactNode;
25
+
26
+ export type ButtonIconPosition = "start" | "end" | "only";
11
27
 
12
28
  export type ButtonProps = {
29
+ /** Shown text, and the accessibility label (also when `iconPosition="only"`). */
13
30
  label: string;
14
31
  onPress: () => void;
15
- backgroundColor: string;
16
- labelColor: string;
32
+ /** Filled: fill. Outline: border, label and icon. Defaults to theme role `buttonBackground`. */
33
+ backgroundColor?: string;
34
+ /** Filled: label, icon and spinner. Defaults to theme role `buttonLabel`. */
35
+ labelColor?: string;
17
36
  disabled?: boolean;
18
37
  loading?: boolean;
19
- variant?: "filled" | "outline";
38
+ variant?: ButtonVariant;
20
39
  radius?: ButtonRadius;
40
+ icon?: ButtonIcon;
41
+ /** Default `"start"`. `"only"` hides the label text; `label` stays the accessibility name. */
42
+ iconPosition?: ButtonIconPosition;
43
+ iconSize?: number;
21
44
  style?: StyleProp<ViewStyle>;
22
45
  labelStyle?: StyleProp<TextStyle>;
23
46
  };
@@ -25,58 +48,69 @@ export type ButtonProps = {
25
48
  export function Button({
26
49
  label,
27
50
  onPress,
28
- backgroundColor,
29
- labelColor,
51
+ backgroundColor: backgroundColorProp,
52
+ labelColor: labelColorProp,
30
53
  disabled = false,
31
54
  loading = false,
32
55
  variant = "filled",
33
56
  radius = "xl",
57
+ icon,
58
+ iconPosition = "start",
59
+ iconSize = BUTTON_ICON_SIZE,
34
60
  style,
35
61
  labelStyle,
36
62
  }: ButtonProps) {
37
- const blocked = disabled || loading;
38
- const isOutline = variant === "outline";
39
- const borderRadius = buttonRadiusValue(radius);
63
+ const backgroundColor = useResolvedFieldColor(
64
+ backgroundColorProp,
65
+ BUTTON_THEME_ROLES.backgroundColor,
66
+ );
67
+ const labelColor = useResolvedFieldColor(
68
+ labelColorProp,
69
+ BUTTON_THEME_ROLES.labelColor,
70
+ );
71
+ const colors = buttonColors(variant, backgroundColor, labelColor);
72
+ const iconNode = icon?.({ color: colors.content, size: iconSize });
73
+ const showLabel = !(icon && iconPosition === "only");
40
74
 
41
75
  return (
42
- <TouchableOpacity
76
+ <Pressable
43
77
  accessibilityLabel={label}
44
78
  accessibilityRole="button"
45
- accessibilityState={{ disabled: blocked, busy: loading }}
46
- activeOpacity={0.75}
47
- disabled={blocked}
79
+ accessibilityState={{ disabled: disabled || loading, busy: loading }}
80
+ disabled={disabled || loading}
48
81
  onPress={onPress}
49
- style={[
82
+ style={({ pressed }) => [
50
83
  styles.shell,
51
- { borderRadius },
52
- isOutline
53
- ? {
54
- backgroundColor: "transparent",
55
- borderWidth: 1,
56
- borderColor: backgroundColor,
57
- }
58
- : { backgroundColor },
59
- blocked && styles.blocked,
84
+ {
85
+ borderRadius: buttonRadiusValue(radius),
86
+ backgroundColor: colors.fill,
87
+ opacity: buttonOpacity({ disabled, loading, pressed }),
88
+ },
89
+ colors.border != null && {
90
+ borderWidth: 1,
91
+ borderColor: colors.border,
92
+ },
60
93
  style,
61
94
  ]}
62
95
  >
96
+ {/* Kept in layout while loading so the button keeps its size. */}
97
+ <View style={[styles.content, loading && styles.hidden]}>
98
+ {iconPosition !== "end" ? iconNode : null}
99
+ {showLabel ? (
100
+ <Text style={[styles.label, { color: colors.content }, labelStyle]}>
101
+ {label}
102
+ </Text>
103
+ ) : null}
104
+ {iconPosition === "end" ? iconNode : null}
105
+ </View>
63
106
  {loading ? (
64
107
  <ActivityIndicator
65
- color={isOutline ? backgroundColor : labelColor}
108
+ color={colors.content}
66
109
  size="small"
110
+ style={StyleSheet.absoluteFill}
67
111
  />
68
- ) : (
69
- <Text
70
- style={[
71
- styles.label,
72
- { color: isOutline ? backgroundColor : labelColor },
73
- labelStyle,
74
- ]}
75
- >
76
- {label}
77
- </Text>
78
- )}
79
- </TouchableOpacity>
112
+ ) : null}
113
+ </Pressable>
80
114
  );
81
115
  }
82
116
 
@@ -84,14 +118,24 @@ const styles = StyleSheet.create({
84
118
  shell: {
85
119
  width: "100%",
86
120
  minHeight: 52,
121
+ paddingHorizontal: 20,
122
+ paddingVertical: 12,
123
+ alignItems: "center",
124
+ justifyContent: "center",
125
+ },
126
+ content: {
127
+ flexDirection: "row",
87
128
  alignItems: "center",
88
129
  justifyContent: "center",
130
+ gap: 8,
89
131
  },
90
- blocked: {
91
- opacity: 0.4,
132
+ hidden: {
133
+ opacity: 0,
92
134
  },
93
135
  label: {
136
+ flexShrink: 1,
94
137
  fontSize: 17,
95
138
  fontWeight: "600",
139
+ textAlign: "center",
96
140
  },
97
141
  });
@@ -0,0 +1,44 @@
1
+ import assert from "node:assert/strict";
2
+ import { describe, it } from "node:test";
3
+ import { buttonColors, buttonOpacity } from "./buttonAppearance.ts";
4
+
5
+ describe("buttonColors", () => {
6
+ it("fills with the background and draws content in the label colour", () => {
7
+ assert.deepEqual(buttonColors("filled", "#2563EB", "#FFFFFF"), {
8
+ fill: "#2563EB",
9
+ border: undefined,
10
+ content: "#FFFFFF",
11
+ });
12
+ });
13
+
14
+ it("outlines with the background colour and draws content in it too", () => {
15
+ assert.deepEqual(buttonColors("outline", "#2563EB", "#FFFFFF"), {
16
+ fill: "transparent",
17
+ border: "#2563EB",
18
+ content: "#2563EB",
19
+ });
20
+ });
21
+ });
22
+
23
+ describe("buttonOpacity", () => {
24
+ it("is fully opaque at rest", () => {
25
+ assert.equal(buttonOpacity({ disabled: false, loading: false, pressed: false }), 1);
26
+ });
27
+
28
+ it("dims while pressed", () => {
29
+ assert.equal(buttonOpacity({ disabled: false, loading: false, pressed: true }), 0.75);
30
+ });
31
+
32
+ it("fades when disabled", () => {
33
+ assert.equal(buttonOpacity({ disabled: true, loading: false, pressed: false }), 0.4);
34
+ });
35
+
36
+ it("stays fully opaque while loading so it does not look disabled", () => {
37
+ assert.equal(buttonOpacity({ disabled: false, loading: true, pressed: false }), 1);
38
+ assert.equal(buttonOpacity({ disabled: false, loading: true, pressed: true }), 1);
39
+ });
40
+
41
+ it("fades when disabled and loading", () => {
42
+ assert.equal(buttonOpacity({ disabled: true, loading: true, pressed: false }), 0.4);
43
+ });
44
+ });
@@ -0,0 +1,38 @@
1
+ export type ButtonVariant = "filled" | "outline";
2
+
3
+ /**
4
+ * Fill, border and content (label, icon, spinner) colours for a variant.
5
+ * Outline draws everything in `background`; `label` is unused there.
6
+ */
7
+ export function buttonColors(
8
+ variant: ButtonVariant,
9
+ background: string,
10
+ label: string,
11
+ ): { fill: string; border: string | undefined; content: string } {
12
+ if (variant === "outline") {
13
+ return { fill: "transparent", border: background, content: background };
14
+ }
15
+ return { fill: background, border: undefined, content: label };
16
+ }
17
+
18
+ /**
19
+ * Disabled fades the button. Loading only blocks presses: a spinner on a
20
+ * faded button reads as broken, not busy.
21
+ */
22
+ export function buttonOpacity({
23
+ disabled,
24
+ loading,
25
+ pressed,
26
+ }: {
27
+ disabled: boolean;
28
+ loading: boolean;
29
+ pressed: boolean;
30
+ }): number {
31
+ if (disabled) {
32
+ return 0.4;
33
+ }
34
+ if (pressed && !loading) {
35
+ return 0.75;
36
+ }
37
+ return 1;
38
+ }
@@ -0,0 +1,10 @@
1
+ import assert from "node:assert/strict";
2
+ import { describe, it } from "node:test";
3
+ import { BUTTON_THEME_ROLES } from "./buttonThemeRoles.ts";
4
+
5
+ describe("BUTTON_THEME_ROLES", () => {
6
+ it("maps colour props to the roles Form already uses", () => {
7
+ assert.equal(BUTTON_THEME_ROLES.backgroundColor, "buttonBackground");
8
+ assert.equal(BUTTON_THEME_ROLES.labelColor, "buttonLabel");
9
+ });
10
+ });
@@ -0,0 +1,6 @@
1
+ export const BUTTON_THEME_ROLES = {
2
+ backgroundColor: "buttonBackground",
3
+ labelColor: "buttonLabel",
4
+ } as const;
5
+
6
+ export type ButtonThemeColorProp = keyof typeof BUTTON_THEME_ROLES;
@@ -1,2 +1,13 @@
1
- export { Button, type ButtonProps } from "./Button";
1
+ export {
2
+ Button,
3
+ BUTTON_ICON_SIZE,
4
+ type ButtonIcon,
5
+ type ButtonIconPosition,
6
+ type ButtonProps,
7
+ } from "./Button";
8
+ export type { ButtonVariant } from "./buttonAppearance";
2
9
  export { buttonRadiusValue, type ButtonRadius } from "./buttonRadius";
10
+ export {
11
+ BUTTON_THEME_ROLES,
12
+ type ButtonThemeColorProp,
13
+ } from "./buttonThemeRoles";
@@ -0,0 +1,109 @@
1
+ import { Pressable, StyleSheet, Text, View } from "react-native";
2
+ import { buttonOpacity } from "../Button/buttonAppearance";
3
+ import { buttonRadiusValue } from "../Button/buttonRadius";
4
+ import { useResolvedFieldColor } from "../Field/useResolvedFieldColor";
5
+ import { CHOICE_ICON_SIZE, choiceIconSlot } from "./choiceLayout";
6
+ import { CHOICE_THEME_ROLES } from "./choiceThemeRoles";
7
+ import type { ChoiceProps } from "./types";
8
+
9
+ /**
10
+ * One option in a list of next steps: an icon, a title and an optional
11
+ * description, in a filled row. Tapping it acts straight away, usually to
12
+ * open the next screen. For picking a value, use RadioField or Select.
13
+ */
14
+ export function Choice({
15
+ title,
16
+ description,
17
+ icon,
18
+ onPress,
19
+ disabled = false,
20
+ iconSize = CHOICE_ICON_SIZE,
21
+ radius = "xl",
22
+ backgroundColor: backgroundColorProp,
23
+ titleColor: titleColorProp,
24
+ descriptionColor: descriptionColorProp,
25
+ iconColor: iconColorProp,
26
+ style,
27
+ }: ChoiceProps) {
28
+ const backgroundColor = useResolvedFieldColor(
29
+ backgroundColorProp,
30
+ CHOICE_THEME_ROLES.backgroundColor,
31
+ );
32
+ const titleColor = useResolvedFieldColor(
33
+ titleColorProp,
34
+ CHOICE_THEME_ROLES.titleColor,
35
+ );
36
+ const descriptionColor = useResolvedFieldColor(
37
+ descriptionColorProp,
38
+ CHOICE_THEME_ROLES.descriptionColor,
39
+ );
40
+ const iconColor = useResolvedFieldColor(
41
+ iconColorProp,
42
+ CHOICE_THEME_ROLES.iconColor,
43
+ );
44
+ const slot = choiceIconSlot(iconSize);
45
+
46
+ return (
47
+ // No explicit label: the row groups its text, so VoiceOver reads the
48
+ // title and description together ("Running, Outdoors, with GPS, button").
49
+ <Pressable
50
+ accessibilityRole="button"
51
+ accessibilityState={{ disabled }}
52
+ disabled={disabled}
53
+ onPress={onPress}
54
+ style={({ pressed }) => [
55
+ styles.row,
56
+ {
57
+ backgroundColor,
58
+ borderRadius: buttonRadiusValue(radius),
59
+ opacity: buttonOpacity({ disabled, loading: false, pressed }),
60
+ },
61
+ style,
62
+ ]}
63
+ >
64
+ {icon ? (
65
+ <View
66
+ importantForAccessibility="no-hide-descendants"
67
+ accessibilityElementsHidden
68
+ style={[styles.icon, { width: slot, height: slot }]}
69
+ >
70
+ {icon({ color: iconColor, size: iconSize })}
71
+ </View>
72
+ ) : null}
73
+ <View style={styles.copy}>
74
+ <Text style={[styles.title, { color: titleColor }]}>{title}</Text>
75
+ {description ? (
76
+ <Text style={[styles.description, { color: descriptionColor }]}>
77
+ {description}
78
+ </Text>
79
+ ) : null}
80
+ </View>
81
+ </Pressable>
82
+ );
83
+ }
84
+
85
+ const styles = StyleSheet.create({
86
+ row: {
87
+ alignItems: "center",
88
+ flexDirection: "row",
89
+ gap: 12,
90
+ minHeight: 72,
91
+ paddingHorizontal: 16,
92
+ paddingVertical: 14,
93
+ },
94
+ icon: {
95
+ alignItems: "center",
96
+ justifyContent: "center",
97
+ },
98
+ copy: {
99
+ flex: 1,
100
+ gap: 2,
101
+ },
102
+ title: {
103
+ fontSize: 17,
104
+ fontWeight: "600",
105
+ },
106
+ description: {
107
+ fontSize: 13,
108
+ },
109
+ });
@@ -0,0 +1,14 @@
1
+ import assert from "node:assert/strict";
2
+ import { describe, it } from "node:test";
3
+ import { CHOICE_ICON_SIZE, CHOICE_ICON_SLOT, choiceIconSlot } from "./choiceLayout.ts";
4
+
5
+ describe("choiceIconSlot", () => {
6
+ it("keeps a steady slot so titles line up across rows", () => {
7
+ assert.equal(choiceIconSlot(CHOICE_ICON_SIZE), CHOICE_ICON_SLOT);
8
+ assert.equal(choiceIconSlot(20), CHOICE_ICON_SLOT);
9
+ });
10
+
11
+ it("grows for an icon larger than the slot instead of overflowing", () => {
12
+ assert.equal(choiceIconSlot(40), 40);
13
+ });
14
+ });
@@ -0,0 +1,9 @@
1
+ /** Default icon box, sized for an SF Symbol next to a two-line label. */
2
+ export const CHOICE_ICON_SIZE = 28;
3
+ /** Icon column width, so titles line up across a list of choices. */
4
+ export const CHOICE_ICON_SLOT = 32;
5
+
6
+ /** The icon column: the steady slot, or the icon itself when it is larger. Pure so it can be unit-tested. */
7
+ export function choiceIconSlot(iconSize: number): number {
8
+ return Math.max(CHOICE_ICON_SLOT, iconSize);
9
+ }
@@ -0,0 +1,14 @@
1
+ import assert from "node:assert/strict";
2
+ import { describe, it } from "node:test";
3
+ import { CHOICE_THEME_ROLES } from "./choiceThemeRoles.ts";
4
+
5
+ describe("CHOICE_THEME_ROLES", () => {
6
+ it("maps colour props to choice-prefixed roles, not the app's own names", () => {
7
+ assert.deepEqual(CHOICE_THEME_ROLES, {
8
+ backgroundColor: "choiceBackground",
9
+ titleColor: "choiceTitle",
10
+ descriptionColor: "choiceDescription",
11
+ iconColor: "choiceIcon",
12
+ });
13
+ });
14
+ });
@@ -0,0 +1,8 @@
1
+ export const CHOICE_THEME_ROLES = {
2
+ backgroundColor: "choiceBackground",
3
+ titleColor: "choiceTitle",
4
+ descriptionColor: "choiceDescription",
5
+ iconColor: "choiceIcon",
6
+ } as const;
7
+
8
+ export type ChoiceThemeColorProp = keyof typeof CHOICE_THEME_ROLES;
@@ -0,0 +1,4 @@
1
+ export { Choice } from "./Choice";
2
+ export { CHOICE_ICON_SIZE } from "./choiceLayout";
3
+ export { CHOICE_THEME_ROLES, type ChoiceThemeColorProp } from "./choiceThemeRoles";
4
+ export type { ChoiceProps } from "./types";
@@ -0,0 +1,26 @@
1
+ import type { StyleProp, ViewStyle } from "react-native";
2
+ import type { ButtonIcon } from "../Button";
3
+ import type { ButtonRadius } from "../Button/buttonRadius";
4
+
5
+ export type ChoiceProps = {
6
+ title: string;
7
+ /** Second line under the title. */
8
+ description?: string;
9
+ /** `({ color, size }) => ReactNode`, e.g. an expo-symbols `SymbolView`. */
10
+ icon?: ButtonIcon;
11
+ onPress: () => void;
12
+ disabled?: boolean;
13
+ /** Icon box. Default 28. */
14
+ iconSize?: number;
15
+ /** Default `"xl"` (12), the same scale as `Button`. */
16
+ radius?: ButtonRadius;
17
+ /** Row fill. Defaults to theme role `choiceBackground`. */
18
+ backgroundColor?: string;
19
+ /** Defaults to theme role `choiceTitle`. */
20
+ titleColor?: string;
21
+ /** Defaults to theme role `choiceDescription`. */
22
+ descriptionColor?: string;
23
+ /** Defaults to theme role `choiceIcon`. */
24
+ iconColor?: string;
25
+ style?: StyleProp<ViewStyle>;
26
+ };
@@ -13,10 +13,22 @@ import {
13
13
  import { useSafeAreaInsets } from "react-native-safe-area-context";
14
14
  import { buttonRadiusValue } from "../Button/buttonRadius";
15
15
  import { useResolvedFieldColor } from "../Field/useResolvedFieldColor";
16
- import { screenPaddingHorizontal } from "../../layout/screenPadding";
16
+ import { useThemeSpacing } from "../../theme/useThemeSpacing";
17
17
  import { errorBannerTitle } from "./errorBannerCopy";
18
+ import {
19
+ ERROR_BANNER_ARROW_SIZE,
20
+ ERROR_BANNER_DISC_SIZE,
21
+ ERROR_BANNER_DISMISS_SIZE,
22
+ ERROR_BANNER_FONT_SIZE,
23
+ ERROR_BANNER_HEADER_GAP,
24
+ ERROR_BANNER_LINE_HEIGHT,
25
+ ERROR_BANNER_MEGAPHONE_SIZE,
26
+ ERROR_BANNER_ROW_INSET,
27
+ ERROR_BANNER_ROW_MIN_HEIGHT,
28
+ errorBannerBarStyle,
29
+ } from "./errorBannerLayout";
18
30
  import { ERROR_BANNER_THEME_ROLES } from "./errorBannerThemeRoles";
19
- import { ArrowRight, Megaphone } from "./icons";
31
+ import { ArrowRight, Cross, Megaphone } from "./icons";
20
32
  import type { ErrorBannerProps } from "./types";
21
33
 
22
34
  const BOTTOM_RADIUS = buttonRadiusValue("xl");
@@ -33,13 +45,15 @@ export function ErrorBanner({
33
45
  onDismiss,
34
46
  onHeightChange,
35
47
  safeAreaTop,
36
- paddingHorizontal = screenPaddingHorizontal,
48
+ paddingHorizontal: paddingHorizontalProp,
37
49
  backgroundColor: backgroundColorProp,
38
50
  textColor: textColorProp,
39
51
  secondaryColor: secondaryColorProp,
40
52
  dividerColor: dividerColorProp,
41
53
  accentColor: accentColorProp,
42
54
  }: ErrorBannerProps) {
55
+ const spacing = useThemeSpacing();
56
+ const paddingHorizontal = paddingHorizontalProp ?? spacing.screen;
43
57
  const insets = useSafeAreaInsets();
44
58
  const topInset = safeAreaTop ?? insets.top;
45
59
  const backgroundColor = useResolvedFieldColor(
@@ -108,7 +122,7 @@ export function ErrorBanner({
108
122
 
109
123
  return (
110
124
  <>
111
- {open ? <StatusBar animated barStyle="light-content" /> : null}
125
+ {open ? <StatusBar animated barStyle={errorBannerBarStyle(backgroundColor)} /> : null}
112
126
  <Animated.View
113
127
  accessibilityRole="alert"
114
128
  accessibilityElementsHidden={!open}
@@ -133,7 +147,7 @@ export function ErrorBanner({
133
147
  importantForAccessibility="no-hide-descendants"
134
148
  style={[styles.iconDisc, { backgroundColor: accentColor }]}
135
149
  >
136
- <Megaphone color={backgroundColor} />
150
+ <Megaphone color={backgroundColor} size={ERROR_BANNER_MEGAPHONE_SIZE} />
137
151
  </View>
138
152
  <Text style={[styles.title, { color: textColor }]}>{title}</Text>
139
153
  <Pressable
@@ -142,7 +156,7 @@ export function ErrorBanner({
142
156
  hitSlop={12}
143
157
  onPress={onDismiss}
144
158
  >
145
- <Text style={[styles.dismiss, { color: secondaryColor }]}>✕</Text>
159
+ <Cross color={secondaryColor} size={ERROR_BANNER_DISMISS_SIZE} />
146
160
  </Pressable>
147
161
  </View>
148
162
  <View style={styles.rows}>
@@ -151,7 +165,6 @@ export function ErrorBanner({
151
165
  key={error.field}
152
166
  accessibilityLabel={`${error.short}. Go to field.`}
153
167
  accessibilityRole="button"
154
- hitSlop={{ top: 4, bottom: 4 }}
155
168
  onPress={() => onJump(error.field)}
156
169
  style={({ pressed }) => [
157
170
  styles.row,
@@ -166,7 +179,7 @@ export function ErrorBanner({
166
179
  accessibilityElementsHidden
167
180
  importantForAccessibility="no-hide-descendants"
168
181
  >
169
- <ArrowRight color={secondaryColor} />
182
+ <ArrowRight color={secondaryColor} size={ERROR_BANNER_ARROW_SIZE} />
170
183
  </View>
171
184
  </Pressable>
172
185
  ))}
@@ -184,7 +197,7 @@ const styles = StyleSheet.create({
184
197
  right: 0,
185
198
  zIndex: 100,
186
199
  paddingBottom: 10,
187
- shadowColor: "#22201D",
200
+ shadowColor: "#000000",
188
201
  shadowOpacity: 0.25,
189
202
  shadowRadius: 12,
190
203
  shadowOffset: { width: 0, height: 8 },
@@ -193,32 +206,29 @@ const styles = StyleSheet.create({
193
206
  header: {
194
207
  flexDirection: "row",
195
208
  alignItems: "center",
196
- gap: 10,
209
+ gap: ERROR_BANNER_HEADER_GAP,
197
210
  },
198
211
  iconDisc: {
199
- width: 28,
200
- height: 28,
201
- borderRadius: 14,
212
+ width: ERROR_BANNER_DISC_SIZE,
213
+ height: ERROR_BANNER_DISC_SIZE,
214
+ borderRadius: ERROR_BANNER_DISC_SIZE / 2,
202
215
  alignItems: "center",
203
216
  justifyContent: "center",
204
217
  },
205
218
  title: {
206
219
  flex: 1,
207
- fontSize: 15,
208
- lineHeight: 20,
220
+ fontSize: ERROR_BANNER_FONT_SIZE,
221
+ lineHeight: ERROR_BANNER_LINE_HEIGHT,
209
222
  fontWeight: "600",
210
223
  },
211
- dismiss: {
212
- fontSize: 15,
213
- },
214
224
  rows: {
215
225
  marginTop: 6,
216
226
  },
217
227
  row: {
218
228
  flexDirection: "row",
219
229
  alignItems: "center",
220
- minHeight: 36,
221
- marginLeft: 38,
230
+ minHeight: ERROR_BANNER_ROW_MIN_HEIGHT,
231
+ marginLeft: ERROR_BANNER_ROW_INSET,
222
232
  borderTopWidth: 1,
223
233
  },
224
234
  pressed: {
@@ -226,7 +236,7 @@ const styles = StyleSheet.create({
226
236
  },
227
237
  rowLabel: {
228
238
  flex: 1,
229
- fontSize: 15,
230
- lineHeight: 20,
239
+ fontSize: ERROR_BANNER_FONT_SIZE,
240
+ lineHeight: ERROR_BANNER_LINE_HEIGHT,
231
241
  },
232
242
  });