@thewhileloop/whileui 1.2.3 → 3.0.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 (690) hide show
  1. package/README.md +264 -88
  2. package/dist/blocks/chat/chat.d.ts +3 -4
  3. package/dist/blocks/chat/chat.js +29 -17
  4. package/dist/blocks/chat/index.d.ts +0 -1
  5. package/dist/blocks/chat/index.js +0 -1
  6. package/dist/blocks/commerce/checkout-summary.d.ts +1 -2
  7. package/dist/blocks/commerce/checkout-summary.js +16 -4
  8. package/dist/blocks/commerce/feature-gate.d.ts +1 -2
  9. package/dist/blocks/commerce/feature-gate.js +14 -4
  10. package/dist/blocks/commerce/index.d.ts +0 -1
  11. package/dist/blocks/commerce/index.js +0 -1
  12. package/dist/blocks/commerce/metric-card.d.ts +10 -31
  13. package/dist/blocks/commerce/metric-card.js +7 -3
  14. package/dist/blocks/commerce/plan-toggle.d.ts +1 -2
  15. package/dist/blocks/commerce/plan-toggle.js +11 -9
  16. package/dist/blocks/commerce/pricing-card.d.ts +1 -2
  17. package/dist/blocks/commerce/pricing-card.js +23 -6
  18. package/dist/blocks/commerce/product-card.d.ts +1 -2
  19. package/dist/blocks/commerce/product-card.js +23 -9
  20. package/dist/blocks/commerce/subscription-card.d.ts +1 -2
  21. package/dist/blocks/commerce/subscription-card.js +6 -3
  22. package/dist/blocks/commerce/upgrade-banner.d.ts +1 -2
  23. package/dist/blocks/commerce/upgrade-banner.js +13 -3
  24. package/dist/blocks/commerce/usage-bar.d.ts +1 -2
  25. package/dist/blocks/commerce/usage-bar.js +4 -2
  26. package/dist/blocks/datepicker/date-range-picker-modal.d.ts +2 -3
  27. package/dist/blocks/datepicker/date-range-picker-modal.js +25 -7
  28. package/dist/blocks/datepicker/datepicker-inline.d.ts +1 -2
  29. package/dist/blocks/datepicker/datepicker-inline.js +9 -3
  30. package/dist/blocks/datepicker/datepicker-modal.d.ts +2 -3
  31. package/dist/blocks/datepicker/datepicker-modal.js +44 -18
  32. package/dist/blocks/datepicker/index.d.ts +0 -1
  33. package/dist/blocks/datepicker/index.js +0 -1
  34. package/dist/blocks/datepicker/use-calendar-theme.d.ts +0 -1
  35. package/dist/blocks/datepicker/use-calendar-theme.js +0 -1
  36. package/dist/blocks/layout/action-bar.d.ts +1 -2
  37. package/dist/blocks/layout/action-bar.js +0 -1
  38. package/dist/blocks/layout/app-shell.d.ts +1 -2
  39. package/dist/blocks/layout/app-shell.js +11 -5
  40. package/dist/blocks/layout/confirm-action-sheet.d.ts +1 -2
  41. package/dist/blocks/layout/confirm-action-sheet.js +18 -6
  42. package/dist/blocks/layout/content-skeleton.d.ts +1 -2
  43. package/dist/blocks/layout/content-skeleton.js +22 -9
  44. package/dist/blocks/layout/docked-input.d.ts +11 -0
  45. package/dist/blocks/layout/docked-input.js +27 -0
  46. package/dist/blocks/layout/empty-state.d.ts +1 -2
  47. package/dist/blocks/layout/empty-state.js +10 -5
  48. package/dist/blocks/layout/error-boundary.d.ts +1 -2
  49. package/dist/blocks/layout/error-boundary.js +0 -2
  50. package/dist/blocks/layout/error-state.d.ts +1 -2
  51. package/dist/blocks/layout/error-state.js +0 -2
  52. package/dist/blocks/layout/form-modal-screen.d.ts +1 -2
  53. package/dist/blocks/layout/form-modal-screen.js +24 -21
  54. package/dist/blocks/layout/index.d.ts +2 -2
  55. package/dist/blocks/layout/index.js +2 -2
  56. package/dist/blocks/layout/keyboard-aware-screen.d.ts +14 -0
  57. package/dist/blocks/layout/keyboard-aware-screen.js +12 -0
  58. package/dist/blocks/layout/loading-screen.d.ts +1 -2
  59. package/dist/blocks/layout/loading-screen.js +6 -8
  60. package/dist/blocks/layout/page-skeleton.d.ts +1 -2
  61. package/dist/blocks/layout/page-skeleton.js +38 -20
  62. package/dist/blocks/layout/pull-to-refresh-scroll-view.d.ts +8 -4
  63. package/dist/blocks/layout/pull-to-refresh-scroll-view.js +17 -4
  64. package/dist/blocks/layout/screen-skeleton.d.ts +1 -2
  65. package/dist/blocks/layout/screen-skeleton.js +0 -1
  66. package/dist/blocks/layout/sheet.d.ts +9 -9
  67. package/dist/blocks/layout/sheet.js +51 -21
  68. package/dist/blocks/layout/smart-input.d.ts +9 -3
  69. package/dist/blocks/layout/smart-input.js +136 -9
  70. package/dist/blocks/lists/index.d.ts +0 -2
  71. package/dist/blocks/lists/index.js +0 -2
  72. package/dist/blocks/lists/list-item.d.ts +1 -2
  73. package/dist/blocks/lists/list-item.js +20 -6
  74. package/dist/blocks/lists/notification-item.d.ts +1 -2
  75. package/dist/blocks/lists/notification-item.js +19 -6
  76. package/dist/blocks/lists/timeline-feed.d.ts +1 -2
  77. package/dist/blocks/lists/timeline-feed.js +4 -2
  78. package/dist/blocks/media/index.d.ts +0 -1
  79. package/dist/blocks/media/index.js +0 -1
  80. package/dist/blocks/media/smart-image.d.ts +39 -99
  81. package/dist/blocks/media/smart-image.js +24 -8
  82. package/dist/blocks/navigation/bottom-nav.d.ts +1 -2
  83. package/dist/blocks/navigation/bottom-nav.js +7 -4
  84. package/dist/blocks/navigation/drawer-menu.d.ts +1 -2
  85. package/dist/blocks/navigation/drawer-menu.js +117 -64
  86. package/dist/blocks/navigation/floating-bottom-nav.d.ts +1 -2
  87. package/dist/blocks/navigation/floating-bottom-nav.js +14 -5
  88. package/dist/blocks/navigation/header.d.ts +2 -3
  89. package/dist/blocks/navigation/header.js +13 -5
  90. package/dist/blocks/navigation/index.d.ts +0 -2
  91. package/dist/blocks/navigation/index.js +0 -2
  92. package/dist/blocks/navigation/tab-bar.d.ts +1 -2
  93. package/dist/blocks/navigation/tab-bar.js +22 -10
  94. package/dist/blocks/splash/index.d.ts +0 -1
  95. package/dist/blocks/splash/index.js +0 -1
  96. package/dist/blocks/splash/splash-screen.d.ts +3 -4
  97. package/dist/blocks/splash/splash-screen.js +15 -11
  98. package/dist/components/accordion/accordion.d.ts +4 -5
  99. package/dist/components/accordion/accordion.js +6 -7
  100. package/dist/components/accordion/index.d.ts +0 -1
  101. package/dist/components/accordion/index.js +0 -1
  102. package/dist/components/alert/alert.d.ts +23 -56
  103. package/dist/components/alert/alert.js +20 -9
  104. package/dist/components/alert/index.d.ts +0 -1
  105. package/dist/components/alert/index.js +0 -1
  106. package/dist/components/alert-dialog/alert-dialog.d.ts +9 -10
  107. package/dist/components/alert-dialog/alert-dialog.js +175 -54
  108. package/dist/components/alert-dialog/index.d.ts +0 -1
  109. package/dist/components/alert-dialog/index.js +0 -1
  110. package/dist/components/aspect-ratio/aspect-ratio.d.ts +1 -2
  111. package/dist/components/aspect-ratio/aspect-ratio.js +0 -3
  112. package/dist/components/aspect-ratio/index.d.ts +0 -1
  113. package/dist/components/aspect-ratio/index.js +0 -1
  114. package/dist/components/avatar/avatar.d.ts +20 -48
  115. package/dist/components/avatar/avatar.js +8 -9
  116. package/dist/components/avatar/index.d.ts +0 -1
  117. package/dist/components/avatar/index.js +0 -1
  118. package/dist/components/badge/badge.d.ts +86 -215
  119. package/dist/components/badge/badge.js +21 -9
  120. package/dist/components/badge/index.d.ts +0 -1
  121. package/dist/components/badge/index.js +0 -1
  122. package/dist/components/button/button.d.ts +75 -193
  123. package/dist/components/button/button.js +62 -33
  124. package/dist/components/button/index.d.ts +0 -1
  125. package/dist/components/button/index.js +0 -1
  126. package/dist/components/card/card.d.ts +32 -74
  127. package/dist/components/card/card.js +29 -15
  128. package/dist/components/card/index.d.ts +0 -1
  129. package/dist/components/card/index.js +0 -1
  130. package/dist/components/checkbox/checkbox.d.ts +1 -2
  131. package/dist/components/checkbox/checkbox.js +15 -2
  132. package/dist/components/checkbox/index.d.ts +0 -1
  133. package/dist/components/checkbox/index.js +0 -1
  134. package/dist/components/collapsible/collapsible.d.ts +4 -4
  135. package/dist/components/collapsible/collapsible.js +8 -11
  136. package/dist/components/collapsible/index.d.ts +0 -1
  137. package/dist/components/collapsible/index.js +0 -1
  138. package/dist/components/container/container.d.ts +74 -0
  139. package/dist/components/container/container.js +43 -0
  140. package/dist/components/container/index.d.ts +1 -0
  141. package/dist/components/container/index.js +1 -0
  142. package/dist/components/context-menu/context-menu.d.ts +6 -7
  143. package/dist/components/context-menu/context-menu.js +42 -12
  144. package/dist/components/context-menu/index.d.ts +0 -1
  145. package/dist/components/context-menu/index.js +0 -1
  146. package/dist/components/data-row/data-row.d.ts +18 -39
  147. package/dist/components/data-row/data-row.js +36 -18
  148. package/dist/components/data-row/index.d.ts +0 -1
  149. package/dist/components/data-row/index.js +0 -1
  150. package/dist/components/dialog/dialog.d.ts +8 -9
  151. package/dist/components/dialog/dialog.js +48 -24
  152. package/dist/components/dialog/index.d.ts +0 -1
  153. package/dist/components/dialog/index.js +0 -1
  154. package/dist/components/dropdown-menu/dropdown-menu.d.ts +6 -7
  155. package/dist/components/dropdown-menu/dropdown-menu.js +45 -11
  156. package/dist/components/dropdown-menu/index.d.ts +0 -1
  157. package/dist/components/dropdown-menu/index.js +0 -1
  158. package/dist/components/form-field/form-field.d.ts +31 -88
  159. package/dist/components/form-field/form-field.js +27 -14
  160. package/dist/components/form-field/index.d.ts +0 -1
  161. package/dist/components/form-field/index.js +0 -1
  162. package/dist/components/hover-card/hover-card.d.ts +4 -4
  163. package/dist/components/hover-card/hover-card.js +12 -3
  164. package/dist/components/hover-card/index.d.ts +0 -1
  165. package/dist/components/hover-card/index.js +0 -1
  166. package/dist/components/input/index.d.ts +0 -1
  167. package/dist/components/input/index.js +0 -1
  168. package/dist/components/input/input.d.ts +12 -32
  169. package/dist/components/input/input.js +18 -3
  170. package/dist/components/label/index.d.ts +0 -1
  171. package/dist/components/label/index.js +0 -1
  172. package/dist/components/label/label.d.ts +3 -4
  173. package/dist/components/label/label.js +0 -1
  174. package/dist/components/labeled-field/index.d.ts +0 -1
  175. package/dist/components/labeled-field/index.js +0 -1
  176. package/dist/components/labeled-field/labeled-field.d.ts +4 -4
  177. package/dist/components/labeled-field/labeled-field.js +10 -2
  178. package/dist/components/menubar/index.d.ts +0 -1
  179. package/dist/components/menubar/index.js +0 -1
  180. package/dist/components/menubar/menubar.d.ts +7 -8
  181. package/dist/components/menubar/menubar.js +48 -15
  182. package/dist/components/numeric-input/index.d.ts +0 -1
  183. package/dist/components/numeric-input/index.js +0 -1
  184. package/dist/components/numeric-input/numeric-input.d.ts +29 -83
  185. package/dist/components/numeric-input/numeric-input.js +93 -73
  186. package/dist/components/otp-input/index.d.ts +0 -1
  187. package/dist/components/otp-input/index.js +0 -1
  188. package/dist/components/otp-input/otp-input.d.ts +22 -67
  189. package/dist/components/otp-input/otp-input.js +13 -9
  190. package/dist/components/popover/index.d.ts +0 -1
  191. package/dist/components/popover/index.js +0 -1
  192. package/dist/components/popover/popover.d.ts +8 -5
  193. package/dist/components/popover/popover.js +21 -4
  194. package/dist/components/pressable/index.d.ts +0 -1
  195. package/dist/components/pressable/index.js +0 -1
  196. package/dist/components/pressable/pressable.d.ts +10 -4
  197. package/dist/components/pressable/pressable.js +47 -4
  198. package/dist/components/progress/index.d.ts +0 -1
  199. package/dist/components/progress/index.js +0 -1
  200. package/dist/components/progress/progress.d.ts +15 -40
  201. package/dist/components/progress/progress.js +5 -2
  202. package/dist/components/radio-group/index.d.ts +0 -1
  203. package/dist/components/radio-group/index.js +0 -1
  204. package/dist/components/radio-group/radio-group.d.ts +2 -3
  205. package/dist/components/radio-group/radio-group.js +16 -7
  206. package/dist/components/row/index.d.ts +0 -1
  207. package/dist/components/row/index.js +0 -1
  208. package/dist/components/row/row.d.ts +63 -164
  209. package/dist/components/row/row.js +0 -1
  210. package/dist/components/segmented-control/index.d.ts +0 -1
  211. package/dist/components/segmented-control/index.js +0 -1
  212. package/dist/components/segmented-control/segmented-control.d.ts +72 -245
  213. package/dist/components/segmented-control/segmented-control.js +57 -24
  214. package/dist/components/select/index.d.ts +0 -1
  215. package/dist/components/select/index.js +0 -1
  216. package/dist/components/select/select.d.ts +23 -27
  217. package/dist/components/select/select.js +54 -12
  218. package/dist/components/separator/index.d.ts +0 -1
  219. package/dist/components/separator/index.js +0 -1
  220. package/dist/components/separator/separator.d.ts +3 -4
  221. package/dist/components/separator/separator.js +0 -1
  222. package/dist/components/skeleton/index.d.ts +0 -1
  223. package/dist/components/skeleton/index.js +0 -1
  224. package/dist/components/skeleton/skeleton.d.ts +10 -31
  225. package/dist/components/skeleton/skeleton.js +7 -8
  226. package/dist/components/spinner/index.d.ts +0 -1
  227. package/dist/components/spinner/index.js +0 -1
  228. package/dist/components/spinner/spinner.d.ts +13 -38
  229. package/dist/components/spinner/spinner.js +4 -2
  230. package/dist/components/stack/index.d.ts +0 -1
  231. package/dist/components/stack/index.js +0 -1
  232. package/dist/components/stack/stack.d.ts +63 -164
  233. package/dist/components/stack/stack.js +0 -1
  234. package/dist/components/switch/index.d.ts +0 -1
  235. package/dist/components/switch/index.js +0 -1
  236. package/dist/components/switch/switch.d.ts +1 -2
  237. package/dist/components/switch/switch.js +21 -2
  238. package/dist/components/tabs/index.d.ts +0 -1
  239. package/dist/components/tabs/index.js +0 -1
  240. package/dist/components/tabs/tabs.d.ts +13 -34
  241. package/dist/components/tabs/tabs.js +42 -12
  242. package/dist/components/text/index.d.ts +0 -1
  243. package/dist/components/text/index.js +0 -1
  244. package/dist/components/text/text.d.ts +51 -132
  245. package/dist/components/text/text.js +0 -1
  246. package/dist/components/textarea/index.d.ts +0 -1
  247. package/dist/components/textarea/index.js +0 -1
  248. package/dist/components/textarea/textarea.d.ts +15 -40
  249. package/dist/components/textarea/textarea.js +17 -9
  250. package/dist/components/toast/index.d.ts +0 -1
  251. package/dist/components/toast/index.js +0 -1
  252. package/dist/components/toast/toast.d.ts +15 -40
  253. package/dist/components/toast/toast.js +40 -24
  254. package/dist/components/toggle/index.d.ts +0 -1
  255. package/dist/components/toggle/index.js +0 -1
  256. package/dist/components/toggle/toggle.d.ts +44 -141
  257. package/dist/components/toggle/toggle.js +32 -16
  258. package/dist/components/toggle-group/index.d.ts +0 -1
  259. package/dist/components/toggle-group/index.js +0 -1
  260. package/dist/components/toggle-group/toggle-group.d.ts +45 -142
  261. package/dist/components/toggle-group/toggle-group.js +36 -19
  262. package/dist/components/tooltip/index.d.ts +0 -1
  263. package/dist/components/tooltip/index.js +0 -1
  264. package/dist/components/tooltip/tooltip.d.ts +4 -4
  265. package/dist/components/tooltip/tooltip.js +20 -3
  266. package/dist/components/view/index.d.ts +0 -1
  267. package/dist/components/view/index.js +0 -1
  268. package/dist/components/view/view.d.ts +3 -4
  269. package/dist/components/view/view.js +0 -1
  270. package/dist/index.d.ts +9 -3
  271. package/dist/index.js +9 -7
  272. package/dist/lib/cn.d.ts +0 -1
  273. package/dist/lib/cn.js +0 -1
  274. package/dist/lib/compose-event-handlers.d.ts +15 -0
  275. package/dist/lib/compose-event-handlers.js +20 -0
  276. package/dist/lib/focus-ring.d.ts +25 -0
  277. package/dist/lib/focus-ring.js +25 -0
  278. package/dist/lib/font-context.d.ts +1 -1
  279. package/dist/lib/font-context.js +6 -4
  280. package/dist/lib/frosted-surface.d.ts +0 -1
  281. package/dist/lib/frosted-surface.js +31 -6
  282. package/dist/lib/interaction-tokens.d.ts +12 -1
  283. package/dist/lib/interaction-tokens.js +27 -13
  284. package/dist/lib/motion-policy.d.ts +25 -0
  285. package/dist/lib/motion-policy.js +97 -0
  286. package/dist/lib/overlay-insets.d.ts +17 -0
  287. package/dist/lib/overlay-insets.js +23 -0
  288. package/dist/lib/portal.d.ts +0 -1
  289. package/dist/lib/portal.js +0 -1
  290. package/dist/lib/react-native-classname.d.ts +0 -1
  291. package/dist/lib/react-native-classname.js +0 -1
  292. package/dist/lib/recipes.d.ts +30 -0
  293. package/dist/lib/recipes.js +138 -0
  294. package/dist/lib/ref-types.d.ts +3 -0
  295. package/dist/lib/ref-types.js +1 -0
  296. package/dist/lib/tap-only.d.ts +11 -0
  297. package/dist/lib/tap-only.js +24 -0
  298. package/dist/lib/theme-bridge.d.ts +4 -3
  299. package/dist/lib/theme-bridge.js +24 -12
  300. package/dist/lib/theme-colors.d.ts +2 -46
  301. package/dist/lib/theme-colors.js +25 -226
  302. package/dist/lib/theme-contract.d.ts +78 -0
  303. package/dist/lib/theme-contract.js +481 -0
  304. package/dist/lib/theme-derive.d.ts +4 -0
  305. package/dist/lib/theme-derive.js +80 -0
  306. package/dist/lib/theme-presets.d.ts +31 -0
  307. package/dist/lib/theme-presets.js +221 -0
  308. package/dist/lib/tv.d.ts +0 -1
  309. package/dist/lib/tv.js +0 -1
  310. package/dist/lib/visual-token-contract.d.ts +110 -0
  311. package/dist/lib/visual-token-contract.js +583 -0
  312. package/dist/lib/visual-tokens.d.ts +2 -38
  313. package/dist/lib/visual-tokens.js +22 -75
  314. package/dist/tokens.d.ts +4 -0
  315. package/dist/tokens.js +6 -0
  316. package/dist/vite.d.ts +0 -1
  317. package/dist/vite.js +0 -1
  318. package/package.json +40 -29
  319. package/dist/blocks/auth/forgot-password-form.d.ts +0 -10
  320. package/dist/blocks/auth/forgot-password-form.d.ts.map +0 -1
  321. package/dist/blocks/auth/forgot-password-form.js +0 -17
  322. package/dist/blocks/auth/forgot-password-form.js.map +0 -1
  323. package/dist/blocks/auth/index.d.ts +0 -8
  324. package/dist/blocks/auth/index.d.ts.map +0 -1
  325. package/dist/blocks/auth/index.js +0 -8
  326. package/dist/blocks/auth/index.js.map +0 -1
  327. package/dist/blocks/auth/reset-password-form.d.ts +0 -9
  328. package/dist/blocks/auth/reset-password-form.d.ts.map +0 -1
  329. package/dist/blocks/auth/reset-password-form.js +0 -16
  330. package/dist/blocks/auth/reset-password-form.js.map +0 -1
  331. package/dist/blocks/auth/sign-in-form.d.ts +0 -17
  332. package/dist/blocks/auth/sign-in-form.d.ts.map +0 -1
  333. package/dist/blocks/auth/sign-in-form.js +0 -19
  334. package/dist/blocks/auth/sign-in-form.js.map +0 -1
  335. package/dist/blocks/auth/sign-up-form.d.ts +0 -17
  336. package/dist/blocks/auth/sign-up-form.d.ts.map +0 -1
  337. package/dist/blocks/auth/sign-up-form.js +0 -21
  338. package/dist/blocks/auth/sign-up-form.js.map +0 -1
  339. package/dist/blocks/auth/social-connections.d.ts +0 -10
  340. package/dist/blocks/auth/social-connections.d.ts.map +0 -1
  341. package/dist/blocks/auth/social-connections.js +0 -8
  342. package/dist/blocks/auth/social-connections.js.map +0 -1
  343. package/dist/blocks/auth/user-menu.d.ts +0 -12
  344. package/dist/blocks/auth/user-menu.d.ts.map +0 -1
  345. package/dist/blocks/auth/user-menu.js +0 -10
  346. package/dist/blocks/auth/user-menu.js.map +0 -1
  347. package/dist/blocks/auth/verify-email-form.d.ts +0 -10
  348. package/dist/blocks/auth/verify-email-form.d.ts.map +0 -1
  349. package/dist/blocks/auth/verify-email-form.js +0 -17
  350. package/dist/blocks/auth/verify-email-form.js.map +0 -1
  351. package/dist/blocks/chat/chat.d.ts.map +0 -1
  352. package/dist/blocks/chat/chat.js.map +0 -1
  353. package/dist/blocks/chat/index.d.ts.map +0 -1
  354. package/dist/blocks/chat/index.js.map +0 -1
  355. package/dist/blocks/commerce/checkout-summary.d.ts.map +0 -1
  356. package/dist/blocks/commerce/checkout-summary.js.map +0 -1
  357. package/dist/blocks/commerce/feature-gate.d.ts.map +0 -1
  358. package/dist/blocks/commerce/feature-gate.js.map +0 -1
  359. package/dist/blocks/commerce/index.d.ts.map +0 -1
  360. package/dist/blocks/commerce/index.js.map +0 -1
  361. package/dist/blocks/commerce/metric-card.d.ts.map +0 -1
  362. package/dist/blocks/commerce/metric-card.js.map +0 -1
  363. package/dist/blocks/commerce/plan-toggle.d.ts.map +0 -1
  364. package/dist/blocks/commerce/plan-toggle.js.map +0 -1
  365. package/dist/blocks/commerce/pricing-card.d.ts.map +0 -1
  366. package/dist/blocks/commerce/pricing-card.js.map +0 -1
  367. package/dist/blocks/commerce/product-card.d.ts.map +0 -1
  368. package/dist/blocks/commerce/product-card.js.map +0 -1
  369. package/dist/blocks/commerce/subscription-card.d.ts.map +0 -1
  370. package/dist/blocks/commerce/subscription-card.js.map +0 -1
  371. package/dist/blocks/commerce/upgrade-banner.d.ts.map +0 -1
  372. package/dist/blocks/commerce/upgrade-banner.js.map +0 -1
  373. package/dist/blocks/commerce/usage-bar.d.ts.map +0 -1
  374. package/dist/blocks/commerce/usage-bar.js.map +0 -1
  375. package/dist/blocks/datepicker/date-range-picker-modal.d.ts.map +0 -1
  376. package/dist/blocks/datepicker/date-range-picker-modal.js.map +0 -1
  377. package/dist/blocks/datepicker/datepicker-inline.d.ts.map +0 -1
  378. package/dist/blocks/datepicker/datepicker-inline.js.map +0 -1
  379. package/dist/blocks/datepicker/datepicker-modal.d.ts.map +0 -1
  380. package/dist/blocks/datepicker/datepicker-modal.js.map +0 -1
  381. package/dist/blocks/datepicker/index.d.ts.map +0 -1
  382. package/dist/blocks/datepicker/index.js.map +0 -1
  383. package/dist/blocks/datepicker/use-calendar-theme.d.ts.map +0 -1
  384. package/dist/blocks/datepicker/use-calendar-theme.js.map +0 -1
  385. package/dist/blocks/layout/action-bar.d.ts.map +0 -1
  386. package/dist/blocks/layout/action-bar.js.map +0 -1
  387. package/dist/blocks/layout/app-shell.d.ts.map +0 -1
  388. package/dist/blocks/layout/app-shell.js.map +0 -1
  389. package/dist/blocks/layout/confirm-action-sheet.d.ts.map +0 -1
  390. package/dist/blocks/layout/confirm-action-sheet.js.map +0 -1
  391. package/dist/blocks/layout/content-skeleton.d.ts.map +0 -1
  392. package/dist/blocks/layout/content-skeleton.js.map +0 -1
  393. package/dist/blocks/layout/empty-state.d.ts.map +0 -1
  394. package/dist/blocks/layout/empty-state.js.map +0 -1
  395. package/dist/blocks/layout/error-boundary.d.ts.map +0 -1
  396. package/dist/blocks/layout/error-boundary.js.map +0 -1
  397. package/dist/blocks/layout/error-state.d.ts.map +0 -1
  398. package/dist/blocks/layout/error-state.js.map +0 -1
  399. package/dist/blocks/layout/form-modal-screen.d.ts.map +0 -1
  400. package/dist/blocks/layout/form-modal-screen.js.map +0 -1
  401. package/dist/blocks/layout/index.d.ts.map +0 -1
  402. package/dist/blocks/layout/index.js.map +0 -1
  403. package/dist/blocks/layout/loading-screen.d.ts.map +0 -1
  404. package/dist/blocks/layout/loading-screen.js.map +0 -1
  405. package/dist/blocks/layout/onboarding-screen.d.ts +0 -19
  406. package/dist/blocks/layout/onboarding-screen.d.ts.map +0 -1
  407. package/dist/blocks/layout/onboarding-screen.js +0 -35
  408. package/dist/blocks/layout/onboarding-screen.js.map +0 -1
  409. package/dist/blocks/layout/page-skeleton.d.ts.map +0 -1
  410. package/dist/blocks/layout/page-skeleton.js.map +0 -1
  411. package/dist/blocks/layout/pull-to-refresh-scroll-view.d.ts.map +0 -1
  412. package/dist/blocks/layout/pull-to-refresh-scroll-view.js.map +0 -1
  413. package/dist/blocks/layout/screen-skeleton.d.ts.map +0 -1
  414. package/dist/blocks/layout/screen-skeleton.js.map +0 -1
  415. package/dist/blocks/layout/sheet.d.ts.map +0 -1
  416. package/dist/blocks/layout/sheet.js.map +0 -1
  417. package/dist/blocks/layout/smart-image.d.ts +0 -9
  418. package/dist/blocks/layout/smart-image.d.ts.map +0 -1
  419. package/dist/blocks/layout/smart-image.js +0 -23
  420. package/dist/blocks/layout/smart-image.js.map +0 -1
  421. package/dist/blocks/layout/smart-input.d.ts.map +0 -1
  422. package/dist/blocks/layout/smart-input.js.map +0 -1
  423. package/dist/blocks/lists/index.d.ts.map +0 -1
  424. package/dist/blocks/lists/index.js.map +0 -1
  425. package/dist/blocks/lists/list-item.d.ts.map +0 -1
  426. package/dist/blocks/lists/list-item.js.map +0 -1
  427. package/dist/blocks/lists/notification-item.d.ts.map +0 -1
  428. package/dist/blocks/lists/notification-item.js.map +0 -1
  429. package/dist/blocks/lists/swipeable-item.d.ts +0 -17
  430. package/dist/blocks/lists/swipeable-item.d.ts.map +0 -1
  431. package/dist/blocks/lists/swipeable-item.js +0 -65
  432. package/dist/blocks/lists/swipeable-item.js.map +0 -1
  433. package/dist/blocks/lists/timeline-feed.d.ts.map +0 -1
  434. package/dist/blocks/lists/timeline-feed.js.map +0 -1
  435. package/dist/blocks/media/index.d.ts.map +0 -1
  436. package/dist/blocks/media/index.js.map +0 -1
  437. package/dist/blocks/media/smart-image.d.ts.map +0 -1
  438. package/dist/blocks/media/smart-image.js.map +0 -1
  439. package/dist/blocks/navigation/bottom-nav.d.ts.map +0 -1
  440. package/dist/blocks/navigation/bottom-nav.js.map +0 -1
  441. package/dist/blocks/navigation/drawer-menu.d.ts.map +0 -1
  442. package/dist/blocks/navigation/drawer-menu.js.map +0 -1
  443. package/dist/blocks/navigation/floating-bottom-nav.d.ts.map +0 -1
  444. package/dist/blocks/navigation/floating-bottom-nav.js.map +0 -1
  445. package/dist/blocks/navigation/header.d.ts.map +0 -1
  446. package/dist/blocks/navigation/header.js.map +0 -1
  447. package/dist/blocks/navigation/index.d.ts.map +0 -1
  448. package/dist/blocks/navigation/index.js.map +0 -1
  449. package/dist/blocks/navigation/navigation-sidebar.d.ts +0 -25
  450. package/dist/blocks/navigation/navigation-sidebar.d.ts.map +0 -1
  451. package/dist/blocks/navigation/navigation-sidebar.js +0 -18
  452. package/dist/blocks/navigation/navigation-sidebar.js.map +0 -1
  453. package/dist/blocks/navigation/tab-bar.d.ts.map +0 -1
  454. package/dist/blocks/navigation/tab-bar.js.map +0 -1
  455. package/dist/blocks/profile/account-card.d.ts +0 -11
  456. package/dist/blocks/profile/account-card.d.ts.map +0 -1
  457. package/dist/blocks/profile/account-card.js +0 -10
  458. package/dist/blocks/profile/account-card.js.map +0 -1
  459. package/dist/blocks/profile/index.d.ts +0 -5
  460. package/dist/blocks/profile/index.d.ts.map +0 -1
  461. package/dist/blocks/profile/index.js +0 -5
  462. package/dist/blocks/profile/index.js.map +0 -1
  463. package/dist/blocks/profile/profile-header.d.ts +0 -27
  464. package/dist/blocks/profile/profile-header.d.ts.map +0 -1
  465. package/dist/blocks/profile/profile-header.js +0 -11
  466. package/dist/blocks/profile/profile-header.js.map +0 -1
  467. package/dist/blocks/profile/settings-item.d.ts +0 -15
  468. package/dist/blocks/profile/settings-item.d.ts.map +0 -1
  469. package/dist/blocks/profile/settings-item.js +0 -11
  470. package/dist/blocks/profile/settings-item.js.map +0 -1
  471. package/dist/blocks/profile/settings-section.d.ts +0 -7
  472. package/dist/blocks/profile/settings-section.d.ts.map +0 -1
  473. package/dist/blocks/profile/settings-section.js +0 -9
  474. package/dist/blocks/profile/settings-section.js.map +0 -1
  475. package/dist/blocks/splash/index.d.ts.map +0 -1
  476. package/dist/blocks/splash/index.js.map +0 -1
  477. package/dist/blocks/splash/splash-screen.d.ts.map +0 -1
  478. package/dist/blocks/splash/splash-screen.js.map +0 -1
  479. package/dist/components/accordion/accordion.d.ts.map +0 -1
  480. package/dist/components/accordion/accordion.js.map +0 -1
  481. package/dist/components/accordion/index.d.ts.map +0 -1
  482. package/dist/components/accordion/index.js.map +0 -1
  483. package/dist/components/alert/alert.d.ts.map +0 -1
  484. package/dist/components/alert/alert.js.map +0 -1
  485. package/dist/components/alert/index.d.ts.map +0 -1
  486. package/dist/components/alert/index.js.map +0 -1
  487. package/dist/components/alert-dialog/alert-dialog.d.ts.map +0 -1
  488. package/dist/components/alert-dialog/alert-dialog.js.map +0 -1
  489. package/dist/components/alert-dialog/index.d.ts.map +0 -1
  490. package/dist/components/alert-dialog/index.js.map +0 -1
  491. package/dist/components/aspect-ratio/aspect-ratio.d.ts.map +0 -1
  492. package/dist/components/aspect-ratio/aspect-ratio.js.map +0 -1
  493. package/dist/components/aspect-ratio/index.d.ts.map +0 -1
  494. package/dist/components/aspect-ratio/index.js.map +0 -1
  495. package/dist/components/avatar/avatar.d.ts.map +0 -1
  496. package/dist/components/avatar/avatar.js.map +0 -1
  497. package/dist/components/avatar/index.d.ts.map +0 -1
  498. package/dist/components/avatar/index.js.map +0 -1
  499. package/dist/components/badge/badge.d.ts.map +0 -1
  500. package/dist/components/badge/badge.js.map +0 -1
  501. package/dist/components/badge/index.d.ts.map +0 -1
  502. package/dist/components/badge/index.js.map +0 -1
  503. package/dist/components/box/box.d.ts +0 -143
  504. package/dist/components/box/box.d.ts.map +0 -1
  505. package/dist/components/box/box.js +0 -38
  506. package/dist/components/box/box.js.map +0 -1
  507. package/dist/components/box/index.d.ts +0 -2
  508. package/dist/components/box/index.d.ts.map +0 -1
  509. package/dist/components/box/index.js +0 -2
  510. package/dist/components/box/index.js.map +0 -1
  511. package/dist/components/button/button.d.ts.map +0 -1
  512. package/dist/components/button/button.js.map +0 -1
  513. package/dist/components/button/index.d.ts.map +0 -1
  514. package/dist/components/button/index.js.map +0 -1
  515. package/dist/components/card/card.d.ts.map +0 -1
  516. package/dist/components/card/card.js.map +0 -1
  517. package/dist/components/card/index.d.ts.map +0 -1
  518. package/dist/components/card/index.js.map +0 -1
  519. package/dist/components/checkbox/checkbox.d.ts.map +0 -1
  520. package/dist/components/checkbox/checkbox.js.map +0 -1
  521. package/dist/components/checkbox/index.d.ts.map +0 -1
  522. package/dist/components/checkbox/index.js.map +0 -1
  523. package/dist/components/collapsible/collapsible.d.ts.map +0 -1
  524. package/dist/components/collapsible/collapsible.js.map +0 -1
  525. package/dist/components/collapsible/index.d.ts.map +0 -1
  526. package/dist/components/collapsible/index.js.map +0 -1
  527. package/dist/components/context-menu/context-menu.d.ts.map +0 -1
  528. package/dist/components/context-menu/context-menu.js.map +0 -1
  529. package/dist/components/context-menu/index.d.ts.map +0 -1
  530. package/dist/components/context-menu/index.js.map +0 -1
  531. package/dist/components/data-row/data-row.d.ts.map +0 -1
  532. package/dist/components/data-row/data-row.js.map +0 -1
  533. package/dist/components/data-row/index.d.ts.map +0 -1
  534. package/dist/components/data-row/index.js.map +0 -1
  535. package/dist/components/dialog/dialog.d.ts.map +0 -1
  536. package/dist/components/dialog/dialog.js.map +0 -1
  537. package/dist/components/dialog/index.d.ts.map +0 -1
  538. package/dist/components/dialog/index.js.map +0 -1
  539. package/dist/components/dropdown-menu/dropdown-menu.d.ts.map +0 -1
  540. package/dist/components/dropdown-menu/dropdown-menu.js.map +0 -1
  541. package/dist/components/dropdown-menu/index.d.ts.map +0 -1
  542. package/dist/components/dropdown-menu/index.js.map +0 -1
  543. package/dist/components/form-field/form-field.d.ts.map +0 -1
  544. package/dist/components/form-field/form-field.js.map +0 -1
  545. package/dist/components/form-field/index.d.ts.map +0 -1
  546. package/dist/components/form-field/index.js.map +0 -1
  547. package/dist/components/hover-card/hover-card.d.ts.map +0 -1
  548. package/dist/components/hover-card/hover-card.js.map +0 -1
  549. package/dist/components/hover-card/index.d.ts.map +0 -1
  550. package/dist/components/hover-card/index.js.map +0 -1
  551. package/dist/components/input/index.d.ts.map +0 -1
  552. package/dist/components/input/index.js.map +0 -1
  553. package/dist/components/input/input.d.ts.map +0 -1
  554. package/dist/components/input/input.js.map +0 -1
  555. package/dist/components/label/index.d.ts.map +0 -1
  556. package/dist/components/label/index.js.map +0 -1
  557. package/dist/components/label/label.d.ts.map +0 -1
  558. package/dist/components/label/label.js.map +0 -1
  559. package/dist/components/labeled-field/index.d.ts.map +0 -1
  560. package/dist/components/labeled-field/index.js.map +0 -1
  561. package/dist/components/labeled-field/labeled-field.d.ts.map +0 -1
  562. package/dist/components/labeled-field/labeled-field.js.map +0 -1
  563. package/dist/components/layout/index.d.ts +0 -2
  564. package/dist/components/layout/index.d.ts.map +0 -1
  565. package/dist/components/layout/index.js +0 -2
  566. package/dist/components/layout/index.js.map +0 -1
  567. package/dist/components/layout/layout.d.ts +0 -395
  568. package/dist/components/layout/layout.d.ts.map +0 -1
  569. package/dist/components/layout/layout.js +0 -93
  570. package/dist/components/layout/layout.js.map +0 -1
  571. package/dist/components/menubar/index.d.ts.map +0 -1
  572. package/dist/components/menubar/index.js.map +0 -1
  573. package/dist/components/menubar/menubar.d.ts.map +0 -1
  574. package/dist/components/menubar/menubar.js.map +0 -1
  575. package/dist/components/numeric-input/index.d.ts.map +0 -1
  576. package/dist/components/numeric-input/index.js.map +0 -1
  577. package/dist/components/numeric-input/numeric-input.d.ts.map +0 -1
  578. package/dist/components/numeric-input/numeric-input.js.map +0 -1
  579. package/dist/components/otp-input/index.d.ts.map +0 -1
  580. package/dist/components/otp-input/index.js.map +0 -1
  581. package/dist/components/otp-input/otp-input.d.ts.map +0 -1
  582. package/dist/components/otp-input/otp-input.js.map +0 -1
  583. package/dist/components/popover/index.d.ts.map +0 -1
  584. package/dist/components/popover/index.js.map +0 -1
  585. package/dist/components/popover/popover.d.ts.map +0 -1
  586. package/dist/components/popover/popover.js.map +0 -1
  587. package/dist/components/pressable/index.d.ts.map +0 -1
  588. package/dist/components/pressable/index.js.map +0 -1
  589. package/dist/components/pressable/pressable.d.ts.map +0 -1
  590. package/dist/components/pressable/pressable.js.map +0 -1
  591. package/dist/components/progress/index.d.ts.map +0 -1
  592. package/dist/components/progress/index.js.map +0 -1
  593. package/dist/components/progress/progress.d.ts.map +0 -1
  594. package/dist/components/progress/progress.js.map +0 -1
  595. package/dist/components/radio-group/index.d.ts.map +0 -1
  596. package/dist/components/radio-group/index.js.map +0 -1
  597. package/dist/components/radio-group/radio-group.d.ts.map +0 -1
  598. package/dist/components/radio-group/radio-group.js.map +0 -1
  599. package/dist/components/row/index.d.ts.map +0 -1
  600. package/dist/components/row/index.js.map +0 -1
  601. package/dist/components/row/row.d.ts.map +0 -1
  602. package/dist/components/row/row.js.map +0 -1
  603. package/dist/components/segmented-control/index.d.ts.map +0 -1
  604. package/dist/components/segmented-control/index.js.map +0 -1
  605. package/dist/components/segmented-control/segmented-control.d.ts.map +0 -1
  606. package/dist/components/segmented-control/segmented-control.js.map +0 -1
  607. package/dist/components/select/index.d.ts.map +0 -1
  608. package/dist/components/select/index.js.map +0 -1
  609. package/dist/components/select/select.d.ts.map +0 -1
  610. package/dist/components/select/select.js.map +0 -1
  611. package/dist/components/separator/index.d.ts.map +0 -1
  612. package/dist/components/separator/index.js.map +0 -1
  613. package/dist/components/separator/separator.d.ts.map +0 -1
  614. package/dist/components/separator/separator.js.map +0 -1
  615. package/dist/components/skeleton/index.d.ts.map +0 -1
  616. package/dist/components/skeleton/index.js.map +0 -1
  617. package/dist/components/skeleton/skeleton.d.ts.map +0 -1
  618. package/dist/components/skeleton/skeleton.js.map +0 -1
  619. package/dist/components/spinner/index.d.ts.map +0 -1
  620. package/dist/components/spinner/index.js.map +0 -1
  621. package/dist/components/spinner/spinner.d.ts.map +0 -1
  622. package/dist/components/spinner/spinner.js.map +0 -1
  623. package/dist/components/stack/index.d.ts.map +0 -1
  624. package/dist/components/stack/index.js.map +0 -1
  625. package/dist/components/stack/stack.d.ts.map +0 -1
  626. package/dist/components/stack/stack.js.map +0 -1
  627. package/dist/components/switch/index.d.ts.map +0 -1
  628. package/dist/components/switch/index.js.map +0 -1
  629. package/dist/components/switch/switch.d.ts.map +0 -1
  630. package/dist/components/switch/switch.js.map +0 -1
  631. package/dist/components/tabs/index.d.ts.map +0 -1
  632. package/dist/components/tabs/index.js.map +0 -1
  633. package/dist/components/tabs/tabs.d.ts.map +0 -1
  634. package/dist/components/tabs/tabs.js.map +0 -1
  635. package/dist/components/text/index.d.ts.map +0 -1
  636. package/dist/components/text/index.js.map +0 -1
  637. package/dist/components/text/text.d.ts.map +0 -1
  638. package/dist/components/text/text.js.map +0 -1
  639. package/dist/components/textarea/index.d.ts.map +0 -1
  640. package/dist/components/textarea/index.js.map +0 -1
  641. package/dist/components/textarea/textarea.d.ts.map +0 -1
  642. package/dist/components/textarea/textarea.js.map +0 -1
  643. package/dist/components/toast/index.d.ts.map +0 -1
  644. package/dist/components/toast/index.js.map +0 -1
  645. package/dist/components/toast/toast.d.ts.map +0 -1
  646. package/dist/components/toast/toast.js.map +0 -1
  647. package/dist/components/toggle/index.d.ts.map +0 -1
  648. package/dist/components/toggle/index.js.map +0 -1
  649. package/dist/components/toggle/toggle.d.ts.map +0 -1
  650. package/dist/components/toggle/toggle.js.map +0 -1
  651. package/dist/components/toggle-group/index.d.ts.map +0 -1
  652. package/dist/components/toggle-group/index.js.map +0 -1
  653. package/dist/components/toggle-group/toggle-group.d.ts.map +0 -1
  654. package/dist/components/toggle-group/toggle-group.js.map +0 -1
  655. package/dist/components/tooltip/index.d.ts.map +0 -1
  656. package/dist/components/tooltip/index.js.map +0 -1
  657. package/dist/components/tooltip/tooltip.d.ts.map +0 -1
  658. package/dist/components/tooltip/tooltip.js.map +0 -1
  659. package/dist/components/view/index.d.ts.map +0 -1
  660. package/dist/components/view/index.js.map +0 -1
  661. package/dist/components/view/view.d.ts.map +0 -1
  662. package/dist/components/view/view.js.map +0 -1
  663. package/dist/index.d.ts.map +0 -1
  664. package/dist/index.js.map +0 -1
  665. package/dist/lib/cn.d.ts.map +0 -1
  666. package/dist/lib/cn.js.map +0 -1
  667. package/dist/lib/font-context.d.ts.map +0 -1
  668. package/dist/lib/font-context.js.map +0 -1
  669. package/dist/lib/frosted-surface.d.ts.map +0 -1
  670. package/dist/lib/frosted-surface.js.map +0 -1
  671. package/dist/lib/index.d.ts +0 -6
  672. package/dist/lib/index.d.ts.map +0 -1
  673. package/dist/lib/index.js +0 -6
  674. package/dist/lib/index.js.map +0 -1
  675. package/dist/lib/interaction-tokens.d.ts.map +0 -1
  676. package/dist/lib/interaction-tokens.js.map +0 -1
  677. package/dist/lib/portal.d.ts.map +0 -1
  678. package/dist/lib/portal.js.map +0 -1
  679. package/dist/lib/react-native-classname.d.ts.map +0 -1
  680. package/dist/lib/react-native-classname.js.map +0 -1
  681. package/dist/lib/theme-bridge.d.ts.map +0 -1
  682. package/dist/lib/theme-bridge.js.map +0 -1
  683. package/dist/lib/theme-colors.d.ts.map +0 -1
  684. package/dist/lib/theme-colors.js.map +0 -1
  685. package/dist/lib/tv.d.ts.map +0 -1
  686. package/dist/lib/tv.js.map +0 -1
  687. package/dist/lib/visual-tokens.d.ts.map +0 -1
  688. package/dist/lib/visual-tokens.js.map +0 -1
  689. package/dist/vite.d.ts.map +0 -1
  690. package/dist/vite.js.map +0 -1
package/README.md CHANGED
@@ -4,13 +4,18 @@
4
4
 
5
5
  Beautiful, accessible, themeable components built with [Uniwind](https://uniwind.dev) + Tailwind CSS v4.
6
6
 
7
- **Requirements:** React 19+, React Native 0.81+, Expo 52+ (if using Expo). Supports React Native Web.
7
+ **Requirements:** React 19.3+, React Native 0.88+, Expo 58+ (if using Expo). Supports React Native Web.
8
+
9
+ WhileUI has one renderer: React Native. iOS, Android and React Native Web are all
10
+ production targets — iOS and Android set the interaction baseline. See
11
+ [ROADMAP.md](./ROADMAP.md) for the product boundary and extraction rules, and
12
+ [PLAN.md](./PLAN.md) for the supported stack and production contracts.
8
13
 
9
14
  ## Installation
10
15
 
11
16
  ```bash
12
17
  bun add @thewhileloop/whileui
13
- bun add react@^19.0.0 react-native@^0.81.0 uniwind@^1.0.0 tailwindcss@^4.0.0 react-native-reanimated react-native-safe-area-context react-native-screens
18
+ bun add react@^19.3.0 react-native@^0.88.0 uniwind@^1.12.2 tailwindcss@^4.0.0 react-native-reanimated react-native-safe-area-context react-native-screens
14
19
  # Only if you use Select, Popover, Tooltip, or HoverCard:
15
20
  bun add @rn-primitives/portal @rn-primitives/hooks @rn-primitives/slot @rn-primitives/select @rn-primitives/popover @rn-primitives/tooltip @rn-primitives/hover-card
16
21
  ```
@@ -101,15 +106,15 @@ module.exports = withUniwindConfig({
101
106
 
102
107
  ```tsx
103
108
  import './global.css';
104
- import { PortalHost } from '@thewhileloop/whileui';
109
+ import { MotionProvider, PortalHost } from '@thewhileloop/whileui';
105
110
  import { Button, ButtonText } from '@thewhileloop/whileui';
106
111
 
107
112
  export default function App() {
108
113
  return (
109
- <>
114
+ <MotionProvider>
110
115
  {/* Your app content */}
111
116
  <PortalHost />
112
- </>
117
+ </MotionProvider>
113
118
  );
114
119
  }
115
120
  ```
@@ -209,6 +214,8 @@ function MyScreen() {
209
214
  - **Layout:** `Stack` (vertical), `Row` (horizontal) — both support `gap`, `align`, `justify`
210
215
  - **Auth callbacks:** Auth templates use objects: `onSubmit({ email, password })`, `onSubmit({ firstName, lastName, email, password })`, etc. Copy templates from `apps/showcase/templates/auth/`.
211
216
  - **PortalHost:** Add `<PortalHost />` at app root for Select, Popover, Tooltip, HoverCard.
217
+ - **Motion:** Wrap the root in `<MotionProvider>`; use `useMotionPolicy()` for semantic
218
+ durations, the responsive spring, and reduced-motion behavior.
212
219
  - **Uniwind:** `withUniwindConfig` must wrap metro config. `global.css` at app root, imported in `App.tsx`.
213
220
  - **Reference:** Block props in `packages/ui/src/blocks` (core) and `apps/showcase/templates/` (auth, profile); flow patterns in README "Flow Patterns" section.
214
221
 
@@ -223,7 +230,12 @@ function MyScreen() {
223
230
  | **Pressable** | Themed pressable wrapper |
224
231
  | **Stack** | Vertical flex layout with gap |
225
232
  | **Row** | Horizontal flex layout with gap |
226
- | **Box** | Flexible container with variants |
233
+
234
+ ### Root Providers
235
+
236
+ | Provider | Notes |
237
+ | ------------------ | ------------------------------------------------------------------------ |
238
+ | **MotionProvider** | System reduced motion, explicit preview modes, and deterministic testing |
227
239
 
228
240
  ### Form Controls
229
241
 
@@ -267,6 +279,7 @@ function MyScreen() {
267
279
  | **Tabs** | TabsList, TabsTrigger, TabsContent |
268
280
  | **Accordion** | AccordionItem, AccordionTrigger, Content |
269
281
  | **Collapsible** | CollapsibleTrigger, CollapsibleContent |
282
+ | **Container** | Centred content column with a max width |
270
283
 
271
284
  ### Overlays & Menus
272
285
 
@@ -305,37 +318,37 @@ Copy from `apps/showcase/templates/auth/`:
305
318
 
306
319
  ### Navigation
307
320
 
308
- | Block | Description |
309
- | --------------------- | ------------------------------------------------- |
310
- | **AppShell** | Layout shell with header/footer/bottomNav slots |
311
- | **NavigationSidebar** | Sidebar nav with grouped sections and footer slot |
312
- | **Header** | Top app bar with back/actions |
313
- | **BottomNav** | Tab-style bottom navigation bar |
314
- | **FloatingBottomNav** | Elevated bottom nav with safe area support |
315
- | **TabBar** | Top tab bar with indicator |
316
- | **DrawerMenu** | Drawer with sections and items |
321
+ | Block | Description |
322
+ | --------------------- | ----------------------------------------------- |
323
+ | **AppShell** | Layout shell with header/footer/bottomNav slots |
324
+ | **Header** | Top app bar with back/actions |
325
+ | **BottomNav** | Tab-style bottom navigation bar |
326
+ | **FloatingBottomNav** | Elevated bottom nav with safe area support |
327
+ | **TabBar** | Top tab bar with indicator |
328
+ | **DrawerMenu** | Drawer with sections and items |
317
329
 
318
330
  ### Layout
319
331
 
320
- | Block | Description |
321
- | --------------------------- | ----------------------------------------------------------------------- |
322
- | **ActionBar** | Sticky bottom action row with safe-area padding |
323
- | **ConfirmActionSheet** | Reusable destructive confirmation sheet |
324
- | **Sheet** | Bottom sheet modal with header/content/footer slots |
325
- | **FormModalScreen** | Modal scaffold for forms with loading states |
326
- | **ContentSkeleton** | Page/content placeholder with variants (list, card, generic) |
327
- | **PageSkeleton** | Variant-based page layouts (dashboard, list, settings, card, generic) |
328
- | **ScreenSkeleton** | Header slot/placeholder + PageSkeleton content in one block |
329
- | **ErrorBoundary** | React ErrorBoundary that renders ErrorState by default |
330
- | **EmptyState** | Empty content placeholder |
331
- | **ErrorState** | Error display with retry |
332
- | **LoadingScreen** | Full-screen loading indicator |
333
- | **PullToRefreshScrollView** | Themed ScrollView with RefreshControl (useThemeTokens for colors) |
334
- | **SmartInput** | Keyboard-aware compose input: left/center/right slots, bar/card variant |
335
- | **OnboardingScreen** | Onboarding flow screen |
336
- | **SplashScreen** | Branded splash (fade/scale/slide variants) |
337
- | **MinimalSplash** | Minimal monochrome splash |
338
- | **BrandedSplash** | Splash with brand imagery |
332
+ | Block | Description |
333
+ | --------------------------- | --------------------------------------------------------------------- |
334
+ | **ActionBar** | Sticky bottom action row with safe-area padding |
335
+ | **ConfirmActionSheet** | Reusable destructive confirmation sheet |
336
+ | **Sheet** | Bottom sheet modal with header/content/footer slots |
337
+ | **FormModalScreen** | Modal scaffold for forms with loading states |
338
+ | **ContentSkeleton** | Page/content placeholder with variants (list, card, generic) |
339
+ | **PageSkeleton** | Variant-based page layouts (dashboard, list, settings, card, generic) |
340
+ | **ScreenSkeleton** | Header slot/placeholder + PageSkeleton content in one block |
341
+ | **ErrorBoundary** | React ErrorBoundary that renders ErrorState by default |
342
+ | **EmptyState** | Empty content placeholder |
343
+ | **ErrorState** | Error display with retry |
344
+ | **LoadingScreen** | Full-screen loading indicator |
345
+ | **PullToRefreshScrollView** | Themed ScrollView with RefreshControl (useThemeTokens for colors) |
346
+ | **KeyboardAwareScreen** | One screen-level keyboard policy for bottom-docked controls |
347
+ | **DockedInput** | Safe-area-aware bottom dock that reports its complete height |
348
+ | **SmartInput** | Compose input with slots, variants, and optional rotating examples |
349
+ | **SplashScreen** | Branded splash (fade/scale/slide variants) |
350
+ | **MinimalSplash** | Minimal monochrome splash |
351
+ | **BrandedSplash** | Splash with brand imagery |
339
352
 
340
353
  ### Chat
341
354
 
@@ -362,7 +375,6 @@ Copy from `apps/showcase/templates/profile/`:
362
375
  | -------------------- | ----------------------------------- |
363
376
  | **ListItem** | Title/subtitle row |
364
377
  | **NotificationItem** | Notification row with metadata |
365
- | **SwipeableItem** | Swipe actions list item |
366
378
  | **TimelineFeed** | Vertical feed with connecting lines |
367
379
 
368
380
  ### Commerce
@@ -393,12 +405,19 @@ Copy from `apps/showcase/templates/profile/`:
393
405
  | **DatePickerInline** | Inline calendar for forms or dashboards |
394
406
  | **DateRangePickerModal** | Range selection modal with period marking |
395
407
 
396
- ## Layout Primitives (Stack, Row, Box)
408
+ **Tokens without a renderer.** `@thewhileloop/whileui/tokens` exports the theme
409
+ and visual contracts, the presets, and `deriveThemeColors(base, scheme)` — give it
410
+ the 25 base colours an app defines and it returns all 52, using the same ratios
411
+ as the default presets. Safe in a build script (no React, RN or Uniwind
412
+ imports); `useThemeColors()` uses it too, so a missing `--color-primary-soft`
413
+ derives from the app's own primary instead of falling back to the default palette.
414
+
415
+ ## Layout Primitives (Stack, Row)
397
416
 
398
417
  Use `Stack` for vertical layouts, `Row` for horizontal layouts. Both support `gap`, `align`, and `justify` variants.
399
418
 
400
419
  ```tsx
401
- import { Stack, Row, Box } from '@thewhileloop/whileui';
420
+ import { Stack, Row } from '@thewhileloop/whileui';
402
421
 
403
422
  <Stack gap="lg">
404
423
  <Text>Title</Text>
@@ -419,7 +438,32 @@ import { Stack, Row, Box } from '@thewhileloop/whileui';
419
438
  | align | `'start' \| 'center' \| 'end' \| 'stretch' \| 'baseline'` | Cross-axis alignment |
420
439
  | justify | `'start' \| 'center' \| 'end' \| 'between' \| 'around' \| 'evenly'` | Main-axis alignment |
421
440
 
422
- `Box` provides optional padding and margin variants for consistent spacing.
441
+ ### Container
442
+
443
+ Caps content width and centres it. Phone-first layouts stretch to the viewport, which
444
+ is right at 390px and wrong at 1600px — line lengths become unreadable and related
445
+ controls drift apart.
446
+
447
+ ```tsx
448
+ <Container size="lg">{children}</Container>
449
+ ```
450
+
451
+ | Prop | Type | Default | Notes |
452
+ | ----------- | -------------------------------------- | ------- | --------------------------- |
453
+ | `size` | `sm` \| `md` \| `lg` \| `xl` \| `full` | `md` | `sm` forms, `lg` dashboards |
454
+ | `fill` | `boolean` | `false` | `flex-1`, for a screen root |
455
+ | `className` | `string` | — | Merged after the variant |
456
+
457
+ No platform branch, and none is needed: every size is wider than any phone, so on iOS
458
+ and Android the cap never engages and it renders as a plain full-width `View`. The same
459
+ component is a no-op on native and the whole fix on desktop.
460
+
461
+ For a scroll view, put the column on the content container so the scrollbar stays at
462
+ the window edge:
463
+
464
+ ```tsx
465
+ <ScrollView contentContainerClassName="w-full max-w-5xl self-center" />
466
+ ```
423
467
 
424
468
  ## Full-Screen Composition
425
469
 
@@ -548,7 +592,7 @@ The WhileUI token contract is strict for cross-app reuse. Define these in **ever
548
592
  - Required core tokens: `background`, `foreground`, `card`, `card-foreground`, `popover`, `popover-foreground`, `primary`, `primary-foreground`, `secondary`, `secondary-foreground`, `muted`, `muted-foreground`, `accent`, `accent-foreground`, `destructive`, `destructive-foreground`, `border`, `input`, `ring`
549
593
  - Optional status tokens: `success`, `success-foreground`, `warning`, `warning-foreground`, `info`, `info-foreground`
550
594
  - Optional effect tokens: `overlay`, `overlay-strong`, `surface-elevated`, `surface-border`, `surface-highlight`, `surface-translucent`, `surface-translucent-border`, `state-hover`, `state-pressed`, `state-disabled`
551
- - Optional interaction/motion tokens: `--ui-press-opacity`, `--ui-press-opacity-strong`, `--ui-disabled-opacity`, `--ui-disabled-opacity-soft`, `--ui-disabled-opacity-subtle`, `--ui-inactive-opacity`, `--ui-motion-fast`, `--ui-motion-normal`, `--ui-motion-slow`, `--ui-drawer-open-duration`, `--ui-drawer-close-duration`, `--ui-blur-intensity-subtle`, `--ui-blur-intensity-medium`, `--ui-blur-intensity-strong`, `--ui-blur-saturation-pct`, `--ui-frosted-highlight-height`, `--ui-frosted-backdrop-blur-intensity`, `--ui-frosted-backdrop-blur-scale`, `--ui-frosted-android-experimental-blur`, `--ui-drawer-frosted-inset`, `--ui-drawer-frosted-radius`, `--ui-drawer-content-top-padding`
595
+ - Optional interaction/motion tokens: `--ui-press-opacity`, `--ui-press-opacity-strong`, `--ui-disabled-opacity`, `--ui-disabled-opacity-soft`, `--ui-disabled-opacity-subtle`, `--ui-inactive-opacity`, `--ui-motion-fast`, `--ui-motion-normal`, `--ui-motion-slow`, `--ui-motion-spring-damping`, `--ui-motion-spring-stiffness`, `--ui-motion-spring-mass`, `--ui-drawer-open-duration`, `--ui-drawer-close-duration`, `--ui-blur-intensity-subtle`, `--ui-blur-intensity-medium`, `--ui-blur-intensity-strong`, `--ui-blur-saturation-pct`, `--ui-frosted-highlight-height`, `--ui-frosted-backdrop-blur-intensity`, `--ui-frosted-backdrop-blur-scale`, `--ui-frosted-android-tint-alpha-scale`, `--ui-frosted-android-experimental-blur`, `--ui-drawer-frosted-inset`, `--ui-drawer-frosted-radius`, `--ui-drawer-content-top-padding`
552
596
  - Optional scale tokens: spacing (`--spacing`, `--spacing-*`), typography (`--text-*`, `--leading-*`, `--tracking-*`), radius (`--radius-*`), elevation (`--shadow-*`)
553
597
 
554
598
  Minimal contract example:
@@ -608,6 +652,8 @@ Some apps want a frosted or translucent look for floating panels (modals, sheets
608
652
 
609
653
  **Optional:** Add `expo-blur` and register its `BlurView` once at app startup for full frosted blur. For tint-only (no blur), translucent surface tokens are sufficient.
610
654
 
655
+ **Android note:** frosted panels usually need denser tint than iOS/web. WhileUI now scales frosted tint alpha on Android with `--ui-frosted-android-tint-alpha-scale` (default `1.18`). Set it to `1` to match other platforms exactly, or raise it if your Android surfaces still feel washed out.
656
+
611
657
  ```tsx
612
658
  import { BlurView } from 'expo-blur';
613
659
  import { registerFrostedBlurView } from '@thewhileloop/whileui';
@@ -635,6 +681,7 @@ Additional frosted tuning tokens:
635
681
  - `--ui-frosted-highlight-height` (top highlight strip height in px, set `0` to disable hard top sheen)
636
682
  - `--ui-frosted-backdrop-blur-intensity` (default backdrop blur amount)
637
683
  - `--ui-frosted-backdrop-blur-scale` (ratio used when component blur is overridden)
684
+ - `--ui-frosted-android-tint-alpha-scale` (Android-only alpha multiplier applied to frosted tint and backdrop layers)
638
685
  - `--ui-frosted-android-experimental-blur` (`1` enables `expo-blur` Android experimental path)
639
686
  - `--ui-drawer-frosted-inset` (floating inset for frosted drawer shells)
640
687
  - `--ui-drawer-frosted-radius` (drawer corner radius in px)
@@ -678,6 +725,9 @@ WhileUI components also read optional `--ui-*` tokens for deeper control of pres
678
725
  --ui-motion-fast: 160;
679
726
  --ui-motion-normal: 220;
680
727
  --ui-motion-slow: 300;
728
+ --ui-motion-spring-damping: 20;
729
+ --ui-motion-spring-stiffness: 260;
730
+ --ui-motion-spring-mass: 0.8;
681
731
  --ui-drawer-open-duration: 300;
682
732
  --ui-drawer-close-duration: 220;
683
733
  --ui-blur-intensity-subtle: 18;
@@ -687,6 +737,7 @@ WhileUI components also read optional `--ui-*` tokens for deeper control of pres
687
737
  --ui-frosted-highlight-height: 0;
688
738
  --ui-frosted-backdrop-blur-intensity: 14;
689
739
  --ui-frosted-backdrop-blur-scale: 0.55;
740
+ --ui-frosted-android-tint-alpha-scale: 1.22;
690
741
  --ui-frosted-android-experimental-blur: 1;
691
742
  --ui-drawer-frosted-inset: 0;
692
743
  --ui-drawer-frosted-radius: 28;
@@ -700,6 +751,23 @@ For custom components, use:
700
751
  import { useInteractionTokens, withInteractivePressableStyle } from '@thewhileloop/whileui';
701
752
  ```
702
753
 
754
+ Wrap the application in `MotionProvider` to coordinate system reduced motion, explicit
755
+ preview overrides, and deterministic animation-free tests. The provider is optional:
756
+ without it `useMotionPolicy` returns the token defaults with Reanimated following the
757
+ system setting, and `--ui-motion-*` overrides are not read. `reduced` preserves
758
+ non-spatial feedback while asking Reanimated to skip motion; `disabled` also resolves
759
+ semantic durations to zero.
760
+
761
+ ```tsx
762
+ import { MotionProvider, useMotionPolicy } from '@thewhileloop/whileui';
763
+
764
+ <MotionProvider mode="system">{/* application */}</MotionProvider>;
765
+
766
+ const motion = useMotionPolicy();
767
+ motion.durations.normal;
768
+ motion.springs.responsive;
769
+ ```
770
+
703
771
  Optional RN fallback tokens (hex/rgb/hsl/named):
704
772
 
705
773
  ```css
@@ -783,7 +851,8 @@ Optional RN fallback tokens (hex/rgb/hsl/named):
783
851
  }
784
852
  ```
785
853
 
786
- Or use the first-party ThemeBridge helper with optional persistence:
854
+ Or use the first-party theme bridge with optional persistence. The hook owns theme
855
+ state and exposes event-driven setters:
787
856
 
788
857
  ```tsx
789
858
  import { useThemeBridge, type ThemeBridgeAdapter } from '@thewhileloop/whileui';
@@ -798,6 +867,43 @@ const adapter: ThemeBridgeAdapter = {
798
867
  const { mode, resolvedTheme, setMode, cycleMode } = useThemeBridge({ adapter });
799
868
  ```
800
869
 
870
+ When another store already owns the mode, mount the controlled bridge once near the
871
+ application root. Change `mode` in the owning event handler; the bridge applies and
872
+ persists it without mirroring state back through a callback effect.
873
+
874
+ ```tsx
875
+ import { ThemeBridge } from '@thewhileloop/whileui';
876
+
877
+ <ThemeBridge mode={mode} adapter={adapter} />;
878
+ ```
879
+
880
+ ## Focus rings
881
+
882
+ Every interactive component draws a themed focus ring on web. It uses `:focus-visible`,
883
+ so it appears for keyboard users and not after a mouse click, and it is driven by the
884
+ `--color-ring` token — restyle it with your theme, not with component overrides.
885
+
886
+ Use the same treatment on your own controls:
887
+
888
+ ```tsx
889
+ import { focusRing, focusRingInset, cn } from '@thewhileloop/whileui';
890
+
891
+ <Pressable className={cn('rounded-full px-4 py-2', focusRing)} onPress={onPress}>
892
+ <Text>Custom control</Text>
893
+ </Pressable>;
894
+ ```
895
+
896
+ | Export | Use for |
897
+ | ---------------- | ------------------------------------------------------------------------------- |
898
+ | `focusRing` | Standalone controls — buttons, inputs, cards, nav items |
899
+ | `focusRingInset` | Controls flush inside a track, where an offset ring would clip (segments, tabs) |
900
+
901
+ **Do not use a bare `outline-none`.** It removes the browser's indicator and leaves
902
+ keyboard users with nothing, which fails WCAG 2.4.7. `focusRing` removes the default and
903
+ supplies a themed replacement in the same class. The one exemption is a visually hidden
904
+ input, where a visible proxy shows the focus instead — `OTPInput` does this with its
905
+ blinking cursor.
906
+
801
907
  ## Tech Stack
802
908
 
803
909
  - **Styling**: [Uniwind](https://uniwind.dev) (free tier) + Tailwind CSS v4
@@ -808,28 +914,57 @@ const { mode, resolvedTheme, setMode, cycleMode } = useThemeBridge({ adapter });
808
914
 
809
915
  # API Reference
810
916
 
917
+ ## Pressable
918
+
919
+ ```tsx
920
+ import { Pressable, Text } from '@thewhileloop/whileui';
921
+
922
+ <Pressable
923
+ accessibilityRole="button"
924
+ feedback="strong"
925
+ disabledFeedback="default"
926
+ loading={false}
927
+ onPress={() => {}}
928
+ >
929
+ <Text>Open</Text>
930
+ </Pressable>;
931
+ ```
932
+
933
+ `Pressable` preserves React Native's event, ref, accessibility, and function-style
934
+ `style` contracts. Feedback changes opacity without changing layout. Native press state
935
+ comes directly from React Native; web adds a motion-policy-aware opacity transition.
936
+
937
+ | Prop | Type | Default | Description |
938
+ | ---------------- | ------------------------------------------- | ----------- | ------------------------------------------ |
939
+ | feedback | `'none' \| 'default' \| 'strong'` | `'none'` | Semantic pressed opacity |
940
+ | disabledFeedback | `'none' \| 'default' \| 'soft' \| 'subtle'` | `'default'` | Semantic unavailable opacity |
941
+ | loading | `boolean` | `false` | Expose busy/disabled state and block input |
942
+ | className | `string` | — | Additional Tailwind classes |
943
+
811
944
  ## Button
812
945
 
813
946
  ```tsx
814
947
  import { Button, ButtonText, ButtonIcon } from '@thewhileloop/whileui';
815
948
 
816
- <Button variant="default" size="default" disabled={false} onPress={() => {}}>
949
+ <Button variant="default" size="default" disabled={false} loading={false} onPress={() => {}}>
817
950
  <ButtonIcon>
818
951
  <Icon />
819
952
  </ButtonIcon>
820
953
  <ButtonText>Click me</ButtonText>
821
- <ButtonIcon position="right">
954
+ {/* Placement is child order — a trailing ButtonIcon renders after the label. */}
955
+ <ButtonIcon>
822
956
  <Icon />
823
957
  </ButtonIcon>
824
958
  </Button>;
825
959
  ```
826
960
 
827
- | Prop | Type | Default | Description |
828
- | --------- | ----------------------------------------------------------------------------- | ----------- | --------------------------- |
829
- | variant | `'default' \| 'destructive' \| 'outline' \| 'secondary' \| 'ghost' \| 'link'` | `'default'` | Button style variant |
830
- | size | `'default' \| 'sm' \| 'lg' \| 'icon'` | `'default'` | Button size |
831
- | disabled | `boolean` | `false` | Disable the button |
832
- | className | `string` | — | Additional Tailwind classes |
961
+ | Prop | Type | Default | Description |
962
+ | --------- | ----------------------------------------------------------------------------- | ----------- | -------------------------------------------------- |
963
+ | variant | `'default' \| 'destructive' \| 'outline' \| 'secondary' \| 'ghost' \| 'link'` | `'default'` | Button style variant |
964
+ | size | `'default' \| 'sm' \| 'lg' \| 'icon'` | `'default'` | Button size |
965
+ | disabled | `boolean` | `false` | Disable the button |
966
+ | loading | `boolean` | `false` | Show a spinner, expose busy state, and block input |
967
+ | className | `string` | — | Additional Tailwind classes |
833
968
 
834
969
  ## Input
835
970
 
@@ -1138,12 +1273,12 @@ import {
1138
1273
 
1139
1274
  `AlertDialogContent` supports the same frosted props as `DialogContent`.
1140
1275
 
1141
- | Prop | Type | Default | Description |
1142
- | ------------- | ------------------------ | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1143
- | presentation | `'modal' \| 'native' \| 'overlay'` | `'modal'` | **`modal`** — themed card in an RN `Modal` (iOS `overFullScreen`). **`native`** — `Alert.alert` on iOS/Android (system UI); use when a second `Modal` won’t stack; ignored on web. **`overlay`** — same themed card as `modal`, but absolutely positioned **inside the parent view** (no second `Modal`). Nest `<AlertDialog>` under your fullscreen sheet’s root so the confirm matches app styling. **Web:** `'native'` is ignored; `overlay` behaves like `modal`. |
1144
- | frosted | `boolean` | `false` | Same as `DialogContent` |
1145
- | blurIntensity | `number` | — | Same as `DialogContent` |
1146
- | blurTintToken | `'surfaceElevated' \| …` | — | Same as `DialogContent` |
1276
+ | Prop | Type | Default | Description |
1277
+ | ------------- | ---------------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1278
+ | presentation | `'modal' \| 'native' \| 'overlay'` | `'modal'` | **`modal`** — themed card in an RN `Modal` (iOS `overFullScreen`). **`native`** — `Alert.alert` on iOS/Android (system UI); use when a second `Modal` won’t stack; ignored on web. **`overlay`** — same themed card as `modal`, but absolutely positioned **inside the parent view** (no second `Modal`). Nest `<AlertDialog>` under your fullscreen sheet’s root so the confirm matches app styling. **Web:** `'native'` is ignored; `overlay` behaves like `modal`. |
1279
+ | frosted | `boolean` | `false` | Same as `DialogContent` |
1280
+ | blurIntensity | `number` | — | Same as `DialogContent` |
1281
+ | blurTintToken | `'surfaceElevated' \| …` | — | Same as `DialogContent` |
1147
1282
 
1148
1283
  ### React Native: stacked modals
1149
1284
 
@@ -1384,6 +1519,40 @@ import {
1384
1519
 
1385
1520
  ## Menubar
1386
1521
 
1522
+ ```tsx
1523
+ import {
1524
+ Menubar,
1525
+ MenubarMenu,
1526
+ MenubarTrigger,
1527
+ MenubarContent,
1528
+ MenubarLabel,
1529
+ MenubarItem,
1530
+ MenubarSeparator,
1531
+ } from '@thewhileloop/whileui';
1532
+
1533
+ <Menubar>
1534
+ <MenubarMenu>
1535
+ <MenubarTrigger>
1536
+ <Text className="text-foreground text-sm">File</Text>
1537
+ </MenubarTrigger>
1538
+ <MenubarContent>
1539
+ <MenubarLabel>Project</MenubarLabel>
1540
+ <MenubarItem>
1541
+ <Text className="text-foreground">New Project</Text>
1542
+ </MenubarItem>
1543
+ <MenubarSeparator />
1544
+ <MenubarItem>
1545
+ <Text className="text-foreground">Export</Text>
1546
+ </MenubarItem>
1547
+ </MenubarContent>
1548
+ </MenubarMenu>
1549
+ </Menubar>;
1550
+ ```
1551
+
1552
+ `MenubarLabel` is a non-interactive section heading. It takes a string or elements, and
1553
+ announces as a heading to assistive technology — as do `DropdownMenuLabel` and
1554
+ `ContextMenuLabel`.
1555
+
1387
1556
  `MenubarContent` supports the same frosted props as `PopoverContent` (default blur preset: medium).
1388
1557
 
1389
1558
  ---
@@ -1392,7 +1561,8 @@ import {
1392
1561
 
1393
1562
  ## SignInForm
1394
1563
 
1395
- Copy from `apps/showcase/templates/auth/sign-in-form.tsx`, then:
1564
+ Copy `sign-in-form.tsx` and its sibling `auth-form-footer.tsx` from
1565
+ `apps/showcase/templates/auth/`, then:
1396
1566
 
1397
1567
  ```tsx
1398
1568
  import { SignInForm } from './templates/auth'; // or your path
@@ -1416,7 +1586,8 @@ import { SignInForm } from './templates/auth'; // or your path
1416
1586
 
1417
1587
  ## SignUpForm
1418
1588
 
1419
- Copy from `apps/showcase/templates/auth/sign-up-form.tsx`, then:
1589
+ Copy `sign-up-form.tsx` and its sibling `auth-form-footer.tsx` from
1590
+ `apps/showcase/templates/auth/`, then:
1420
1591
 
1421
1592
  ```tsx
1422
1593
  import { SignUpForm } from './templates/auth'; // or your path
@@ -1494,9 +1665,24 @@ import { ActionBar, Button, ButtonText } from '@thewhileloop/whileui';
1494
1665
  </ActionBar>;
1495
1666
  ```
1496
1667
 
1668
+ ## KeyboardAwareScreen and DockedInput
1669
+
1670
+ Use one keyboard-aware root for the screen, then place the composer in a bottom dock. Feed the dock height into the scroll content inset so the last item remains visible.
1671
+
1672
+ ```tsx
1673
+ import { DockedInput, KeyboardAwareScreen, SmartInput } from '@thewhileloop/whileui';
1674
+
1675
+ <KeyboardAwareScreen>
1676
+ <ScrollView contentContainerStyle={{ paddingBottom: inputHeight }} />
1677
+ <DockedInput onHeightChange={setInputHeight}>
1678
+ <SmartInput variant="card" safeArea={false} />
1679
+ </DockedInput>
1680
+ </KeyboardAwareScreen>;
1681
+ ```
1682
+
1497
1683
  ## SmartInput
1498
1684
 
1499
- Keyboard-aware compose input. `variant`: "bar" (sticky bottom) or "card" (floating). Slots: `leftSlot`, `centerSlot` (intent selector), `rightSlot`. `submitBehavior`: "newline" (default) or "submit"/"blurAndSubmit". Forwards ref to `TextInput`.
1685
+ Compose input for use inline or inside `DockedInput`. `variant`: "bar" or "card". Slots: `leftSlot`, `centerSlot` (intent selector), `rightSlot`. `submitBehavior`: "newline" (default) or "submit"/"blurAndSubmit". `placeholderExamples` animates rotating prompts and respects the platform reduced-motion setting. Forwards ref to `TextInput`.
1500
1686
 
1501
1687
  ```tsx
1502
1688
  import { SmartInput, Button, ButtonText } from '@thewhileloop/whileui';
@@ -1504,7 +1690,7 @@ import { SmartInput, Button, ButtonText } from '@thewhileloop/whileui';
1504
1690
  <SmartInput
1505
1691
  value={message}
1506
1692
  onChangeText={setMessage}
1507
- placeholder="Type a message..."
1693
+ placeholderExamples={['Log breakfast', 'Add a 30 minute walk', 'Set weight to 72 kg']}
1508
1694
  leftSlot={
1509
1695
  <Button variant="ghost" size="icon">
1510
1696
  <Icon name="add" />
@@ -1677,27 +1863,12 @@ import {
1677
1863
  | blurIntensity | `number` | medium preset |
1678
1864
  | blurTintToken | `'surfaceElevated' \| 'surfaceTranslucent' \| 'card' \| 'popover'` | `'surfaceTranslucent'` |
1679
1865
 
1680
- ## NavigationSidebar
1681
-
1682
- ```tsx
1683
- import { NavigationSidebar } from '@thewhileloop/whileui';
1684
-
1685
- <NavigationSidebar
1686
- sections={[
1687
- {
1688
- title: 'Workspace',
1689
- items: [
1690
- { key: 'overview', label: 'Overview', icon: <Icon /> },
1691
- { key: 'billing', label: 'Billing', icon: <Icon />, badge: 2 },
1692
- ],
1693
- },
1694
- ]}
1695
- activeKey="overview"
1696
- onSelect={(key) => {}}
1697
- header={<Text>Acme Inc.</Text>}
1698
- footer={<Text className="text-xs text-muted-foreground">v1.0.0</Text>}
1699
- />;
1700
- ```
1866
+ `SheetContent` is a `ScrollView` and accepts its props. It enables nested scrolling and
1867
+ keeps taps on inputs while the keyboard is open (`keyboardShouldPersistTaps="handled"`).
1868
+ Your `contentContainerStyle` is merged after the default padding. Tapping the backdrop
1869
+ closes the sheet; a drag across the backdrop does not, so a missed scroll never dismisses
1870
+ it. There is no drag-to-dismiss: close with the backdrop, Android back, Escape on web or
1871
+ `SheetClose`.
1701
1872
 
1702
1873
  ## Header
1703
1874
 
@@ -1825,11 +1996,17 @@ import { PullToRefreshScrollView } from '@thewhileloop/whileui';
1825
1996
  </PullToRefreshScrollView>;
1826
1997
  ```
1827
1998
 
1828
- | Prop | Type | Description |
1829
- | ------------ | ------------ | ------------------------------------------ |
1830
- | refreshing | `boolean` | Whether refresh is in progress |
1831
- | onRefresh | `() => void` | Called when user pulls to refresh |
1832
- | refreshColor | `string` | Optional hex override; defaults to primary |
1999
+ | Prop | Type | Description |
2000
+ | ------------ | ----------------------------- | --------------------------------------------------------------------------------------------------------------- |
2001
+ | refreshing | `boolean` | Whether refresh is in progress |
2002
+ | onRefresh | `() => void \| Promise<void>` | Called when user pulls to refresh. Not awaited — drive the spinner with `refreshing`, and catch your own errors |
2003
+ | refreshColor | `string` | Optional hex override; defaults to primary |
2004
+
2005
+ The scroll view owns the refresh gesture; don't pass `refreshControl`. It bounces even
2006
+ when content is shorter than the screen, so a short list can still be pulled. Screen
2007
+ reader users get the same refresh as a **Refresh** accessibility action, since they
2008
+ cannot pull. It is ignored while `refreshing` is true, and any `accessibilityActions` you
2009
+ pass are kept.
1833
2010
 
1834
2011
  ## EmptyState
1835
2012
 
@@ -2064,13 +2241,12 @@ Tracked work items for future releases.
2064
2241
 
2065
2242
  - [x] ProductCard, ListItem, NotificationItem, MetricCard, SubscriptionCard, PricingCard
2066
2243
  - [x] AppShell, Chat, FormModalScreen, CheckoutSummary (already had `loading`)
2067
- - [ ] Add `loading` to remaining blocks: Header, BottomNav, DrawerMenu, TimelineFeed, SwipeableItem
2244
+ - [ ] Add `loading` to remaining blocks: Header, BottomNav, DrawerMenu, TimelineFeed
2068
2245
 
2069
2246
  ### Documentation Gaps
2070
2247
 
2071
- - [ ] Add `## API` sections for: Textarea, Toggle, ToggleGroup, Label, Separator, Skeleton, AspectRatio, Collapsible, Text, View, Pressable
2072
- - [ ] Add `## API` sections for blocks: FloatingBottomNav, TabBar, FormModalScreen, ErrorState, LoadingScreen, OnboardingScreen, ListItem, NotificationItem, MetricCard, SmartImage, TimelineFeed
2073
- - [ ] Build `apps/site/` (docs website) with `registry.ts`, `demos.tsx`, `block-demos.tsx`, `props-data.ts`
2248
+ - [ ] Add `## API` sections for: Textarea, Toggle, ToggleGroup, Label, Separator, Skeleton, AspectRatio, Collapsible, Text, View
2249
+ - [ ] Add `## API` sections for blocks: FloatingBottomNav, TabBar, FormModalScreen, ErrorState, LoadingScreen, ListItem, NotificationItem, MetricCard, SmartImage, TimelineFeed
2074
2250
 
2075
2251
  ### Infrastructure
2076
2252
 
@@ -43,7 +43,6 @@ export interface ChatProps {
43
43
  export declare function ChatMessageBubble({ message, contentClassName, }: {
44
44
  message: ChatMessage;
45
45
  contentClassName?: string;
46
- }): import("react/jsx-runtime").JSX.Element;
47
- export declare function ChatSuggestions({ suggestions, onSelect, className }: ChatSuggestionsProps): import("react/jsx-runtime").JSX.Element;
48
- export declare function Chat({ messages, value, onChangeText, onSend, placeholder, suggestions, onSuggestionPress, leftSlot, rightSlot, loading, header, emptyTitle, emptyDescription, exampleMessage, renderMessage, loadingIndicator, inputSafeArea, keyboardVerticalOffset, className, messagesClassName, }: ChatProps): import("react/jsx-runtime").JSX.Element;
49
- //# sourceMappingURL=chat.d.ts.map
46
+ }): React.JSX.Element;
47
+ export declare function ChatSuggestions({ suggestions, onSelect, className }: ChatSuggestionsProps): React.JSX.Element;
48
+ export declare function Chat({ messages, value, onChangeText, onSend, placeholder, suggestions, onSuggestionPress, leftSlot, rightSlot, loading, header, emptyTitle, emptyDescription, exampleMessage, renderMessage, loadingIndicator, inputSafeArea, keyboardVerticalOffset, className, messagesClassName, }: ChatProps): React.JSX.Element;