@passui/react 0.1.17 → 0.1.20

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 (408) hide show
  1. package/README.md +140 -1
  2. package/THIRD_PARTY_NOTICES.md +25 -0
  3. package/dist/types/src/appearance/index.d.ts +2 -0
  4. package/dist/types/src/appearance/platform.d.ts +9 -0
  5. package/dist/types/src/appearance/theme.d.ts +71 -0
  6. package/dist/types/src/components/accordion/accordion.d.ts +19 -0
  7. package/dist/types/src/components/ambient/ambient.d.ts +12 -0
  8. package/dist/types/src/components/ambient/index.d.ts +1 -0
  9. package/dist/types/src/components/aspect-ratio/aspect-ratio.d.ts +7 -0
  10. package/dist/types/src/components/breadcrumb/breadcrumb.d.ts +16 -0
  11. package/dist/types/src/components/button/button-styles.d.ts +12 -0
  12. package/dist/types/src/components/button/button.d.ts +32 -0
  13. package/dist/types/src/components/button/icon-button.d.ts +10 -0
  14. package/dist/types/src/components/button/pending-spinner.d.ts +5 -0
  15. package/dist/types/src/components/button/use-pending-indicator.d.ts +2 -0
  16. package/dist/types/src/components/chip/chip.d.ts +7 -0
  17. package/dist/types/src/components/code-block/code-block.d.ts +10 -0
  18. package/dist/types/src/components/combo-box/combo-box.d.ts +9 -0
  19. package/dist/types/src/components/command/command.d.ts +18 -0
  20. package/dist/types/src/components/compact-date-picker/calendar-month.d.ts +25 -0
  21. package/dist/types/src/components/compact-date-picker/compact-date-picker.d.ts +27 -0
  22. package/dist/types/src/components/compact-time-picker/compact-time-picker.d.ts +26 -0
  23. package/dist/types/src/components/compact-time-picker/time-value.d.ts +18 -0
  24. package/dist/types/src/components/content-unavailable-view/content-unavailable-view.d.ts +9 -0
  25. package/dist/types/src/components/content-view/content-view.d.ts +48 -0
  26. package/dist/types/src/components/content-view/index.d.ts +1 -0
  27. package/dist/types/src/components/context-menu/conceal-menu-source.d.ts +2 -0
  28. package/dist/types/src/components/context-menu/context-menu-host.d.ts +2 -0
  29. package/dist/types/src/components/context-menu/context-menu-store.d.ts +57 -0
  30. package/dist/types/src/components/context-menu/menu-navigation.d.ts +6 -0
  31. package/dist/types/src/components/context-menu/menu-position.d.ts +21 -0
  32. package/dist/types/src/components/context-menu/menu-reveal.d.ts +17 -0
  33. package/dist/types/src/components/context-menu/use-context-menu.d.ts +14 -0
  34. package/dist/types/src/components/conversation/conversation.d.ts +43 -0
  35. package/dist/types/src/components/conversation/index.d.ts +1 -0
  36. package/dist/types/src/components/date-picker/date-picker.d.ts +16 -0
  37. package/dist/types/src/components/date-picker/date-value.d.ts +2 -0
  38. package/dist/types/src/components/dialog/dialog-host.d.ts +6 -0
  39. package/dist/types/src/components/dialog/dialog-store.d.ts +23 -0
  40. package/dist/types/src/components/dialog/dialog.d.ts +30 -0
  41. package/dist/types/src/components/dialog/index.d.ts +1 -0
  42. package/dist/types/src/components/disclosure-group/disclosure-group.d.ts +15 -0
  43. package/dist/types/src/components/divider/divider.d.ts +9 -0
  44. package/dist/types/src/components/inline-disclosure/inline-disclosure.d.ts +15 -0
  45. package/dist/types/src/components/keyboard-shortcut/keyboard-shortcut.d.ts +5 -0
  46. package/dist/types/src/components/labeled-content/labeled-content.d.ts +19 -0
  47. package/dist/types/src/components/locale-switcher/index.d.ts +1 -0
  48. package/dist/types/src/components/locale-switcher/locale-switcher.d.ts +10 -0
  49. package/dist/types/src/components/menu/menu.d.ts +16 -0
  50. package/dist/types/src/components/one-time-code/one-time-code.d.ts +18 -0
  51. package/dist/types/src/components/picker/picker-trigger.d.ts +2 -0
  52. package/dist/types/src/components/picker/picker.d.ts +43 -0
  53. package/dist/types/src/components/popover/anchored-surface.d.ts +13 -0
  54. package/dist/types/src/components/popover/popover-fit.d.ts +21 -0
  55. package/dist/types/src/components/popover/popover.d.ts +18 -0
  56. package/dist/types/src/components/profile-image/profile-image.d.ts +4 -0
  57. package/dist/types/src/components/progress-view/progress-view.d.ts +13 -0
  58. package/dist/types/src/components/progress-view/use-liquid-progress.d.ts +3 -0
  59. package/dist/types/src/components/radio-group/radio-group.d.ts +17 -0
  60. package/dist/types/src/components/search-field/expanding-search-field.d.ts +5 -0
  61. package/dist/types/src/components/search-field/search-field.d.ts +6 -0
  62. package/dist/types/src/components/search-list/search-list.d.ts +19 -0
  63. package/dist/types/src/components/section/section.d.ts +15 -0
  64. package/dist/types/src/components/secure-field/secure-field.d.ts +4 -0
  65. package/dist/types/src/components/segmented-control/segmented-control.d.ts +20 -0
  66. package/dist/types/src/components/sheet/modal-environment.d.ts +2 -0
  67. package/dist/types/src/components/sheet/sheet-portal.d.ts +5 -0
  68. package/dist/types/src/components/sheet/sheet.d.ts +21 -0
  69. package/dist/types/src/components/sheet/use-sheet-focus.d.ts +3 -0
  70. package/dist/types/src/components/sidebar/sidebar.d.ts +19 -0
  71. package/dist/types/src/components/skeleton/skeleton.d.ts +6 -0
  72. package/dist/types/src/components/slider/slider.d.ts +14 -0
  73. package/dist/types/src/components/slosh-slider/liquid-step.d.ts +6 -0
  74. package/dist/types/src/components/slosh-slider/slosh-slider.d.ts +18 -0
  75. package/dist/types/src/components/stat-tile/index.d.ts +1 -0
  76. package/dist/types/src/components/stat-tile/stat-tile.d.ts +15 -0
  77. package/dist/types/src/components/status-indicator/status-indicator.d.ts +14 -0
  78. package/dist/types/src/components/stepper/rolling-digit.d.ts +11 -0
  79. package/dist/types/src/components/stepper/stepper.d.ts +19 -0
  80. package/dist/types/src/components/swatch-picker/swatch-picker.d.ts +17 -0
  81. package/dist/types/src/components/tab-bar/tab-bar.d.ts +40 -0
  82. package/dist/types/src/components/tab-view/tab-view.d.ts +24 -0
  83. package/dist/types/src/components/table/table.d.ts +10 -0
  84. package/dist/types/src/components/text-editor/text-editor.d.ts +2 -0
  85. package/dist/types/src/components/text-field/text-field.d.ts +20 -0
  86. package/dist/types/src/components/toast/toast-store.d.ts +47 -0
  87. package/dist/types/src/components/toast/toaster.d.ts +10 -0
  88. package/dist/types/src/components/toggle/toggle.d.ts +17 -0
  89. package/dist/types/src/components/tooltip/tooltip-host.d.ts +6 -0
  90. package/dist/types/src/components/view-controller/index.d.ts +1 -0
  91. package/dist/types/src/components/view-controller/view-controller.d.ts +21 -0
  92. package/dist/types/src/components/wake-slider/wake-slider.d.ts +12 -0
  93. package/dist/types/src/hooks/scroll/minimize-decision.d.ts +2 -0
  94. package/dist/types/src/hooks/use-anchored-disclosure.d.ts +9 -0
  95. package/dist/types/src/hooks/use-anchored-placement.d.ts +7 -0
  96. package/dist/types/src/hooks/use-dismiss.d.ts +9 -0
  97. package/dist/types/src/hooks/use-floating-dismiss.d.ts +3 -0
  98. package/dist/types/src/hooks/use-media-query.d.ts +21 -0
  99. package/dist/types/src/hooks/use-minimize-on-scroll.d.ts +6 -0
  100. package/dist/types/src/hooks/use-visual-viewport.d.ts +4 -0
  101. package/dist/types/src/hooks/viewport/types.d.ts +19 -0
  102. package/dist/types/src/hooks/viewport/viewport-metrics.d.ts +3 -0
  103. package/dist/types/src/icons/icons.d.ts +612 -0
  104. package/dist/types/src/index.d.ts +71 -0
  105. package/dist/types/src/lib/anchored-placement.d.ts +39 -0
  106. package/dist/types/src/lib/class-names.d.ts +2 -0
  107. package/dist/types/src/lib/clipboard.d.ts +6 -0
  108. package/dist/types/src/lib/date.d.ts +50 -0
  109. package/dist/types/src/lib/floating-layers.d.ts +8 -0
  110. package/dist/types/src/lib/haptics.d.ts +8 -0
  111. package/dist/types/src/lib/language.d.ts +4 -0
  112. package/dist/types/src/lib/range-value.d.ts +4 -0
  113. package/dist/types/src/lib/screen-edges.d.ts +12 -0
  114. package/dist/types/src/lib/shapes.d.ts +17 -0
  115. package/dist/types/src/motion/transitions.d.ts +97 -0
  116. package/dist/types/src/tokens.d.ts +1 -0
  117. package/package.json +248 -40
  118. package/src/appearance/platform.tsx +10 -47
  119. package/src/appearance/theme.tsx +42 -142
  120. package/src/components/accordion/accordion.tsx +48 -0
  121. package/src/components/ambient/ambient.tsx +2 -10
  122. package/src/components/aspect-ratio/aspect-ratio.tsx +22 -0
  123. package/src/components/breadcrumb/breadcrumb.tsx +53 -0
  124. package/src/components/button/button-styles.ts +13 -31
  125. package/src/components/button/button.tsx +24 -15
  126. package/src/components/button/icon-button.tsx +14 -56
  127. package/src/components/button/use-pending-indicator.ts +2 -7
  128. package/src/components/chip/chip.tsx +8 -13
  129. package/src/components/code-block/code-block.tsx +41 -0
  130. package/src/components/combo-box/combo-box.tsx +13 -0
  131. package/src/components/command/command.tsx +119 -0
  132. package/src/components/compact-date-picker/calendar-month.ts +13 -57
  133. package/src/components/compact-date-picker/compact-date-picker.tsx +72 -195
  134. package/src/components/compact-time-picker/compact-time-picker.tsx +74 -195
  135. package/src/components/compact-time-picker/time-value.ts +4 -16
  136. package/src/components/content-unavailable-view/content-unavailable-view.tsx +37 -0
  137. package/src/components/content-view/content-view.tsx +13 -56
  138. package/src/components/context-menu/conceal-menu-source.ts +1 -4
  139. package/src/components/context-menu/context-menu-host.tsx +132 -198
  140. package/src/components/context-menu/context-menu-store.ts +5 -14
  141. package/src/components/context-menu/menu-navigation.ts +29 -0
  142. package/src/components/context-menu/menu-position.ts +6 -27
  143. package/src/components/context-menu/menu-reveal.ts +14 -52
  144. package/src/components/context-menu/use-context-menu.ts +6 -30
  145. package/src/components/conversation/conversation.tsx +26 -72
  146. package/src/components/date-picker/date-picker.tsx +8 -37
  147. package/src/components/date-picker/date-value.ts +5 -30
  148. package/src/components/dialog/dialog-host.tsx +37 -76
  149. package/src/components/dialog/dialog-store.ts +16 -7
  150. package/src/components/dialog/dialog.tsx +23 -80
  151. package/src/components/disclosure-group/disclosure-group.tsx +79 -0
  152. package/src/components/divider/divider.tsx +31 -0
  153. package/src/components/inline-disclosure/inline-disclosure.tsx +49 -0
  154. package/src/components/keyboard-shortcut/keyboard-shortcut.tsx +17 -0
  155. package/src/components/labeled-content/labeled-content.tsx +24 -18
  156. package/src/components/locale-switcher/locale-switcher.tsx +20 -70
  157. package/src/components/menu/menu.tsx +68 -0
  158. package/src/components/one-time-code/one-time-code.tsx +168 -0
  159. package/src/components/picker/picker-trigger.ts +10 -0
  160. package/src/components/picker/picker.tsx +165 -283
  161. package/src/components/popover/anchored-surface.tsx +223 -0
  162. package/src/components/popover/popover-fit.ts +69 -0
  163. package/src/components/popover/popover.tsx +209 -63
  164. package/src/components/profile-image/profile-image.tsx +6 -28
  165. package/src/components/progress-view/progress-view.tsx +70 -0
  166. package/src/components/progress-view/use-liquid-progress.ts +43 -0
  167. package/src/components/radio-group/radio-group.tsx +63 -0
  168. package/src/components/search-field/expanding-search-field.tsx +183 -0
  169. package/src/components/search-field/search-field.tsx +25 -7
  170. package/src/components/search-list/search-list.tsx +58 -75
  171. package/src/components/section/section.tsx +18 -17
  172. package/src/components/secure-field/secure-field.tsx +5 -7
  173. package/src/components/segmented-control/segmented-control.tsx +20 -29
  174. package/src/components/sheet/modal-environment.ts +16 -54
  175. package/src/components/sheet/sheet-portal.tsx +10 -42
  176. package/src/components/sheet/sheet.tsx +17 -25
  177. package/src/components/sheet/use-sheet-focus.ts +15 -51
  178. package/src/components/sidebar/sidebar.tsx +44 -38
  179. package/src/components/skeleton/skeleton.tsx +19 -0
  180. package/src/components/slider/slider.tsx +76 -0
  181. package/src/components/slosh-slider/liquid-step.ts +42 -0
  182. package/src/components/slosh-slider/slosh-slider.tsx +251 -0
  183. package/src/components/stat-tile/stat-tile.tsx +9 -30
  184. package/src/components/status-indicator/status-indicator.tsx +12 -19
  185. package/src/components/stepper/rolling-digit.tsx +77 -0
  186. package/src/components/stepper/stepper.tsx +101 -0
  187. package/src/components/swatch-picker/swatch-picker.tsx +19 -15
  188. package/src/components/tab-bar/tab-bar.tsx +59 -59
  189. package/src/components/tab-view/tab-view.tsx +52 -57
  190. package/src/components/table/table.tsx +14 -62
  191. package/src/components/text-editor/text-editor.tsx +2 -12
  192. package/src/components/text-field/text-field.tsx +53 -44
  193. package/src/components/toast/toast-store.ts +9 -30
  194. package/src/components/toast/toaster.tsx +90 -104
  195. package/src/components/toggle/toggle.tsx +165 -44
  196. package/src/components/tooltip/tooltip-host.tsx +70 -67
  197. package/src/components/view-controller/view-controller.tsx +4 -21
  198. package/src/components/wake-slider/wake-slider.tsx +237 -0
  199. package/src/hooks/scroll/minimize-decision.ts +1 -5
  200. package/src/hooks/use-anchored-disclosure.ts +23 -0
  201. package/src/hooks/use-anchored-placement.ts +7 -14
  202. package/src/hooks/use-dismiss.ts +5 -23
  203. package/src/hooks/use-floating-dismiss.ts +28 -0
  204. package/src/hooks/use-media-query.ts +12 -31
  205. package/src/hooks/use-minimize-on-scroll.ts +10 -34
  206. package/src/hooks/use-visual-viewport.ts +5 -14
  207. package/src/hooks/viewport/viewport-metrics.ts +4 -16
  208. package/src/icons/icons.tsx +229 -183
  209. package/src/index.ts +27 -1
  210. package/src/lib/anchored-placement.ts +12 -18
  211. package/src/lib/class-names.ts +1 -2
  212. package/src/lib/clipboard.ts +14 -0
  213. package/src/lib/date.ts +4 -15
  214. package/src/lib/floating-layers.ts +18 -8
  215. package/src/lib/haptics.ts +1 -3
  216. package/src/lib/language.ts +2 -7
  217. package/src/lib/range-value.ts +32 -0
  218. package/src/lib/screen-edges.ts +2 -6
  219. package/src/lib/shapes.ts +5 -20
  220. package/src/motion/transitions.ts +18 -12
  221. package/src/styles/code-block.css +33 -0
  222. package/src/styles/motion-controls.css +189 -0
  223. package/src/styles/styles.css +3 -0
  224. package/src/components/ambient/ambient.docs.tsx +0 -68
  225. package/src/components/ambient/examples/ambient-images.tsx +0 -30
  226. package/src/components/ambient/examples/ambient-now-playing.tsx +0 -55
  227. package/src/components/ambient/examples/ambient-showcase.tsx +0 -33
  228. package/src/components/ambient/examples/ambient-usage.tsx +0 -19
  229. package/src/components/button/button.docs.tsx +0 -116
  230. package/src/components/button/examples/button-disabled.tsx +0 -19
  231. package/src/components/button/examples/button-icon.tsx +0 -39
  232. package/src/components/button/examples/button-link.tsx +0 -12
  233. package/src/components/button/examples/button-pending.tsx +0 -27
  234. package/src/components/button/examples/button-showcase.tsx +0 -115
  235. package/src/components/button/examples/button-sizes.tsx +0 -12
  236. package/src/components/button/examples/button-usage.tsx +0 -12
  237. package/src/components/button/examples/button-variants.tsx +0 -15
  238. package/src/components/button/examples/button-with-icon.tsx +0 -32
  239. package/src/components/button/examples/icon-button-player.tsx +0 -38
  240. package/src/components/button/examples/icon-button-showcase.tsx +0 -83
  241. package/src/components/button/examples/icon-button-usage.tsx +0 -11
  242. package/src/components/button/examples/icon-button-variants.tsx +0 -39
  243. package/src/components/button/icon-button.docs.tsx +0 -68
  244. package/src/components/chip/chip.docs.tsx +0 -37
  245. package/src/components/chip/examples/chip-in-rows.tsx +0 -19
  246. package/src/components/chip/examples/chip-showcase.tsx +0 -51
  247. package/src/components/chip/examples/chip-tones.tsx +0 -13
  248. package/src/components/chip/examples/chip-usage.tsx +0 -5
  249. package/src/components/compact-date-picker/compact-date-picker.docs.tsx +0 -81
  250. package/src/components/compact-date-picker/examples/compact-date-picker-showcase.tsx +0 -35
  251. package/src/components/compact-date-picker/examples/compact-date-picker-usage.tsx +0 -22
  252. package/src/components/compact-time-picker/compact-time-picker.docs.tsx +0 -80
  253. package/src/components/compact-time-picker/examples/compact-time-picker-showcase.tsx +0 -31
  254. package/src/components/compact-time-picker/examples/compact-time-picker-usage.tsx +0 -21
  255. package/src/components/content-view/content-view.docs.tsx +0 -61
  256. package/src/components/content-view/examples/content-view-header-action.tsx +0 -33
  257. package/src/components/content-view/examples/content-view-showcase.tsx +0 -65
  258. package/src/components/content-view/examples/content-view-stats.tsx +0 -35
  259. package/src/components/content-view/examples/content-view-usage.tsx +0 -14
  260. package/src/components/context-menu/context-menu.docs.tsx +0 -92
  261. package/src/components/context-menu/examples/context-menu-checked.tsx +0 -37
  262. package/src/components/context-menu/examples/context-menu-list.tsx +0 -85
  263. package/src/components/context-menu/examples/context-menu-showcase.tsx +0 -56
  264. package/src/components/context-menu/examples/context-menu-toolbar.tsx +0 -63
  265. package/src/components/context-menu/examples/context-menu-usage.tsx +0 -24
  266. package/src/components/conversation/conversation.docs.tsx +0 -88
  267. package/src/components/conversation/examples/conversation-composer.tsx +0 -36
  268. package/src/components/conversation/examples/conversation-days.tsx +0 -48
  269. package/src/components/conversation/examples/conversation-showcase.tsx +0 -71
  270. package/src/components/conversation/examples/conversation-usage.tsx +0 -28
  271. package/src/components/date-picker/date-picker.docs.tsx +0 -88
  272. package/src/components/date-picker/examples/date-picker-locales.tsx +0 -41
  273. package/src/components/date-picker/examples/date-picker-past-only.tsx +0 -29
  274. package/src/components/date-picker/examples/date-picker-showcase.tsx +0 -49
  275. package/src/components/date-picker/examples/date-picker-usage.tsx +0 -22
  276. package/src/components/dialog/dialog.docs.tsx +0 -114
  277. package/src/components/dialog/examples/dialog-confirm.tsx +0 -24
  278. package/src/components/dialog/examples/dialog-form.tsx +0 -46
  279. package/src/components/dialog/examples/dialog-inline.tsx +0 -48
  280. package/src/components/dialog/examples/dialog-showcase.tsx +0 -53
  281. package/src/components/dialog/examples/dialog-usage.tsx +0 -31
  282. package/src/components/labeled-content/examples/labeled-content-descriptions.tsx +0 -37
  283. package/src/components/labeled-content/examples/labeled-content-showcase.tsx +0 -54
  284. package/src/components/labeled-content/examples/labeled-content-usage.tsx +0 -22
  285. package/src/components/labeled-content/examples/labeled-content-values.tsx +0 -26
  286. package/src/components/labeled-content/examples/labeled-content-wide.tsx +0 -46
  287. package/src/components/labeled-content/labeled-content.docs.tsx +0 -69
  288. package/src/components/locale-switcher/examples/locale-switcher-native-names.tsx +0 -30
  289. package/src/components/locale-switcher/examples/locale-switcher-showcase.tsx +0 -46
  290. package/src/components/locale-switcher/examples/locale-switcher-translated-page.tsx +0 -35
  291. package/src/components/locale-switcher/examples/locale-switcher-usage.tsx +0 -20
  292. package/src/components/locale-switcher/locale-switcher.docs.tsx +0 -91
  293. package/src/components/picker/examples/picker-details.tsx +0 -44
  294. package/src/components/picker/examples/picker-searchable.tsx +0 -48
  295. package/src/components/picker/examples/picker-showcase.tsx +0 -66
  296. package/src/components/picker/examples/picker-usage.tsx +0 -20
  297. package/src/components/picker/picker.docs.tsx +0 -68
  298. package/src/components/popover/examples/popover-help.tsx +0 -57
  299. package/src/components/popover/examples/popover-menu.tsx +0 -51
  300. package/src/components/popover/examples/popover-showcase.tsx +0 -61
  301. package/src/components/popover/examples/popover-usage.tsx +0 -31
  302. package/src/components/popover/popover.docs.tsx +0 -84
  303. package/src/components/profile-image/examples/profile-image-fallbacks.tsx +0 -29
  304. package/src/components/profile-image/examples/profile-image-group.tsx +0 -34
  305. package/src/components/profile-image/examples/profile-image-showcase.tsx +0 -30
  306. package/src/components/profile-image/examples/profile-image-usage.tsx +0 -14
  307. package/src/components/profile-image/profile-image.docs.tsx +0 -81
  308. package/src/components/search-field/examples/search-field-filter.tsx +0 -53
  309. package/src/components/search-field/examples/search-field-showcase.tsx +0 -56
  310. package/src/components/search-field/examples/search-field-toolbar.tsx +0 -27
  311. package/src/components/search-field/examples/search-field-usage.tsx +0 -18
  312. package/src/components/search-field/search-field.docs.tsx +0 -58
  313. package/src/components/search-list/examples/search-list-dropdown.tsx +0 -53
  314. package/src/components/search-list/examples/search-list-groups.tsx +0 -64
  315. package/src/components/search-list/examples/search-list-showcase.tsx +0 -67
  316. package/src/components/search-list/examples/search-list-usage.tsx +0 -27
  317. package/src/components/search-list/search-list.docs.tsx +0 -87
  318. package/src/components/section/examples/section-actions.tsx +0 -35
  319. package/src/components/section/examples/section-groups.tsx +0 -41
  320. package/src/components/section/examples/section-showcase.tsx +0 -63
  321. package/src/components/section/examples/section-usage.tsx +0 -19
  322. package/src/components/section/section.docs.tsx +0 -51
  323. package/src/components/secure-field/examples/secure-field-new-password.tsx +0 -56
  324. package/src/components/secure-field/examples/secure-field-reveal.tsx +0 -20
  325. package/src/components/secure-field/examples/secure-field-showcase.tsx +0 -62
  326. package/src/components/secure-field/examples/secure-field-usage.tsx +0 -19
  327. package/src/components/secure-field/secure-field.docs.tsx +0 -72
  328. package/src/components/segmented-control/examples/segmented-control-overflow.tsx +0 -28
  329. package/src/components/segmented-control/examples/segmented-control-showcase.tsx +0 -59
  330. package/src/components/segmented-control/examples/segmented-control-usage.tsx +0 -20
  331. package/src/components/segmented-control/examples/segmented-control-views.tsx +0 -32
  332. package/src/components/segmented-control/segmented-control.docs.tsx +0 -61
  333. package/src/components/sheet/examples/sheet-choices.tsx +0 -58
  334. package/src/components/sheet/examples/sheet-share.tsx +0 -51
  335. package/src/components/sheet/examples/sheet-showcase.tsx +0 -74
  336. package/src/components/sheet/examples/sheet-usage.tsx +0 -32
  337. package/src/components/sheet/sheet.docs.tsx +0 -75
  338. package/src/components/sidebar/examples/sidebar-groups.tsx +0 -133
  339. package/src/components/sidebar/examples/sidebar-showcase.tsx +0 -123
  340. package/src/components/sidebar/examples/sidebar-unread.tsx +0 -66
  341. package/src/components/sidebar/examples/sidebar-usage.tsx +0 -52
  342. package/src/components/sidebar/sidebar.docs.tsx +0 -135
  343. package/src/components/stat-tile/examples/stat-tile-filters.tsx +0 -32
  344. package/src/components/stat-tile/examples/stat-tile-grid.tsx +0 -21
  345. package/src/components/stat-tile/examples/stat-tile-showcase.tsx +0 -52
  346. package/src/components/stat-tile/examples/stat-tile-usage.tsx +0 -13
  347. package/src/components/stat-tile/stat-tile.docs.tsx +0 -60
  348. package/src/components/status-indicator/examples/status-indicator-live.tsx +0 -34
  349. package/src/components/status-indicator/examples/status-indicator-showcase.tsx +0 -39
  350. package/src/components/status-indicator/examples/status-indicator-states.tsx +0 -17
  351. package/src/components/status-indicator/examples/status-indicator-usage.tsx +0 -9
  352. package/src/components/status-indicator/status-indicator.docs.tsx +0 -43
  353. package/src/components/swatch-picker/examples/swatch-picker-accents.tsx +0 -42
  354. package/src/components/swatch-picker/examples/swatch-picker-labels.tsx +0 -45
  355. package/src/components/swatch-picker/examples/swatch-picker-showcase.tsx +0 -70
  356. package/src/components/swatch-picker/examples/swatch-picker-usage.tsx +0 -39
  357. package/src/components/swatch-picker/swatch-picker.docs.tsx +0 -60
  358. package/src/components/tab-bar/examples/tab-bar-five-tabs.tsx +0 -66
  359. package/src/components/tab-bar/examples/tab-bar-minimize.tsx +0 -71
  360. package/src/components/tab-bar/examples/tab-bar-showcase.tsx +0 -82
  361. package/src/components/tab-bar/examples/tab-bar-usage.tsx +0 -54
  362. package/src/components/tab-bar/tab-bar.docs.tsx +0 -136
  363. package/src/components/tab-view/examples/tab-view-keyboard.tsx +0 -39
  364. package/src/components/tab-view/examples/tab-view-settings.tsx +0 -56
  365. package/src/components/tab-view/examples/tab-view-showcase.tsx +0 -53
  366. package/src/components/tab-view/examples/tab-view-usage.tsx +0 -23
  367. package/src/components/tab-view/tab-view.docs.tsx +0 -77
  368. package/src/components/table/examples/table-empty.tsx +0 -53
  369. package/src/components/table/examples/table-invoices.tsx +0 -102
  370. package/src/components/table/examples/table-selection.tsx +0 -150
  371. package/src/components/table/examples/table-showcase.tsx +0 -115
  372. package/src/components/table/examples/table-usage.tsx +0 -67
  373. package/src/components/table/examples/table-wide.tsx +0 -75
  374. package/src/components/table/table.docs.tsx +0 -131
  375. package/src/components/text-editor/examples/text-editor-comment.tsx +0 -48
  376. package/src/components/text-editor/examples/text-editor-count.tsx +0 -38
  377. package/src/components/text-editor/examples/text-editor-showcase.tsx +0 -58
  378. package/src/components/text-editor/examples/text-editor-usage.tsx +0 -25
  379. package/src/components/text-editor/text-editor.docs.tsx +0 -61
  380. package/src/components/text-field/examples/text-field-icons.tsx +0 -72
  381. package/src/components/text-field/examples/text-field-showcase.tsx +0 -50
  382. package/src/components/text-field/examples/text-field-usage.tsx +0 -18
  383. package/src/components/text-field/examples/text-field-validation.tsx +0 -27
  384. package/src/components/text-field/text-field.docs.tsx +0 -118
  385. package/src/components/toast/examples/toast-action.tsx +0 -32
  386. package/src/components/toast/examples/toast-promise.tsx +0 -45
  387. package/src/components/toast/examples/toast-showcase.tsx +0 -49
  388. package/src/components/toast/examples/toast-usage.tsx +0 -13
  389. package/src/components/toast/toast.docs.tsx +0 -79
  390. package/src/components/toggle/examples/toggle-checkboxes.tsx +0 -43
  391. package/src/components/toggle/examples/toggle-settings.tsx +0 -31
  392. package/src/components/toggle/examples/toggle-showcase.tsx +0 -59
  393. package/src/components/toggle/examples/toggle-usage.tsx +0 -13
  394. package/src/components/toggle/toggle.docs.tsx +0 -69
  395. package/src/components/tooltip/examples/tooltip-icon-buttons.tsx +0 -27
  396. package/src/components/tooltip/examples/tooltip-shortcuts.tsx +0 -38
  397. package/src/components/tooltip/examples/tooltip-showcase.tsx +0 -44
  398. package/src/components/tooltip/examples/tooltip-usage.tsx +0 -13
  399. package/src/components/tooltip/tooltip.docs.tsx +0 -56
  400. package/src/components/view-controller/examples/view-controller-action.tsx +0 -27
  401. package/src/components/view-controller/examples/view-controller-settings.tsx +0 -31
  402. package/src/components/view-controller/examples/view-controller-showcase.tsx +0 -45
  403. package/src/components/view-controller/examples/view-controller-usage.tsx +0 -19
  404. package/src/components/view-controller/view-controller.docs.tsx +0 -71
  405. package/src/docs/index.ts +0 -3
  406. package/src/docs/registry.ts +0 -113
  407. package/src/docs/snippet.ts +0 -17
  408. package/src/docs/types.ts +0 -180
@@ -1,5 +1,5 @@
1
- import { motion } from "motion/react"
2
- import { type ReactNode, useId } from "react"
1
+ import { motion, useReducedMotion } from "motion/react"
2
+ import { Fragment, type ReactNode, useId } from "react"
3
3
  import { useMinimizeOnScroll } from "../../hooks/use-minimize-on-scroll"
4
4
  import { SearchIcon } from "../../icons/icons"
5
5
  import { cn } from "../../lib/class-names"
@@ -19,6 +19,22 @@ export interface TabBarLinkProps {
19
19
  children: ReactNode
20
20
  }
21
21
 
22
+ export type TabBarMinimizeBehavior = "platform" | "scroll" | "never"
23
+
24
+ export interface TabBarProps<Tab extends TabBarTab> {
25
+ /** `platform` follows the platform, `scroll` always minimizes, `never` stays expanded. @default "platform" */
26
+ minimizeBehavior?: TabBarMinimizeBehavior
27
+ tabs: readonly Tab[]
28
+ /** Active tab ID, or null for a destination outside the bar. */
29
+ active: Tab["id"] | null
30
+ /** Renders your router's link with the supplied appearance and accessibility props. */
31
+ renderLink: (tab: Tab, props: TabBarLinkProps) => ReactNode
32
+ search?: { label: string; onPress: () => void }
33
+ /** Accessible name for the navigation. */
34
+ label: string
35
+ className?: string
36
+ }
37
+
22
38
  /**
23
39
  * The app's main places a thumb's reach away, drawn as iOS 26 draws them: a
24
40
  * floating glass capsule of tabs, with Search as its own round button at the
@@ -36,25 +52,12 @@ export function TabBar<Tab extends TabBarTab>({
36
52
  label,
37
53
  className,
38
54
  minimizeBehavior = "platform",
39
- }: {
40
- minimizeBehavior?: "platform" | "scroll" | "never"
41
- tabs: readonly Tab[]
42
- /** Null in places the bar has no tab for. */
43
- active: Tab["id"] | null
44
- renderLink: (
45
- tab: Tab,
46
- props: TabBarLinkProps
47
- ) => ReactNode
48
- search?: { label: string; onPress: () => void }
49
- /** Names the navigation for screen readers. */
50
- label: string
51
- className?: string
52
- }) {
55
+ }: TabBarProps<Tab>) {
53
56
  // Scopes the sliding selection to this bar, so two bars on one
54
57
  // screen (a docs page, a split view) never trade their highlight.
55
58
  const selectionId = `${useId()}-tab-selection`
56
- const [scrolledAway, setScrolledAway] =
57
- useMinimizeOnScroll()
59
+ const reducedMotion = useReducedMotion()
60
+ const [scrolledAway, setScrolledAway] = useMinimizeOnScroll()
58
61
  // Platform behavior keeps Android expanded; apps can opt into scroll minimization.
59
62
  const minimized =
60
63
  scrolledAway &&
@@ -70,8 +73,8 @@ export function TabBar<Tab extends TabBarTab>({
70
73
  )}
71
74
  >
72
75
  <motion.div
73
- layout
74
- transition={spring.smooth}
76
+ layout={!reducedMotion}
77
+ transition={reducedMotion ? { duration: 0 } : spring.smooth}
75
78
  // A tap on the shrunken capsule brings every tab back.
76
79
  onClickCapture={(event) => {
77
80
  if (!minimized) return
@@ -87,41 +90,41 @@ export function TabBar<Tab extends TabBarTab>({
87
90
  {tabs.map((tab) => {
88
91
  const current = tab.id === active
89
92
  if (minimized && !current) return null
90
- return renderLink(tab, {
91
- "aria-current": current
92
- ? "page"
93
- : undefined,
94
- // Switching tabs is silent, as on Apple and Android: no haptic.
95
- onClick: () => {},
96
- className: cn(
97
- "relative isolate flex h-11 min-w-0 flex-col items-center justify-center gap-0.5 rounded-full font-semibold text-[10px] tracking-[0.01em] no-underline transition-[color,transform] duration-fast active:scale-[0.94]",
98
- minimized
99
- ? "w-11"
100
- : "flex-1 px-1",
101
- current
102
- ? "text-accent-text"
103
- : "text-label-secondary"
104
- ),
105
- children: (
106
- <>
107
- {current && (
108
- <motion.span
109
- layoutId={selectionId}
110
- className="glass-lens absolute inset-0 -z-10 rounded-full"
111
- transition={
112
- spring.snappy
113
- }
114
- />
115
- )}
116
- {tab.icon}
117
- {!minimized && (
118
- <span className="max-w-full truncate">
119
- {tab.label}
120
- </span>
121
- )}
122
- </>
123
- ),
124
- })
93
+ return (
94
+ <Fragment key={tab.id}>
95
+ {renderLink(tab, {
96
+ "aria-current": current ? "page" : undefined,
97
+ // Switching tabs is silent, as on Apple and Android: no haptic.
98
+ onClick: () => {},
99
+ className: cn(
100
+ "relative isolate flex h-11 min-w-0 flex-col items-center justify-center gap-0.5 rounded-full font-semibold text-[10px] tracking-[0.01em] no-underline transition-[color,transform] duration-fast active:scale-[0.94]",
101
+ minimized ? "w-11" : "flex-1 px-1",
102
+ current ? "text-accent-text" : "text-label-secondary"
103
+ ),
104
+ children: (
105
+ <>
106
+ {current && (
107
+ <motion.span
108
+ layoutId={selectionId}
109
+ className="glass-lens absolute inset-0 -z-10 rounded-full"
110
+ transition={
111
+ reducedMotion ? { duration: 0 } : spring.snappy
112
+ }
113
+ />
114
+ )}
115
+ {tab.icon}
116
+ <span
117
+ className={
118
+ minimized ? "sr-only" : "max-w-full truncate"
119
+ }
120
+ >
121
+ {tab.label}
122
+ </span>
123
+ </>
124
+ ),
125
+ })}
126
+ </Fragment>
127
+ )
125
128
  })}
126
129
  </motion.div>
127
130
  {search && (
@@ -141,8 +144,5 @@ export function TabBar<Tab extends TabBarTab>({
141
144
  }
142
145
 
143
146
  function onAndroid() {
144
- return (
145
- typeof document !== "undefined" &&
146
- document.documentElement.dataset.os === "android"
147
- )
147
+ return typeof document !== "undefined" && document.documentElement.dataset.os === "android"
148
148
  }
@@ -1,11 +1,25 @@
1
- import {
2
- useId,
3
- useRef,
4
- useState,
5
- type ReactNode,
6
- } from "react"
1
+ import { useId, useRef, useState, type ReactNode } from "react"
7
2
  import { cn } from "../../lib/class-names"
8
3
 
4
+ export type TabViewAlign = "start" | "center"
5
+
6
+ export interface TabViewProps<Value extends string> {
7
+ /** Available tabs, in keyboard navigation order. */
8
+ options: readonly { value: Value; label: string; disabled?: boolean }[]
9
+ /** Initial selection when value is not controlled. */
10
+ defaultValue: Value
11
+ /** Controlled selection; omit to keep selection inside TabView. */
12
+ value?: Value
13
+ onValueChange?: (value: Value) => void
14
+ /** Tab alignment: `start` or `center`. @default "center" */
15
+ align?: TabViewAlign
16
+ /** Accessible name for the tab list. */
17
+ label: string
18
+ /** Renders the selected tab's panel. */
19
+ children: (value: Value) => ReactNode
20
+ className?: string
21
+ }
22
+
9
23
  /** Content tabs with native buttons, roving focus and automatic keyboard activation. */
10
24
  export function TabView<Value extends string>({
11
25
  options,
@@ -16,16 +30,7 @@ export function TabView<Value extends string>({
16
30
  label,
17
31
  children,
18
32
  className,
19
- }: {
20
- options: readonly { value: Value; label: string }[]
21
- defaultValue: Value
22
- value?: Value
23
- onValueChange?: (value: Value) => void
24
- align?: "start" | "center"
25
- label: string
26
- children: (value: Value) => ReactNode
27
- className?: string
28
- }) {
33
+ }: TabViewProps<Value>) {
29
34
  const id = useId()
30
35
  const buttons = useRef<(HTMLButtonElement | null)[]>([])
31
36
  const [selected, setSelected] = useState(defaultValue)
@@ -34,28 +39,18 @@ export function TabView<Value extends string>({
34
39
  if (controlledValue === undefined) setSelected(next)
35
40
  onValueChange?.(next)
36
41
  }
37
- const value = options.some(
38
- (option) => option.value === current
39
- )
40
- ? current
41
- : options[0]?.value
42
+ const enabled = options.filter((option) => !option.disabled)
43
+ const value = enabled.some((option) => option.value === current) ? current : enabled[0]?.value
42
44
  if (value === undefined) return null
43
45
 
44
46
  return (
45
- <div
46
- className={cn(
47
- "flex w-full flex-col gap-5",
48
- className
49
- )}
50
- >
47
+ <div className={cn("flex w-full flex-col gap-5", className)}>
51
48
  <div
52
49
  role="tablist"
53
50
  aria-label={label}
54
51
  className={cn(
55
52
  "inline-flex h-8 w-fit max-w-full items-center gap-5 p-[3px]",
56
- align === "start"
57
- ? "self-start"
58
- : "mx-auto justify-center"
53
+ align === "start" ? "self-start" : "mx-auto justify-center"
59
54
  )}
60
55
  >
61
56
  {options.map((option, index) => (
@@ -66,38 +61,39 @@ export function TabView<Value extends string>({
66
61
  id={`${id}-tab-${index}`}
67
62
  aria-controls={`${id}-panel-${index}`}
68
63
  aria-selected={option.value === value}
69
- tabIndex={
70
- option.value === value ? 0 : -1
71
- }
64
+ aria-disabled={option.disabled || undefined}
65
+ disabled={option.disabled}
66
+ tabIndex={option.value === value ? 0 : -1}
72
67
  ref={(element) => {
73
68
  buttons.current[index] = element
74
69
  }}
75
70
  onClick={() => select(option.value)}
76
71
  onKeyDown={(event) => {
77
- const rtl =
78
- getComputedStyle(
79
- event.currentTarget
80
- ).direction === "rtl"
72
+ const rtl = getComputedStyle(event.currentTarget).direction === "rtl"
81
73
  let next: number
82
- if (event.key === "Home") next = 0
83
- else if (event.key === "End")
84
- next = options.length - 1
85
- else if (
86
- event.key === "ArrowRight"
87
- )
88
- next = index + (rtl ? -1 : 1)
89
- else if (
90
- event.key === "ArrowLeft"
91
- )
92
- next = index + (rtl ? 1 : -1)
93
- else return
74
+ let step: number
75
+ if (event.key === "Home") {
76
+ next = -1
77
+ step = 1
78
+ } else if (event.key === "End") {
79
+ next = options.length
80
+ step = -1
81
+ } else if (event.key === "ArrowRight") {
82
+ step = rtl ? -1 : 1
83
+ next = index
84
+ } else if (event.key === "ArrowLeft") {
85
+ step = rtl ? 1 : -1
86
+ next = index
87
+ } else return
94
88
  event.preventDefault()
95
- next =
96
- (next + options.length) %
97
- options.length
98
- const option = options[next]
99
- if (option) select(option.value)
100
- buttons.current[next]?.focus()
89
+ for (let offset = 0; offset < options.length; offset++) {
90
+ next = (next + step + options.length) % options.length
91
+ const option = options[next]
92
+ if (!option || option.disabled) continue
93
+ select(option.value)
94
+ buttons.current[next]?.focus()
95
+ break
96
+ }
101
97
  }}
102
98
  className={cn(
103
99
  "relative inline-flex h-[calc(100%-1px)] shrink-0 items-center justify-center border border-transparent p-0 text-sm font-medium whitespace-nowrap",
@@ -121,8 +117,7 @@ export function TabView<Value extends string>({
121
117
  hidden={option.value !== value}
122
118
  className="w-full outline-offset-4"
123
119
  >
124
- {option.value === value &&
125
- children(option.value)}
120
+ {option.value === value && children(option.value)}
126
121
  </div>
127
122
  ))}
128
123
  </div>
@@ -2,63 +2,39 @@ import type * as React from "react"
2
2
 
3
3
  import { cn } from "../../lib/class-names"
4
4
 
5
- function Table({
6
- className,
7
- ...props
8
- }: React.ComponentProps<"table">) {
5
+ function Table({ className, ...props }: React.ComponentProps<"table">) {
9
6
  return (
10
- <div
11
- data-slot="table-container"
12
- className="relative w-full overflow-x-auto"
13
- >
7
+ <div data-slot="table-container" className="relative w-full overflow-x-auto">
14
8
  <table
15
9
  data-slot="table"
16
- className={cn(
17
- "w-full caption-bottom text-subheadline text-label",
18
- className
19
- )}
10
+ className={cn("w-full caption-bottom text-subheadline text-label", className)}
20
11
  {...props}
21
12
  />
22
13
  </div>
23
14
  )
24
15
  }
25
16
 
26
- function TableHeader({
27
- className,
28
- ...props
29
- }: React.ComponentProps<"thead">) {
17
+ function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
30
18
  return (
31
19
  <thead
32
20
  data-slot="table-header"
33
- className={cn(
34
- "[&_tr]:border-separator [&_tr]:border-b",
35
- className
36
- )}
21
+ className={cn("[&_tr]:border-separator [&_tr]:border-b", className)}
37
22
  {...props}
38
23
  />
39
24
  )
40
25
  }
41
26
 
42
- function TableBody({
43
- className,
44
- ...props
45
- }: React.ComponentProps<"tbody">) {
27
+ function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
46
28
  return (
47
29
  <tbody
48
30
  data-slot="table-body"
49
- className={cn(
50
- "[&_tr:last-child]:border-0",
51
- className
52
- )}
31
+ className={cn("[&_tr:last-child]:border-0", className)}
53
32
  {...props}
54
33
  />
55
34
  )
56
35
  }
57
36
 
58
- function TableFooter({
59
- className,
60
- ...props
61
- }: React.ComponentProps<"tfoot">) {
37
+ function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
62
38
  return (
63
39
  <tfoot
64
40
  data-slot="table-footer"
@@ -71,10 +47,7 @@ function TableFooter({
71
47
  )
72
48
  }
73
49
 
74
- function TableRow({
75
- className,
76
- ...props
77
- }: React.ComponentProps<"tr">) {
50
+ function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
78
51
  return (
79
52
  <tr
80
53
  data-slot="table-row"
@@ -88,10 +61,7 @@ function TableRow({
88
61
  )
89
62
  }
90
63
 
91
- function TableHead({
92
- className,
93
- ...props
94
- }: React.ComponentProps<"th">) {
64
+ function TableHead({ className, ...props }: React.ComponentProps<"th">) {
95
65
  return (
96
66
  <th
97
67
  data-slot="table-head"
@@ -105,10 +75,7 @@ function TableHead({
105
75
  )
106
76
  }
107
77
 
108
- function TableCell({
109
- className,
110
- ...props
111
- }: React.ComponentProps<"td">) {
78
+ function TableCell({ className, ...props }: React.ComponentProps<"td">) {
112
79
  return (
113
80
  <td
114
81
  data-slot="table-cell"
@@ -121,29 +88,14 @@ function TableCell({
121
88
  )
122
89
  }
123
90
 
124
- function TableCaption({
125
- className,
126
- ...props
127
- }: React.ComponentProps<"caption">) {
91
+ function TableCaption({ className, ...props }: React.ComponentProps<"caption">) {
128
92
  return (
129
93
  <caption
130
94
  data-slot="table-caption"
131
- className={cn(
132
- "mt-4 text-footnote text-label-secondary",
133
- className
134
- )}
95
+ className={cn("mt-4 text-footnote text-label-secondary", className)}
135
96
  {...props}
136
97
  />
137
98
  )
138
99
  }
139
100
 
140
- export {
141
- Table,
142
- TableBody,
143
- TableCaption,
144
- TableCell,
145
- TableFooter,
146
- TableHead,
147
- TableHeader,
148
- TableRow,
149
- }
101
+ export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow }
@@ -2,18 +2,8 @@ import type { ComponentProps } from "react"
2
2
  import { cn } from "../../lib/class-names"
3
3
  import { textControlClasses } from "../text-field/text-field"
4
4
 
5
- export function TextEditor({
6
- className,
7
- ...props
8
- }: ComponentProps<"textarea">) {
5
+ export function TextEditor({ className, ...props }: ComponentProps<"textarea">) {
9
6
  return (
10
- <textarea
11
- {...props}
12
- className={cn(
13
- textControlClasses,
14
- "min-h-28 resize-y",
15
- className
16
- )}
17
- />
7
+ <textarea {...props} className={cn(textControlClasses, "min-h-28 resize-y", className)} />
18
8
  )
19
9
  }
@@ -1,9 +1,4 @@
1
- import {
2
- type ComponentProps,
3
- type ReactNode,
4
- useId,
5
- useState,
6
- } from "react"
1
+ import { type ComponentProps, type ReactNode, useId, useState } from "react"
7
2
  import { Button } from "../button/button"
8
3
  import { cn } from "../../lib/class-names"
9
4
 
@@ -14,8 +9,7 @@ export const textControlClasses = cn(
14
9
  "disabled:cursor-not-allowed disabled:opacity-40 aria-invalid:border-danger"
15
10
  )
16
11
 
17
- const fieldIconClasses =
18
- "flex shrink-0 items-center text-label-secondary"
12
+ const fieldIconClasses = "flex shrink-0 items-center text-label-secondary"
19
13
 
20
14
  export type TextFieldProps = ComponentProps<"input"> & {
21
15
  label: string
@@ -28,6 +22,8 @@ export type TextFieldProps = ComponentProps<"input"> & {
28
22
  /** An interactive control after the text, such as a clear button. Size it to the field: an `xs` or `icon-xs` button, never the default. */
29
23
  action?: ReactNode
30
24
  revealLabels?: { show: string; hide: string }
25
+ /** Float the label into the outline on focus or when filled. @default "above" */
26
+ labelPlacement?: "above" | "floating"
31
27
  }
32
28
 
33
29
  export function TextField({
@@ -38,6 +34,8 @@ export function TextField({
38
34
  trailingIcon,
39
35
  action,
40
36
  revealLabels,
37
+ labelPlacement = "above",
38
+ placeholder,
41
39
  type = "text",
42
40
  id: suppliedId,
43
41
  className,
@@ -49,19 +47,40 @@ export function TextField({
49
47
  const messages = Array.from(new Set(errors))
50
48
  const reveal = type === "password" && revealLabels
51
49
  return (
52
- <div className="flex flex-col gap-2">
53
- <label
54
- htmlFor={id}
55
- className="text-subheadline font-semibold"
50
+ <div className="not-typeset flex flex-col gap-2">
51
+ {labelPlacement === "above" && (
52
+ <label htmlFor={id} className="text-subheadline font-semibold">
53
+ {label}
54
+ </label>
55
+ )}
56
+ <div
57
+ className={cn(
58
+ "relative flex items-center gap-2 rounded-xl bg-elevated px-3",
59
+ labelPlacement === "floating"
60
+ ? "passui-floating-field"
61
+ : "border border-separator focus-within:ring-1 focus-within:ring-accent/40 has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-accent-text/70"
62
+ )}
56
63
  >
57
- {label}
58
- </label>
59
- <div className="flex items-center gap-2 rounded-xl border border-separator bg-elevated px-3 focus-within:ring-1 focus-within:ring-accent/40 has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-accent-text/70">
64
+ {labelPlacement === "floating" && (
65
+ <>
66
+ <fieldset aria-hidden="true" className="passui-field-outline">
67
+ <legend>
68
+ <span>{label}</span>
69
+ </legend>
70
+ </fieldset>
71
+ <label
72
+ htmlFor={id}
73
+ className={cn(
74
+ "passui-floating-label",
75
+ icon && "passui-floating-label-with-icon"
76
+ )}
77
+ >
78
+ {label}
79
+ </label>
80
+ </>
81
+ )}
60
82
  {icon && (
61
- <span
62
- aria-hidden
63
- className={fieldIconClasses}
64
- >
83
+ <span aria-hidden className={fieldIconClasses}>
65
84
  {icon}
66
85
  </span>
67
86
  )}
@@ -69,23 +88,25 @@ export function TextField({
69
88
  {...props}
70
89
  id={id}
71
90
  type={reveal && revealed ? "text" : type}
72
- aria-invalid={messages.length > 0}
91
+ placeholder={placeholder ?? (labelPlacement === "floating" ? " " : label)}
92
+ aria-invalid={messages.length > 0 || props["aria-invalid"]}
73
93
  aria-describedby={
74
- messages.length || description
75
- ? `${id}-description`
76
- : undefined
94
+ [
95
+ props["aria-describedby"],
96
+ (messages.length || description) && `${id}-description`,
97
+ ]
98
+ .filter(Boolean)
99
+ .join(" ") || undefined
77
100
  }
78
101
  className={cn(
79
102
  "h-11 w-full min-w-0 bg-transparent text-body text-label outline-none",
103
+ labelPlacement === "floating" && "h-12",
80
104
  "placeholder:text-label-tertiary disabled:opacity-40",
81
105
  className
82
106
  )}
83
107
  />
84
108
  {trailingIcon && (
85
- <span
86
- aria-hidden
87
- className={fieldIconClasses}
88
- >
109
+ <span aria-hidden className={fieldIconClasses}>
89
110
  {trailingIcon}
90
111
  </span>
91
112
  )}
@@ -97,17 +118,11 @@ export function TextField({
97
118
  // wider invisible area keeps a 44px target
98
119
  className="-mr-1.5 shrink-0 whitespace-nowrap [@media(pointer:coarse)]:before:absolute [@media(pointer:coarse)]:before:-inset-1.5 [@media(pointer:coarse)]:before:content-['']"
99
120
  aria-controls={id}
100
- aria-label={
101
- revealed
102
- ? revealLabels.hide
103
- : revealLabels.show
104
- }
121
+ aria-label={revealed ? revealLabels.hide : revealLabels.show}
105
122
  aria-pressed={revealed}
106
123
  onClick={() => setRevealed(!revealed)}
107
124
  >
108
- {revealed
109
- ? revealLabels.hide
110
- : revealLabels.show}
125
+ {revealed ? revealLabels.hide : revealLabels.show}
111
126
  </Button>
112
127
  )}
113
128
  {action}
@@ -115,19 +130,13 @@ export function TextField({
115
130
  {(messages.length > 0 || description) && (
116
131
  <div
117
132
  id={`${id}-description`}
118
- role={
119
- messages.length ? "alert" : undefined
120
- }
133
+ role={messages.length ? "alert" : undefined}
121
134
  className={cn(
122
135
  "text-footnote",
123
- messages.length
124
- ? "text-danger"
125
- : "text-label-secondary"
136
+ messages.length ? "text-danger" : "text-label-secondary"
126
137
  )}
127
138
  >
128
- {messages.length
129
- ? messages.join(". ")
130
- : description}
139
+ {messages.length ? messages.join(". ") : description}
131
140
  </div>
132
141
  )}
133
142
  </div>