@passui/react 0.1.17 → 0.1.19

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 (366) hide show
  1. package/README.md +102 -1
  2. package/dist/types/src/appearance/index.d.ts +2 -0
  3. package/dist/types/src/appearance/platform.d.ts +9 -0
  4. package/dist/types/src/appearance/theme.d.ts +71 -0
  5. package/dist/types/src/components/ambient/ambient.d.ts +12 -0
  6. package/dist/types/src/components/ambient/index.d.ts +1 -0
  7. package/dist/types/src/components/button/button-styles.d.ts +12 -0
  8. package/dist/types/src/components/button/button.d.ts +30 -0
  9. package/dist/types/src/components/button/icon-button.d.ts +10 -0
  10. package/dist/types/src/components/button/pending-spinner.d.ts +5 -0
  11. package/dist/types/src/components/button/use-pending-indicator.d.ts +2 -0
  12. package/dist/types/src/components/chip/chip.d.ts +7 -0
  13. package/dist/types/src/components/compact-date-picker/calendar-month.d.ts +25 -0
  14. package/dist/types/src/components/compact-date-picker/compact-date-picker.d.ts +27 -0
  15. package/dist/types/src/components/compact-time-picker/compact-time-picker.d.ts +26 -0
  16. package/dist/types/src/components/compact-time-picker/time-value.d.ts +18 -0
  17. package/dist/types/src/components/content-view/content-view.d.ts +48 -0
  18. package/dist/types/src/components/content-view/index.d.ts +1 -0
  19. package/dist/types/src/components/context-menu/conceal-menu-source.d.ts +2 -0
  20. package/dist/types/src/components/context-menu/context-menu-host.d.ts +2 -0
  21. package/dist/types/src/components/context-menu/context-menu-store.d.ts +57 -0
  22. package/dist/types/src/components/context-menu/menu-navigation.d.ts +6 -0
  23. package/dist/types/src/components/context-menu/menu-position.d.ts +21 -0
  24. package/dist/types/src/components/context-menu/menu-reveal.d.ts +22 -0
  25. package/dist/types/src/components/context-menu/use-context-menu.d.ts +14 -0
  26. package/dist/types/src/components/conversation/conversation.d.ts +43 -0
  27. package/dist/types/src/components/conversation/index.d.ts +1 -0
  28. package/dist/types/src/components/date-picker/date-picker.d.ts +16 -0
  29. package/dist/types/src/components/date-picker/date-value.d.ts +2 -0
  30. package/dist/types/src/components/dialog/dialog-host.d.ts +6 -0
  31. package/dist/types/src/components/dialog/dialog-store.d.ts +21 -0
  32. package/dist/types/src/components/dialog/dialog.d.ts +30 -0
  33. package/dist/types/src/components/dialog/index.d.ts +1 -0
  34. package/dist/types/src/components/disclosure-group/disclosure-group.d.ts +13 -0
  35. package/dist/types/src/components/divider/divider.d.ts +9 -0
  36. package/dist/types/src/components/inline-disclosure/inline-disclosure.d.ts +15 -0
  37. package/dist/types/src/components/labeled-content/labeled-content.d.ts +19 -0
  38. package/dist/types/src/components/locale-switcher/index.d.ts +1 -0
  39. package/dist/types/src/components/locale-switcher/locale-switcher.d.ts +10 -0
  40. package/dist/types/src/components/menu/menu.d.ts +16 -0
  41. package/dist/types/src/components/picker/picker-trigger.d.ts +2 -0
  42. package/dist/types/src/components/picker/picker.d.ts +37 -0
  43. package/dist/types/src/components/popover/popover-fit.d.ts +21 -0
  44. package/dist/types/src/components/popover/popover.d.ts +14 -0
  45. package/dist/types/src/components/profile-image/profile-image.d.ts +4 -0
  46. package/dist/types/src/components/progress-view/progress-view.d.ts +13 -0
  47. package/dist/types/src/components/search-field/search-field.d.ts +2 -0
  48. package/dist/types/src/components/search-list/search-list.d.ts +19 -0
  49. package/dist/types/src/components/section/section.d.ts +15 -0
  50. package/dist/types/src/components/secure-field/secure-field.d.ts +4 -0
  51. package/dist/types/src/components/segmented-control/segmented-control.d.ts +20 -0
  52. package/dist/types/src/components/sheet/modal-environment.d.ts +2 -0
  53. package/dist/types/src/components/sheet/sheet-portal.d.ts +5 -0
  54. package/dist/types/src/components/sheet/sheet.d.ts +21 -0
  55. package/dist/types/src/components/sheet/use-sheet-focus.d.ts +3 -0
  56. package/dist/types/src/components/sidebar/sidebar.d.ts +18 -0
  57. package/dist/types/src/components/slider/slider.d.ts +14 -0
  58. package/dist/types/src/components/stat-tile/index.d.ts +1 -0
  59. package/dist/types/src/components/stat-tile/stat-tile.d.ts +15 -0
  60. package/dist/types/src/components/status-indicator/status-indicator.d.ts +14 -0
  61. package/dist/types/src/components/stepper/stepper.d.ts +19 -0
  62. package/dist/types/src/components/swatch-picker/swatch-picker.d.ts +17 -0
  63. package/dist/types/src/components/tab-bar/tab-bar.d.ts +40 -0
  64. package/dist/types/src/components/tab-view/tab-view.d.ts +24 -0
  65. package/dist/types/src/components/table/table.d.ts +10 -0
  66. package/dist/types/src/components/text-editor/text-editor.d.ts +2 -0
  67. package/dist/types/src/components/text-field/text-field.d.ts +18 -0
  68. package/dist/types/src/components/toast/toast-store.d.ts +47 -0
  69. package/dist/types/src/components/toast/toaster.d.ts +10 -0
  70. package/dist/types/src/components/toggle/toggle.d.ts +17 -0
  71. package/dist/types/src/components/tooltip/tooltip-host.d.ts +6 -0
  72. package/dist/types/src/components/view-controller/index.d.ts +1 -0
  73. package/dist/types/src/components/view-controller/view-controller.d.ts +21 -0
  74. package/dist/types/src/hooks/scroll/minimize-decision.d.ts +2 -0
  75. package/dist/types/src/hooks/use-anchored-placement.d.ts +7 -0
  76. package/dist/types/src/hooks/use-dismiss.d.ts +9 -0
  77. package/dist/types/src/hooks/use-floating-dismiss.d.ts +3 -0
  78. package/dist/types/src/hooks/use-media-query.d.ts +21 -0
  79. package/dist/types/src/hooks/use-minimize-on-scroll.d.ts +6 -0
  80. package/dist/types/src/hooks/use-visual-viewport.d.ts +4 -0
  81. package/dist/types/src/hooks/viewport/types.d.ts +19 -0
  82. package/dist/types/src/hooks/viewport/viewport-metrics.d.ts +3 -0
  83. package/dist/types/src/icons/icons.d.ts +612 -0
  84. package/dist/types/src/index.d.ts +58 -0
  85. package/dist/types/src/lib/anchored-placement.d.ts +39 -0
  86. package/dist/types/src/lib/class-names.d.ts +2 -0
  87. package/dist/types/src/lib/clipboard.d.ts +6 -0
  88. package/dist/types/src/lib/date.d.ts +50 -0
  89. package/dist/types/src/lib/floating-layers.d.ts +8 -0
  90. package/dist/types/src/lib/haptics.d.ts +8 -0
  91. package/dist/types/src/lib/language.d.ts +4 -0
  92. package/dist/types/src/lib/range-value.d.ts +4 -0
  93. package/dist/types/src/lib/screen-edges.d.ts +12 -0
  94. package/dist/types/src/lib/shapes.d.ts +17 -0
  95. package/dist/types/src/motion/transitions.d.ts +97 -0
  96. package/dist/types/src/tokens.d.ts +1 -0
  97. package/package.json +192 -40
  98. package/src/appearance/platform.tsx +10 -47
  99. package/src/appearance/theme.tsx +42 -142
  100. package/src/components/ambient/ambient.tsx +2 -10
  101. package/src/components/button/button-styles.ts +13 -31
  102. package/src/components/button/button.tsx +19 -14
  103. package/src/components/button/icon-button.tsx +14 -56
  104. package/src/components/button/use-pending-indicator.ts +2 -7
  105. package/src/components/chip/chip.tsx +8 -13
  106. package/src/components/compact-date-picker/calendar-month.ts +13 -57
  107. package/src/components/compact-date-picker/compact-date-picker.tsx +44 -123
  108. package/src/components/compact-time-picker/compact-time-picker.tsx +46 -130
  109. package/src/components/compact-time-picker/time-value.ts +4 -16
  110. package/src/components/content-view/content-view.tsx +13 -56
  111. package/src/components/context-menu/conceal-menu-source.ts +1 -4
  112. package/src/components/context-menu/context-menu-host.tsx +125 -195
  113. package/src/components/context-menu/context-menu-store.ts +3 -11
  114. package/src/components/context-menu/menu-navigation.ts +29 -0
  115. package/src/components/context-menu/menu-position.ts +6 -27
  116. package/src/components/context-menu/menu-reveal.ts +13 -54
  117. package/src/components/context-menu/use-context-menu.ts +6 -30
  118. package/src/components/conversation/conversation.tsx +26 -72
  119. package/src/components/date-picker/date-picker.tsx +8 -37
  120. package/src/components/date-picker/date-value.ts +5 -30
  121. package/src/components/dialog/dialog-host.tsx +31 -76
  122. package/src/components/dialog/dialog-store.ts +1 -3
  123. package/src/components/dialog/dialog.tsx +23 -80
  124. package/src/components/disclosure-group/disclosure-group.tsx +70 -0
  125. package/src/components/divider/divider.tsx +31 -0
  126. package/src/components/inline-disclosure/inline-disclosure.tsx +49 -0
  127. package/src/components/labeled-content/labeled-content.tsx +24 -18
  128. package/src/components/locale-switcher/locale-switcher.tsx +20 -70
  129. package/src/components/menu/menu.tsx +68 -0
  130. package/src/components/picker/picker-trigger.ts +10 -0
  131. package/src/components/picker/picker.tsx +72 -203
  132. package/src/components/popover/popover-fit.ts +69 -0
  133. package/src/components/popover/popover.tsx +94 -77
  134. package/src/components/profile-image/profile-image.tsx +6 -28
  135. package/src/components/progress-view/progress-view.tsx +65 -0
  136. package/src/components/search-field/search-field.tsx +27 -25
  137. package/src/components/search-list/search-list.tsx +43 -69
  138. package/src/components/section/section.tsx +18 -17
  139. package/src/components/secure-field/secure-field.tsx +5 -7
  140. package/src/components/segmented-control/segmented-control.tsx +20 -29
  141. package/src/components/sheet/modal-environment.ts +16 -54
  142. package/src/components/sheet/sheet-portal.tsx +10 -42
  143. package/src/components/sheet/sheet.tsx +17 -25
  144. package/src/components/sheet/use-sheet-focus.ts +15 -51
  145. package/src/components/sidebar/sidebar.tsx +27 -30
  146. package/src/components/slider/slider.tsx +76 -0
  147. package/src/components/stat-tile/stat-tile.tsx +9 -30
  148. package/src/components/status-indicator/status-indicator.tsx +12 -19
  149. package/src/components/stepper/stepper.tsx +80 -0
  150. package/src/components/swatch-picker/swatch-picker.tsx +19 -15
  151. package/src/components/tab-bar/tab-bar.tsx +59 -59
  152. package/src/components/tab-view/tab-view.tsx +52 -57
  153. package/src/components/table/table.tsx +14 -62
  154. package/src/components/text-editor/text-editor.tsx +2 -12
  155. package/src/components/text-field/text-field.tsx +11 -40
  156. package/src/components/toast/toast-store.ts +9 -30
  157. package/src/components/toast/toaster.tsx +90 -104
  158. package/src/components/toggle/toggle.tsx +28 -24
  159. package/src/components/tooltip/tooltip-host.tsx +70 -67
  160. package/src/components/view-controller/view-controller.tsx +4 -21
  161. package/src/hooks/scroll/minimize-decision.ts +1 -5
  162. package/src/hooks/use-anchored-placement.ts +4 -14
  163. package/src/hooks/use-dismiss.ts +5 -23
  164. package/src/hooks/use-floating-dismiss.ts +28 -0
  165. package/src/hooks/use-media-query.ts +12 -31
  166. package/src/hooks/use-minimize-on-scroll.ts +10 -34
  167. package/src/hooks/use-visual-viewport.ts +5 -14
  168. package/src/hooks/viewport/viewport-metrics.ts +4 -16
  169. package/src/icons/icons.tsx +167 -121
  170. package/src/index.ts +9 -1
  171. package/src/lib/anchored-placement.ts +5 -15
  172. package/src/lib/class-names.ts +1 -2
  173. package/src/lib/clipboard.ts +14 -0
  174. package/src/lib/date.ts +4 -15
  175. package/src/lib/floating-layers.ts +18 -8
  176. package/src/lib/haptics.ts +1 -3
  177. package/src/lib/language.ts +2 -7
  178. package/src/lib/range-value.ts +32 -0
  179. package/src/lib/screen-edges.ts +2 -6
  180. package/src/lib/shapes.ts +5 -20
  181. package/src/motion/transitions.ts +18 -12
  182. package/src/components/ambient/ambient.docs.tsx +0 -68
  183. package/src/components/ambient/examples/ambient-images.tsx +0 -30
  184. package/src/components/ambient/examples/ambient-now-playing.tsx +0 -55
  185. package/src/components/ambient/examples/ambient-showcase.tsx +0 -33
  186. package/src/components/ambient/examples/ambient-usage.tsx +0 -19
  187. package/src/components/button/button.docs.tsx +0 -116
  188. package/src/components/button/examples/button-disabled.tsx +0 -19
  189. package/src/components/button/examples/button-icon.tsx +0 -39
  190. package/src/components/button/examples/button-link.tsx +0 -12
  191. package/src/components/button/examples/button-pending.tsx +0 -27
  192. package/src/components/button/examples/button-showcase.tsx +0 -115
  193. package/src/components/button/examples/button-sizes.tsx +0 -12
  194. package/src/components/button/examples/button-usage.tsx +0 -12
  195. package/src/components/button/examples/button-variants.tsx +0 -15
  196. package/src/components/button/examples/button-with-icon.tsx +0 -32
  197. package/src/components/button/examples/icon-button-player.tsx +0 -38
  198. package/src/components/button/examples/icon-button-showcase.tsx +0 -83
  199. package/src/components/button/examples/icon-button-usage.tsx +0 -11
  200. package/src/components/button/examples/icon-button-variants.tsx +0 -39
  201. package/src/components/button/icon-button.docs.tsx +0 -68
  202. package/src/components/chip/chip.docs.tsx +0 -37
  203. package/src/components/chip/examples/chip-in-rows.tsx +0 -19
  204. package/src/components/chip/examples/chip-showcase.tsx +0 -51
  205. package/src/components/chip/examples/chip-tones.tsx +0 -13
  206. package/src/components/chip/examples/chip-usage.tsx +0 -5
  207. package/src/components/compact-date-picker/compact-date-picker.docs.tsx +0 -81
  208. package/src/components/compact-date-picker/examples/compact-date-picker-showcase.tsx +0 -35
  209. package/src/components/compact-date-picker/examples/compact-date-picker-usage.tsx +0 -22
  210. package/src/components/compact-time-picker/compact-time-picker.docs.tsx +0 -80
  211. package/src/components/compact-time-picker/examples/compact-time-picker-showcase.tsx +0 -31
  212. package/src/components/compact-time-picker/examples/compact-time-picker-usage.tsx +0 -21
  213. package/src/components/content-view/content-view.docs.tsx +0 -61
  214. package/src/components/content-view/examples/content-view-header-action.tsx +0 -33
  215. package/src/components/content-view/examples/content-view-showcase.tsx +0 -65
  216. package/src/components/content-view/examples/content-view-stats.tsx +0 -35
  217. package/src/components/content-view/examples/content-view-usage.tsx +0 -14
  218. package/src/components/context-menu/context-menu.docs.tsx +0 -92
  219. package/src/components/context-menu/examples/context-menu-checked.tsx +0 -37
  220. package/src/components/context-menu/examples/context-menu-list.tsx +0 -85
  221. package/src/components/context-menu/examples/context-menu-showcase.tsx +0 -56
  222. package/src/components/context-menu/examples/context-menu-toolbar.tsx +0 -63
  223. package/src/components/context-menu/examples/context-menu-usage.tsx +0 -24
  224. package/src/components/conversation/conversation.docs.tsx +0 -88
  225. package/src/components/conversation/examples/conversation-composer.tsx +0 -36
  226. package/src/components/conversation/examples/conversation-days.tsx +0 -48
  227. package/src/components/conversation/examples/conversation-showcase.tsx +0 -71
  228. package/src/components/conversation/examples/conversation-usage.tsx +0 -28
  229. package/src/components/date-picker/date-picker.docs.tsx +0 -88
  230. package/src/components/date-picker/examples/date-picker-locales.tsx +0 -41
  231. package/src/components/date-picker/examples/date-picker-past-only.tsx +0 -29
  232. package/src/components/date-picker/examples/date-picker-showcase.tsx +0 -49
  233. package/src/components/date-picker/examples/date-picker-usage.tsx +0 -22
  234. package/src/components/dialog/dialog.docs.tsx +0 -114
  235. package/src/components/dialog/examples/dialog-confirm.tsx +0 -24
  236. package/src/components/dialog/examples/dialog-form.tsx +0 -46
  237. package/src/components/dialog/examples/dialog-inline.tsx +0 -48
  238. package/src/components/dialog/examples/dialog-showcase.tsx +0 -53
  239. package/src/components/dialog/examples/dialog-usage.tsx +0 -31
  240. package/src/components/labeled-content/examples/labeled-content-descriptions.tsx +0 -37
  241. package/src/components/labeled-content/examples/labeled-content-showcase.tsx +0 -54
  242. package/src/components/labeled-content/examples/labeled-content-usage.tsx +0 -22
  243. package/src/components/labeled-content/examples/labeled-content-values.tsx +0 -26
  244. package/src/components/labeled-content/examples/labeled-content-wide.tsx +0 -46
  245. package/src/components/labeled-content/labeled-content.docs.tsx +0 -69
  246. package/src/components/locale-switcher/examples/locale-switcher-native-names.tsx +0 -30
  247. package/src/components/locale-switcher/examples/locale-switcher-showcase.tsx +0 -46
  248. package/src/components/locale-switcher/examples/locale-switcher-translated-page.tsx +0 -35
  249. package/src/components/locale-switcher/examples/locale-switcher-usage.tsx +0 -20
  250. package/src/components/locale-switcher/locale-switcher.docs.tsx +0 -91
  251. package/src/components/picker/examples/picker-details.tsx +0 -44
  252. package/src/components/picker/examples/picker-searchable.tsx +0 -48
  253. package/src/components/picker/examples/picker-showcase.tsx +0 -66
  254. package/src/components/picker/examples/picker-usage.tsx +0 -20
  255. package/src/components/picker/picker.docs.tsx +0 -68
  256. package/src/components/popover/examples/popover-help.tsx +0 -57
  257. package/src/components/popover/examples/popover-menu.tsx +0 -51
  258. package/src/components/popover/examples/popover-showcase.tsx +0 -61
  259. package/src/components/popover/examples/popover-usage.tsx +0 -31
  260. package/src/components/popover/popover.docs.tsx +0 -84
  261. package/src/components/profile-image/examples/profile-image-fallbacks.tsx +0 -29
  262. package/src/components/profile-image/examples/profile-image-group.tsx +0 -34
  263. package/src/components/profile-image/examples/profile-image-showcase.tsx +0 -30
  264. package/src/components/profile-image/examples/profile-image-usage.tsx +0 -14
  265. package/src/components/profile-image/profile-image.docs.tsx +0 -81
  266. package/src/components/search-field/examples/search-field-filter.tsx +0 -53
  267. package/src/components/search-field/examples/search-field-showcase.tsx +0 -56
  268. package/src/components/search-field/examples/search-field-toolbar.tsx +0 -27
  269. package/src/components/search-field/examples/search-field-usage.tsx +0 -18
  270. package/src/components/search-field/search-field.docs.tsx +0 -58
  271. package/src/components/search-list/examples/search-list-dropdown.tsx +0 -53
  272. package/src/components/search-list/examples/search-list-groups.tsx +0 -64
  273. package/src/components/search-list/examples/search-list-showcase.tsx +0 -67
  274. package/src/components/search-list/examples/search-list-usage.tsx +0 -27
  275. package/src/components/search-list/search-list.docs.tsx +0 -87
  276. package/src/components/section/examples/section-actions.tsx +0 -35
  277. package/src/components/section/examples/section-groups.tsx +0 -41
  278. package/src/components/section/examples/section-showcase.tsx +0 -63
  279. package/src/components/section/examples/section-usage.tsx +0 -19
  280. package/src/components/section/section.docs.tsx +0 -51
  281. package/src/components/secure-field/examples/secure-field-new-password.tsx +0 -56
  282. package/src/components/secure-field/examples/secure-field-reveal.tsx +0 -20
  283. package/src/components/secure-field/examples/secure-field-showcase.tsx +0 -62
  284. package/src/components/secure-field/examples/secure-field-usage.tsx +0 -19
  285. package/src/components/secure-field/secure-field.docs.tsx +0 -72
  286. package/src/components/segmented-control/examples/segmented-control-overflow.tsx +0 -28
  287. package/src/components/segmented-control/examples/segmented-control-showcase.tsx +0 -59
  288. package/src/components/segmented-control/examples/segmented-control-usage.tsx +0 -20
  289. package/src/components/segmented-control/examples/segmented-control-views.tsx +0 -32
  290. package/src/components/segmented-control/segmented-control.docs.tsx +0 -61
  291. package/src/components/sheet/examples/sheet-choices.tsx +0 -58
  292. package/src/components/sheet/examples/sheet-share.tsx +0 -51
  293. package/src/components/sheet/examples/sheet-showcase.tsx +0 -74
  294. package/src/components/sheet/examples/sheet-usage.tsx +0 -32
  295. package/src/components/sheet/sheet.docs.tsx +0 -75
  296. package/src/components/sidebar/examples/sidebar-groups.tsx +0 -133
  297. package/src/components/sidebar/examples/sidebar-showcase.tsx +0 -123
  298. package/src/components/sidebar/examples/sidebar-unread.tsx +0 -66
  299. package/src/components/sidebar/examples/sidebar-usage.tsx +0 -52
  300. package/src/components/sidebar/sidebar.docs.tsx +0 -135
  301. package/src/components/stat-tile/examples/stat-tile-filters.tsx +0 -32
  302. package/src/components/stat-tile/examples/stat-tile-grid.tsx +0 -21
  303. package/src/components/stat-tile/examples/stat-tile-showcase.tsx +0 -52
  304. package/src/components/stat-tile/examples/stat-tile-usage.tsx +0 -13
  305. package/src/components/stat-tile/stat-tile.docs.tsx +0 -60
  306. package/src/components/status-indicator/examples/status-indicator-live.tsx +0 -34
  307. package/src/components/status-indicator/examples/status-indicator-showcase.tsx +0 -39
  308. package/src/components/status-indicator/examples/status-indicator-states.tsx +0 -17
  309. package/src/components/status-indicator/examples/status-indicator-usage.tsx +0 -9
  310. package/src/components/status-indicator/status-indicator.docs.tsx +0 -43
  311. package/src/components/swatch-picker/examples/swatch-picker-accents.tsx +0 -42
  312. package/src/components/swatch-picker/examples/swatch-picker-labels.tsx +0 -45
  313. package/src/components/swatch-picker/examples/swatch-picker-showcase.tsx +0 -70
  314. package/src/components/swatch-picker/examples/swatch-picker-usage.tsx +0 -39
  315. package/src/components/swatch-picker/swatch-picker.docs.tsx +0 -60
  316. package/src/components/tab-bar/examples/tab-bar-five-tabs.tsx +0 -66
  317. package/src/components/tab-bar/examples/tab-bar-minimize.tsx +0 -71
  318. package/src/components/tab-bar/examples/tab-bar-showcase.tsx +0 -82
  319. package/src/components/tab-bar/examples/tab-bar-usage.tsx +0 -54
  320. package/src/components/tab-bar/tab-bar.docs.tsx +0 -136
  321. package/src/components/tab-view/examples/tab-view-keyboard.tsx +0 -39
  322. package/src/components/tab-view/examples/tab-view-settings.tsx +0 -56
  323. package/src/components/tab-view/examples/tab-view-showcase.tsx +0 -53
  324. package/src/components/tab-view/examples/tab-view-usage.tsx +0 -23
  325. package/src/components/tab-view/tab-view.docs.tsx +0 -77
  326. package/src/components/table/examples/table-empty.tsx +0 -53
  327. package/src/components/table/examples/table-invoices.tsx +0 -102
  328. package/src/components/table/examples/table-selection.tsx +0 -150
  329. package/src/components/table/examples/table-showcase.tsx +0 -115
  330. package/src/components/table/examples/table-usage.tsx +0 -67
  331. package/src/components/table/examples/table-wide.tsx +0 -75
  332. package/src/components/table/table.docs.tsx +0 -131
  333. package/src/components/text-editor/examples/text-editor-comment.tsx +0 -48
  334. package/src/components/text-editor/examples/text-editor-count.tsx +0 -38
  335. package/src/components/text-editor/examples/text-editor-showcase.tsx +0 -58
  336. package/src/components/text-editor/examples/text-editor-usage.tsx +0 -25
  337. package/src/components/text-editor/text-editor.docs.tsx +0 -61
  338. package/src/components/text-field/examples/text-field-icons.tsx +0 -72
  339. package/src/components/text-field/examples/text-field-showcase.tsx +0 -50
  340. package/src/components/text-field/examples/text-field-usage.tsx +0 -18
  341. package/src/components/text-field/examples/text-field-validation.tsx +0 -27
  342. package/src/components/text-field/text-field.docs.tsx +0 -118
  343. package/src/components/toast/examples/toast-action.tsx +0 -32
  344. package/src/components/toast/examples/toast-promise.tsx +0 -45
  345. package/src/components/toast/examples/toast-showcase.tsx +0 -49
  346. package/src/components/toast/examples/toast-usage.tsx +0 -13
  347. package/src/components/toast/toast.docs.tsx +0 -79
  348. package/src/components/toggle/examples/toggle-checkboxes.tsx +0 -43
  349. package/src/components/toggle/examples/toggle-settings.tsx +0 -31
  350. package/src/components/toggle/examples/toggle-showcase.tsx +0 -59
  351. package/src/components/toggle/examples/toggle-usage.tsx +0 -13
  352. package/src/components/toggle/toggle.docs.tsx +0 -69
  353. package/src/components/tooltip/examples/tooltip-icon-buttons.tsx +0 -27
  354. package/src/components/tooltip/examples/tooltip-shortcuts.tsx +0 -38
  355. package/src/components/tooltip/examples/tooltip-showcase.tsx +0 -44
  356. package/src/components/tooltip/examples/tooltip-usage.tsx +0 -13
  357. package/src/components/tooltip/tooltip.docs.tsx +0 -56
  358. package/src/components/view-controller/examples/view-controller-action.tsx +0 -27
  359. package/src/components/view-controller/examples/view-controller-settings.tsx +0 -31
  360. package/src/components/view-controller/examples/view-controller-showcase.tsx +0 -45
  361. package/src/components/view-controller/examples/view-controller-usage.tsx +0 -19
  362. package/src/components/view-controller/view-controller.docs.tsx +0 -71
  363. package/src/docs/index.ts +0 -3
  364. package/src/docs/registry.ts +0 -113
  365. package/src/docs/snippet.ts +0 -17
  366. package/src/docs/types.ts +0 -180
@@ -1,11 +1,5 @@
1
- import { AnimatePresence, motion } from "motion/react"
2
- import {
3
- useEffect,
4
- useLayoutEffect,
5
- useRef,
6
- useState,
7
- useSyncExternalStore,
8
- } from "react"
1
+ import { AnimatePresence, motion, useReducedMotion } from "motion/react"
2
+ import { useEffect, useId, useLayoutEffect, useRef, useState, useSyncExternalStore } from "react"
9
3
  import { CheckIcon, CloseIcon } from "../../icons/icons"
10
4
  import { cn } from "../../lib/class-names"
11
5
  import { spring } from "../../motion/transitions"
@@ -19,7 +13,6 @@ import {
19
13
  } from "./toast-store"
20
14
 
21
15
  const PILL = 40
22
- const GOO_FILTER_ID = "nt-toast-goo"
23
16
  const EMPTY: Toast[] = []
24
17
  /** A little loose, so the body overshoots and settles like a drop of honey. */
25
18
  const BODY_SPRING = {
@@ -37,22 +30,22 @@ const BODY_SPRING = {
37
30
  */
38
31
  export function Toaster({
39
32
  className,
33
+ label = "Notifications",
40
34
  }: {
41
35
  className?: string
36
+ label?: string
42
37
  }) {
43
- const toasts = useSyncExternalStore(
44
- subscribeToasts,
45
- getToasts,
46
- () => EMPTY
47
- )
38
+ const toasts = useSyncExternalStore(subscribeToasts, getToasts, () => EMPTY)
39
+ const filterId = useId()
40
+ const reducedMotion = useReducedMotion()
48
41
  const [hovered, setHovered] = useState(false)
49
42
  const visible = toasts.slice(0, toastLimits.visible)
50
43
 
51
44
  return (
52
45
  <>
53
- <GooFilter />
46
+ <GooFilter id={filterId} />
54
47
  <section
55
- aria-label="Notifications"
48
+ aria-label={label}
56
49
  aria-live="polite"
57
50
  className={cn(
58
51
  "pointer-events-none fixed inset-x-0 top-[max(10px,env(safe-area-inset-top))] z-[60] flex justify-center px-3",
@@ -72,6 +65,8 @@ export function Toaster({
72
65
  index={index}
73
66
  expanded={hovered}
74
67
  paused={hovered}
68
+ filterId={filterId}
69
+ reducedMotion={Boolean(reducedMotion)}
75
70
  />
76
71
  ))}
77
72
  </AnimatePresence>
@@ -81,30 +76,19 @@ export function Toaster({
81
76
  )
82
77
  }
83
78
 
84
- function GooFilter() {
79
+ function GooFilter({ id }: { id: string }) {
85
80
  return (
86
- <svg
87
- aria-hidden="true"
88
- className="pointer-events-none absolute size-0"
89
- >
81
+ <svg aria-hidden="true" className="pointer-events-none absolute size-0">
90
82
  <defs>
91
- <filter id={GOO_FILTER_ID}>
92
- <feGaussianBlur
93
- in="SourceGraphic"
94
- stdDeviation="7"
95
- result="blur"
96
- />
83
+ <filter id={id}>
84
+ <feGaussianBlur in="SourceGraphic" stdDeviation="7" result="blur" />
97
85
  <feColorMatrix
98
86
  in="blur"
99
87
  mode="matrix"
100
88
  values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 22 -10"
101
89
  result="goo"
102
90
  />
103
- <feComposite
104
- in="SourceGraphic"
105
- in2="goo"
106
- operator="atop"
107
- />
91
+ <feComposite in="SourceGraphic" in2="goo" operator="atop" />
108
92
  </filter>
109
93
  </defs>
110
94
  </svg>
@@ -116,11 +100,15 @@ function ToastItem({
116
100
  index,
117
101
  expanded,
118
102
  paused,
103
+ filterId,
104
+ reducedMotion,
119
105
  }: {
120
106
  toast: Toast
121
107
  index: number
122
108
  expanded: boolean
123
109
  paused: boolean
110
+ filterId: string
111
+ reducedMotion: boolean
124
112
  }) {
125
113
  const content = useRef<HTMLDivElement>(null)
126
114
  const [size, setSize] = useState({
@@ -131,9 +119,9 @@ function ToastItem({
131
119
 
132
120
  // The body flows out of the pill a beat after it lands.
133
121
  useEffect(() => {
134
- const timer = setTimeout(() => setOpen(true), 140)
122
+ const timer = setTimeout(() => setOpen(true), reducedMotion ? 0 : 140)
135
123
  return () => clearTimeout(timer)
136
- }, [])
124
+ }, [reducedMotion])
137
125
 
138
126
  useLayoutEffect(() => {
139
127
  const element = content.current
@@ -151,10 +139,7 @@ function ToastItem({
151
139
 
152
140
  useEffect(() => {
153
141
  if (toast.duration === null || paused) return
154
- const timer = setTimeout(
155
- () => toastApi.dismiss(toast.id),
156
- toast.duration
157
- )
142
+ const timer = setTimeout(() => toastApi.dismiss(toast.id), toast.duration)
158
143
  return () => clearTimeout(timer)
159
144
  }, [toast.id, toast.duration, paused])
160
145
 
@@ -165,33 +150,31 @@ function ToastItem({
165
150
 
166
151
  return (
167
152
  <motion.li
168
- layout
153
+ layout={!reducedMotion}
169
154
  className="pointer-events-none absolute inset-x-0 top-0 flex justify-center"
170
155
  style={{ zIndex: 10 - index }}
171
- initial={{ opacity: 0, y: -24, scale: 0.6 }}
156
+ initial={reducedMotion ? false : { opacity: 0, y: -24, scale: 0.6 }}
172
157
  animate={{
173
158
  opacity: stacked ? 1 - index * 0.25 : 1,
174
- y: stacked
175
- ? index * 9
176
- : index * (PILL + 14) + index * 6,
159
+ y: stacked ? index * 9 : index * (PILL + 14) + index * 6,
177
160
  scale: stacked ? 1 - index * 0.05 : 1,
178
161
  }}
179
- exit={{
180
- opacity: 0,
181
- y: -18,
182
- scale: 0.6,
183
- transition: spring.snappy,
184
- }}
185
- transition={spring.bouncy}
186
- drag="y"
162
+ exit={
163
+ reducedMotion
164
+ ? { opacity: 0 }
165
+ : {
166
+ opacity: 0,
167
+ y: -18,
168
+ scale: 0.6,
169
+ transition: spring.snappy,
170
+ }
171
+ }
172
+ transition={reducedMotion ? { duration: 0 } : spring.bouncy}
173
+ drag={reducedMotion ? false : "y"}
187
174
  dragConstraints={{ top: 0, bottom: 0 }}
188
175
  dragElastic={{ top: 0.6, bottom: 0.1 }}
189
176
  onDragEnd={(_, info) => {
190
- if (
191
- info.offset.y < -30 ||
192
- info.velocity.y < -300
193
- )
194
- toastApi.dismiss(toast.id)
177
+ if (info.offset.y < -30 || info.velocity.y < -300) toastApi.dismiss(toast.id)
195
178
  }}
196
179
  >
197
180
  <motion.div
@@ -199,21 +182,21 @@ function ToastItem({
199
182
  className="pointer-events-auto relative"
200
183
  initial={{ width: PILL, height: PILL }}
201
184
  animate={{ width, height }}
202
- transition={BODY_SPRING}
185
+ transition={reducedMotion ? { duration: 0 } : BODY_SPRING}
203
186
  >
204
187
  {/* Shapes, under the goo filter; padded so the blur isn't clipped. */}
205
188
  <div
206
189
  aria-hidden="true"
207
190
  className="absolute -inset-3"
208
191
  style={{
209
- filter: `url(#${GOO_FILTER_ID})`,
192
+ filter: reducedMotion ? undefined : `url(#${filterId})`,
210
193
  }}
211
194
  >
212
195
  <motion.span
213
196
  className="absolute top-3 left-3 rounded-full bg-inverse shadow-xl"
214
197
  style={{ width: PILL, height: PILL }}
215
198
  animate={{ scale: open ? 1 : 1.06 }}
216
- transition={spring.bouncy}
199
+ transition={reducedMotion ? { duration: 0 } : spring.bouncy}
217
200
  />
218
201
  <motion.span
219
202
  className="absolute top-3 left-3 bg-inverse"
@@ -225,13 +208,9 @@ function ToastItem({
225
208
  animate={{
226
209
  width,
227
210
  height,
228
- borderRadius: Math.min(
229
- PILL / 2,
230
- height / 2,
231
- 22
232
- ),
211
+ borderRadius: Math.min(PILL / 2, height / 2, 22),
233
212
  }}
234
- transition={BODY_SPRING}
213
+ transition={reducedMotion ? { duration: 0 } : BODY_SPRING}
235
214
  />
236
215
  </div>
237
216
 
@@ -241,36 +220,45 @@ function ToastItem({
241
220
  className="absolute top-0 left-0 flex w-max max-w-[min(420px,calc(100vw-24px))] items-start gap-2.5 py-[10px] pr-4 pl-[10px] text-on-inverse"
242
221
  style={{ minHeight: PILL }}
243
222
  animate={{ opacity: open ? 1 : 0 }}
244
- transition={{
245
- duration: open ? 0.22 : 0.1,
246
- delay: open ? 0.08 : 0,
247
- }}
223
+ transition={
224
+ reducedMotion
225
+ ? { duration: 0 }
226
+ : {
227
+ duration: open ? 0.22 : 0.1,
228
+ delay: open ? 0.08 : 0,
229
+ }
230
+ }
248
231
  >
249
- <ToneIcon tone={toast.tone} />
232
+ <ToneIcon tone={toast.tone} reducedMotion={reducedMotion} />
250
233
  <div className="flex min-w-0 flex-col py-px">
251
- <AnimatePresence
252
- mode="popLayout"
253
- initial={false}
254
- >
234
+ <AnimatePresence mode="popLayout" initial={false}>
255
235
  <motion.span
256
236
  key={toast.title}
257
237
  className="text-subheadline leading-5 font-semibold"
258
- initial={{
259
- opacity: 0,
260
- y: 6,
261
- filter: "blur(4px)",
262
- }}
238
+ initial={
239
+ reducedMotion
240
+ ? false
241
+ : {
242
+ opacity: 0,
243
+ y: 6,
244
+ filter: "blur(4px)",
245
+ }
246
+ }
263
247
  animate={{
264
248
  opacity: 1,
265
249
  y: 0,
266
250
  filter: "blur(0px)",
267
251
  }}
268
- exit={{
269
- opacity: 0,
270
- y: -6,
271
- filter: "blur(4px)",
272
- }}
273
- transition={spring.snappy}
252
+ exit={
253
+ reducedMotion
254
+ ? { opacity: 0 }
255
+ : {
256
+ opacity: 0,
257
+ y: -6,
258
+ filter: "blur(4px)",
259
+ }
260
+ }
261
+ transition={reducedMotion ? { duration: 0 } : spring.snappy}
274
262
  >
275
263
  {toast.title}
276
264
  </motion.span>
@@ -306,7 +294,7 @@ const toneColors: Record<ToastTone, string> = {
306
294
  loading: "bg-on-inverse/15 text-on-inverse",
307
295
  }
308
296
 
309
- function ToneIcon({ tone }: { tone: ToastTone }) {
297
+ function ToneIcon({ tone, reducedMotion }: { tone: ToastTone; reducedMotion: boolean }) {
310
298
  return (
311
299
  <AnimatePresence mode="popLayout" initial={false}>
312
300
  <motion.span
@@ -315,37 +303,35 @@ function ToneIcon({ tone }: { tone: ToastTone }) {
315
303
  "flex size-5 shrink-0 items-center justify-center rounded-full",
316
304
  toneColors[tone]
317
305
  )}
318
- initial={{
319
- scale: 0.3,
320
- opacity: 0,
321
- rotate: -40,
322
- }}
306
+ initial={
307
+ reducedMotion
308
+ ? false
309
+ : {
310
+ scale: 0.3,
311
+ opacity: 0,
312
+ rotate: -40,
313
+ }
314
+ }
323
315
  animate={{ scale: 1, opacity: 1, rotate: 0 }}
324
316
  exit={{ scale: 0.3, opacity: 0 }}
325
- transition={spring.bouncy}
317
+ transition={reducedMotion ? { duration: 0 } : spring.bouncy}
326
318
  >
327
- {tone === "success" && (
328
- <CheckIcon size={13} strokeWidth={3} />
329
- )}
330
- {tone === "error" && (
331
- <CloseIcon size={12} strokeWidth={3} />
332
- )}
319
+ {tone === "success" && <CheckIcon size={13} strokeWidth={3} />}
320
+ {tone === "error" && <CloseIcon size={12} strokeWidth={3} />}
333
321
  {/* The full stop from the Notables mark. */}
334
- {tone === "neutral" && (
335
- <span className="size-2 rounded-full bg-[#EE8A2A]" />
336
- )}
337
- {tone === "loading" && <Spinner />}
322
+ {tone === "neutral" && <span className="size-2 rounded-full bg-[#EE8A2A]" />}
323
+ {tone === "loading" && <Spinner reducedMotion={reducedMotion} />}
338
324
  </motion.span>
339
325
  </AnimatePresence>
340
326
  )
341
327
  }
342
328
 
343
- function Spinner() {
329
+ function Spinner({ reducedMotion }: { reducedMotion: boolean }) {
344
330
  return (
345
331
  <motion.svg
346
332
  viewBox="0 0 20 20"
347
333
  className="size-4"
348
- animate={{ rotate: 360 }}
334
+ animate={reducedMotion ? undefined : { rotate: 360 }}
349
335
  transition={{
350
336
  repeat: Number.POSITIVE_INFINITY,
351
337
  duration: 0.8,
@@ -1,4 +1,4 @@
1
- import { motion } from "motion/react"
1
+ import { motion, useReducedMotion } from "motion/react"
2
2
  import { useEffect, useRef } from "react"
3
3
  import { cn } from "../../lib/class-names"
4
4
  import { haptic } from "../../lib/haptics"
@@ -6,6 +6,22 @@ import { spring } from "../../motion/transitions"
6
6
 
7
7
  export type ToggleStyle = "switch" | "checkbox"
8
8
 
9
+ export interface ToggleProps {
10
+ /** Current on or off state. */
11
+ checked: boolean
12
+ /** Called with the next checked state. */
13
+ onChange: (checked: boolean) => void
14
+ /** Accessible name, including when the visible label is hidden. */
15
+ label: string
16
+ disabled?: boolean
17
+ /** `switch` for a setting, `checkbox` for a selection. @default "switch" */
18
+ style?: ToggleStyle
19
+ /** Reports a mixed selection to assistive technology. @default false */
20
+ mixed?: boolean
21
+ /** Keeps the accessible name while hiding the visible label. @default false */
22
+ labelHidden?: boolean
23
+ }
24
+
9
25
  export function Toggle({
10
26
  checked,
11
27
  onChange,
@@ -14,17 +30,9 @@ export function Toggle({
14
30
  style = "switch",
15
31
  mixed = false,
16
32
  labelHidden = false,
17
- }: {
18
- checked: boolean
19
- onChange: (checked: boolean) => void
20
- label: string
21
- /** Shown but not yet usable, as iOS dims a switch it can't change. */
22
- disabled?: boolean
23
- style?: ToggleStyle
24
- mixed?: boolean
25
- labelHidden?: boolean
26
- }) {
33
+ }: ToggleProps) {
27
34
  const input = useRef<HTMLInputElement>(null)
35
+ const reducedMotion = useReducedMotion()
28
36
  useEffect(() => {
29
37
  if (input.current) input.current.indeterminate = mixed
30
38
  }, [mixed])
@@ -37,21 +45,13 @@ export function Toggle({
37
45
  aria-checked={mixed ? "mixed" : checked}
38
46
  checked={checked}
39
47
  disabled={disabled}
40
- onChange={(event) =>
41
- onChange(event.target.checked)
42
- }
48
+ onChange={(event) => onChange(event.target.checked)}
43
49
  className={cn(
44
50
  "size-5 accent-accent",
45
51
  "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent-text disabled:opacity-40"
46
52
  )}
47
53
  />
48
- <span
49
- className={
50
- labelHidden ? "sr-only" : undefined
51
- }
52
- >
53
- {label}
54
- </span>
54
+ <span className={labelHidden ? "sr-only" : undefined}>{label}</span>
55
55
  </label>
56
56
  )
57
57
  }
@@ -76,9 +76,13 @@ export function Toggle({
76
76
  >
77
77
  {/* The thumb stretches while pressed, as on iOS. */}
78
78
  <motion.span
79
- layout
80
- transition={spring.snappy}
81
- className="h-[26px] w-[26px] rounded-full bg-white shadow-[0_0_0_0.5px_rgb(0_0_0/0.04),0_2px_4px_rgb(0_0_0/0.16),0_3px_8px_rgb(0_0_0/0.10)] transition-[width] duration-fast group-active/switch:w-[32px]"
79
+ layout={!reducedMotion}
80
+ transition={reducedMotion ? { duration: 0 } : spring.snappy}
81
+ className={cn(
82
+ "h-[26px] w-[26px] rounded-full bg-white shadow-[0_0_0_0.5px_rgb(0_0_0/0.04),0_2px_4px_rgb(0_0_0/0.16),0_3px_8px_rgb(0_0_0/0.10)]",
83
+ !reducedMotion &&
84
+ "transition-[width] duration-fast group-active/switch:w-[32px]"
85
+ )}
82
86
  />
83
87
  </button>
84
88
  )
@@ -1,6 +1,6 @@
1
- import { AnimatePresence, motion } from "motion/react"
1
+ import { AnimatePresence, motion, useReducedMotion } from "motion/react"
2
2
  import { spring } from "../../motion/transitions"
3
- import { useEffect, useState } from "react"
3
+ import { useEffect, useId, useState } from "react"
4
4
 
5
5
  interface Tip {
6
6
  text: string
@@ -22,30 +22,33 @@ const MARGIN = 8
22
22
  */
23
23
  export function TooltipHost() {
24
24
  const [tip, setTip] = useState<Tip | null>(null)
25
+ const tooltipId = useId()
26
+ const reducedMotion = useReducedMotion()
25
27
 
26
28
  useEffect(() => {
27
- if (
28
- !window.matchMedia(
29
- "(hover: hover) and (pointer: fine)"
30
- ).matches
31
- )
32
- return
29
+ const canHover = window.matchMedia("(hover: hover) and (pointer: fine)").matches
33
30
  let timer: ReturnType<typeof setTimeout> | undefined
34
31
  let current: Element | null = null
35
32
  let lastShown = 0
33
+ let described: Element | null = null
34
+ let previousDescription: string | null = null
35
+
36
+ const restoreDescription = () => {
37
+ if (!described) return
38
+ if (previousDescription === null) described.removeAttribute("aria-describedby")
39
+ else described.setAttribute("aria-describedby", previousDescription)
40
+ described = null
41
+ }
36
42
 
37
43
  const show = (element: Element) => {
38
44
  const text = element.getAttribute("data-tooltip")
39
45
  if (!text) return
40
46
  const rect = element.getBoundingClientRect()
41
- const above =
42
- rect.bottom + 40 > window.innerHeight
47
+ const above = rect.bottom + 40 > window.innerHeight
43
48
  setTip({
44
49
  text,
45
50
  x: rect.left + rect.width / 2,
46
- y: above
47
- ? rect.top - MARGIN
48
- : rect.bottom + MARGIN,
51
+ y: above ? rect.top - MARGIN : rect.bottom + MARGIN,
49
52
  above,
50
53
  })
51
54
  lastShown = Date.now()
@@ -54,13 +57,12 @@ export function TooltipHost() {
54
57
  clearTimeout(timer)
55
58
  if (current) lastShown = Date.now()
56
59
  current = null
60
+ restoreDescription()
57
61
  setTip(null)
58
62
  }
59
63
  const onOver = (event: PointerEvent) => {
60
- const element =
61
- (event.target as Element | null)?.closest?.(
62
- "[data-tooltip]"
63
- ) ?? null
64
+ if (!canHover) return
65
+ const element = (event.target as Element | null)?.closest?.("[data-tooltip]") ?? null
64
66
  if (element === current) return
65
67
  clearTimeout(timer)
66
68
  current = element
@@ -72,80 +74,81 @@ export function TooltipHost() {
72
74
  if (warm) show(element)
73
75
  else {
74
76
  setTip(null)
75
- timer = setTimeout(
76
- () =>
77
- current === element && show(element),
78
- DELAY
79
- )
77
+ timer = setTimeout(() => current === element && show(element), DELAY)
80
78
  }
81
79
  }
80
+ const onFocus = (event: FocusEvent) => {
81
+ const element = (event.target as Element | null)?.closest?.("[data-tooltip]") ?? null
82
+ if (!element) return
83
+ hide()
84
+ current = element
85
+ described = element
86
+ previousDescription = element.getAttribute("aria-describedby")
87
+ element.setAttribute(
88
+ "aria-describedby",
89
+ [previousDescription, tooltipId].filter(Boolean).join(" ")
90
+ )
91
+ show(element)
92
+ }
93
+ const onBlur = (event: FocusEvent) => {
94
+ if (described && !described.contains(event.relatedTarget as Node | null)) hide()
95
+ }
82
96
 
83
- window.document.addEventListener(
84
- "pointerover",
85
- onOver
86
- )
87
- window.document.addEventListener(
88
- "pointerdown",
89
- hide,
90
- true
91
- )
92
- window.document.addEventListener(
93
- "keydown",
94
- hide,
95
- true
96
- )
97
+ window.document.addEventListener("pointerover", onOver)
98
+ window.document.addEventListener("focusin", onFocus)
99
+ window.document.addEventListener("focusout", onBlur)
100
+ window.document.addEventListener("pointerdown", hide, true)
101
+ window.document.addEventListener("keydown", hide, true)
97
102
  window.addEventListener("scroll", hide, true)
98
103
  window.addEventListener("blur", hide)
99
104
  return () => {
100
105
  clearTimeout(timer)
101
- window.document.removeEventListener(
102
- "pointerover",
103
- onOver
104
- )
105
- window.document.removeEventListener(
106
- "pointerdown",
107
- hide,
108
- true
109
- )
110
- window.document.removeEventListener(
111
- "keydown",
112
- hide,
113
- true
114
- )
106
+ restoreDescription()
107
+ window.document.removeEventListener("pointerover", onOver)
108
+ window.document.removeEventListener("focusin", onFocus)
109
+ window.document.removeEventListener("focusout", onBlur)
110
+ window.document.removeEventListener("pointerdown", hide, true)
111
+ window.document.removeEventListener("keydown", hide, true)
115
112
  window.removeEventListener("scroll", hide, true)
116
113
  window.removeEventListener("blur", hide)
117
114
  }
118
- }, [])
115
+ }, [tooltipId])
119
116
 
120
117
  return (
121
118
  <AnimatePresence>
122
119
  {tip && (
123
120
  <motion.div
121
+ id={tooltipId}
124
122
  key={tip.text + tip.x}
125
123
  role="tooltip"
126
124
  className="pointer-events-none fixed z-[80] max-w-[240px] rounded-md bg-inverse px-2.5 py-1.5 text-center text-caption leading-tight font-medium text-on-inverse shadow-lg"
127
125
  style={{
128
- left: Math.min(
129
- Math.max(tip.x, 128),
130
- window.innerWidth - 128
131
- ),
126
+ left: Math.min(Math.max(tip.x, 128), window.innerWidth - 128),
132
127
  top: tip.y,
133
128
  translateX: "-50%",
134
129
  translateY: tip.above ? "-100%" : 0,
135
130
  }}
136
- initial={{
137
- opacity: 0,
138
- scale: 0.92,
139
- y: tip.above ? 4 : -4,
140
- }}
131
+ initial={
132
+ reducedMotion
133
+ ? false
134
+ : {
135
+ opacity: 0,
136
+ scale: 0.92,
137
+ y: tip.above ? 4 : -4,
138
+ }
139
+ }
141
140
  animate={{ opacity: 1, scale: 1, y: 0 }}
142
- exit={{
143
- opacity: 0,
144
- scale: 0.96,
145
- y: tip.above ? 2 : -2,
146
- transition: spring.snappy,
147
- }}
148
- transition={spring.snappy}
141
+ exit={
142
+ reducedMotion
143
+ ? { opacity: 0 }
144
+ : {
145
+ opacity: 0,
146
+ scale: 0.96,
147
+ y: tip.above ? 2 : -2,
148
+ transition: spring.snappy,
149
+ }
150
+ }
151
+ transition={reducedMotion ? { duration: 0 } : spring.snappy}
149
152
  >
150
153
  {tip.text}
151
154
  </motion.div>