pixelize-native-library 1.2.0 → 1.2.1

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 (353) hide show
  1. package/lib/module/core/MODULE.md +2 -1
  2. package/lib/module/core/gradient/AccentGradientFill.js +80 -0
  3. package/lib/module/core/gradient/darkenHex.js +13 -0
  4. package/lib/module/core/gradient/gradientStops.js +27 -0
  5. package/lib/module/core/gradient/index.js +7 -0
  6. package/lib/module/core/gradient/withAlpha.js +19 -0
  7. package/lib/module/core/haptics/MODULE.md +4 -0
  8. package/lib/module/core/haptics/context.js +7 -0
  9. package/lib/module/core/haptics/haptics.js +17 -0
  10. package/lib/module/core/haptics/index.js +6 -0
  11. package/lib/module/core/haptics/useHaptics.js +73 -0
  12. package/lib/module/core/icon/MODULE.md +16 -9
  13. package/lib/module/core/icon/icons/trending-up.js +10 -0
  14. package/lib/module/core/icon/resolve.js +2 -0
  15. package/lib/module/core/media/expoImage.js +6 -0
  16. package/lib/module/core/motion/MODULE.md +12 -12
  17. package/lib/module/core/motion/config.js +4 -1
  18. package/lib/module/core/motion/index.js +2 -1
  19. package/lib/module/core/motion/usePressState.js +145 -0
  20. package/lib/module/core/style/index.js +1 -0
  21. package/lib/module/core/style/radius.js +4 -0
  22. package/lib/module/index.js +1 -0
  23. package/lib/module/modules/accordion/Accordion.js +69 -49
  24. package/lib/module/modules/accordion/Accordion.variants.js +4 -3
  25. package/lib/module/modules/accordion/MODULE.md +2 -1
  26. package/lib/module/modules/alert-dialog/AlertDialog.js +6 -5
  27. package/lib/module/modules/alert-dialog/AlertDialog.variants.js +4 -0
  28. package/lib/module/modules/app-bar/AppBar.js +6 -4
  29. package/lib/module/modules/app-bar/AppBar.variants.js +1 -2
  30. package/lib/module/modules/avatar/Avatar.js +7 -1
  31. package/lib/module/modules/avatar/Avatar.variants.js +1 -1
  32. package/lib/module/modules/avatar/MODULE.md +2 -2
  33. package/lib/module/modules/avatar-group/AvatarGroup.js +10 -6
  34. package/lib/module/modules/avatar-group/AvatarGroup.variants.js +23 -0
  35. package/lib/module/modules/avatar-group/MODULE.md +16 -0
  36. package/lib/module/modules/badge/Badge.js +11 -5
  37. package/lib/module/modules/badge/Badge.variants.js +2 -1
  38. package/lib/module/modules/badge/MODULE.md +5 -5
  39. package/lib/module/modules/banner/Banner.js +106 -60
  40. package/lib/module/modules/banner/Banner.variants.js +2 -2
  41. package/lib/module/modules/banner/MODULE.md +7 -2
  42. package/lib/module/modules/bottom-nav/BottomNav.js +6 -3
  43. package/lib/module/modules/bottom-nav/BottomNav.variants.js +9 -10
  44. package/lib/module/modules/bottom-nav/BottomNavOverflowSheet.js +28 -4
  45. package/lib/module/modules/bottom-nav/BottomNavTab.js +28 -4
  46. package/lib/module/modules/bottom-nav/MODULE.md +10 -1
  47. package/lib/module/modules/bottom-sheet/BottomSheet.js +20 -7
  48. package/lib/module/modules/bottom-sheet/BottomSheet.variants.js +15 -5
  49. package/lib/module/modules/bottom-sheet/MODULE.md +13 -2
  50. package/lib/module/modules/button/Button.js +87 -101
  51. package/lib/module/modules/button/Button.variants.js +8 -7
  52. package/lib/module/modules/button/MODULE.md +6 -0
  53. package/lib/module/modules/button-group/ButtonGroup.js +36 -37
  54. package/lib/module/modules/button-group/ButtonGroup.variants.js +21 -46
  55. package/lib/module/modules/button-group/MODULE.md +25 -30
  56. package/lib/module/modules/card/Card.js +117 -19
  57. package/lib/module/modules/card/Card.variants.js +1 -0
  58. package/lib/module/modules/card/MODULE.md +13 -10
  59. package/lib/module/modules/charts/BarChart.js +29 -14
  60. package/lib/module/modules/charts/BarList.js +31 -18
  61. package/lib/module/modules/charts/Charts.variants.js +66 -2
  62. package/lib/module/modules/charts/DonutChart.js +9 -4
  63. package/lib/module/modules/charts/LineChart.js +5 -3
  64. package/lib/module/modules/charts/MODULE.md +24 -11
  65. package/lib/module/modules/charts/PieChart.js +13 -4
  66. package/lib/module/modules/charts/Sparkline.js +4 -2
  67. package/lib/module/modules/checkbox/Checkbox.js +10 -2
  68. package/lib/module/modules/checkbox/MODULE.md +5 -0
  69. package/lib/module/modules/chip/Chip.js +83 -38
  70. package/lib/module/modules/chip/Chip.variants.js +15 -3
  71. package/lib/module/modules/chip/MODULE.md +6 -4
  72. package/lib/module/modules/combobox/Combobox.js +93 -57
  73. package/lib/module/modules/combobox/Combobox.variants.js +22 -7
  74. package/lib/module/modules/combobox/MODULE.md +14 -4
  75. package/lib/module/modules/composer/Composer.js +9 -2
  76. package/lib/module/modules/composer/Composer.variants.js +2 -0
  77. package/lib/module/modules/composer/MODULE.md +5 -0
  78. package/lib/module/modules/copy-button/CopyButton.js +22 -4
  79. package/lib/module/modules/copy-button/CopyButton.variants.js +4 -2
  80. package/lib/module/modules/copy-button/MODULE.md +5 -0
  81. package/lib/module/modules/data-table/DataTable.js +28 -9
  82. package/lib/module/modules/data-table/DataTable.variants.js +3 -2
  83. package/lib/module/modules/data-table/MODULE.md +1 -0
  84. package/lib/module/modules/date-picker/Calendar.js +75 -29
  85. package/lib/module/modules/date-picker/DatePicker.variants.js +24 -9
  86. package/lib/module/modules/date-picker/MODULE.md +25 -4
  87. package/lib/module/modules/date-picker/PickerField.js +13 -4
  88. package/lib/module/modules/date-picker/PickerShell.js +2 -0
  89. package/lib/module/modules/date-picker/TimePicker.js +13 -18
  90. package/lib/module/modules/divider/Divider.variants.js +6 -5
  91. package/lib/module/modules/divider/MODULE.md +2 -0
  92. package/lib/module/modules/drawer/Drawer.js +20 -8
  93. package/lib/module/modules/drawer/Drawer.variants.js +4 -4
  94. package/lib/module/modules/drawer/MODULE.md +3 -0
  95. package/lib/module/modules/empty-state/EmptyState.js +18 -29
  96. package/lib/module/modules/empty-state/EmptyState.variants.js +7 -0
  97. package/lib/module/modules/empty-state/MODULE.md +1 -0
  98. package/lib/module/modules/fab/Fab.js +41 -61
  99. package/lib/module/modules/fab/Fab.variants.js +15 -1
  100. package/lib/module/modules/fab/FabGroup.js +84 -57
  101. package/lib/module/modules/fab/MODULE.md +19 -6
  102. package/lib/module/modules/file-grid/FileGrid.js +30 -16
  103. package/lib/module/modules/file-grid/FileGrid.variants.js +2 -2
  104. package/lib/module/modules/file-grid/MODULE.md +3 -1
  105. package/lib/module/modules/file-upload/FileUpload.variants.js +3 -1
  106. package/lib/module/modules/file-upload/MODULE.md +2 -0
  107. package/lib/module/modules/filter-sheet/FilterChip.js +11 -3
  108. package/lib/module/modules/filter-sheet/FilterSheetBody.js +15 -3
  109. package/lib/module/modules/filter-sheet/MODULE.md +9 -0
  110. package/lib/module/modules/folder-row/FolderRow.js +29 -17
  111. package/lib/module/modules/folder-row/FolderRow.variants.js +4 -2
  112. package/lib/module/modules/folder-row/MODULE.md +2 -1
  113. package/lib/module/modules/gantt/Gantt.js +30 -9
  114. package/lib/module/modules/gantt/Gantt.variants.js +36 -0
  115. package/lib/module/modules/gantt/MODULE.md +11 -1
  116. package/lib/module/modules/image-viewer/ImageViewer.js +35 -5
  117. package/lib/module/modules/image-viewer/MODULE.md +6 -0
  118. package/lib/module/modules/input/Input.js +20 -7
  119. package/lib/module/modules/input/Input.variants.js +8 -7
  120. package/lib/module/modules/input/MODULE.md +2 -0
  121. package/lib/module/modules/list-item/ListItem.js +48 -26
  122. package/lib/module/modules/list-item/ListItem.variants.js +11 -2
  123. package/lib/module/modules/list-item/MODULE.md +2 -3
  124. package/lib/module/modules/markdown/MODULE.md +8 -1
  125. package/lib/module/modules/markdown/Markdown.js +57 -22
  126. package/lib/module/modules/markdown/Markdown.variants.js +2 -1
  127. package/lib/module/modules/menu/MODULE.md +11 -0
  128. package/lib/module/modules/menu/Menu.js +99 -40
  129. package/lib/module/modules/menu/Menu.variants.js +3 -3
  130. package/lib/module/modules/message-bubble/MODULE.md +4 -1
  131. package/lib/module/modules/message-bubble/MessageBubble.js +4 -5
  132. package/lib/module/modules/message-bubble/MessageBubble.variants.js +5 -5
  133. package/lib/module/modules/modal/MODULE.md +11 -0
  134. package/lib/module/modules/modal/Modal.js +87 -35
  135. package/lib/module/modules/modal/Modal.variants.js +2 -2
  136. package/lib/module/modules/more-items/MODULE.md +5 -0
  137. package/lib/module/modules/more-items/MoreItems.js +7 -1
  138. package/lib/module/modules/more-items/MoreItems.variants.js +4 -1
  139. package/lib/module/modules/multi-select/MODULE.md +5 -0
  140. package/lib/module/modules/multi-select/MultiSelect.js +23 -1
  141. package/lib/module/modules/multi-select/MultiSelect.variants.js +4 -2
  142. package/lib/module/modules/number-input/MODULE.md +2 -1
  143. package/lib/module/modules/number-input/NumberInput.js +97 -84
  144. package/lib/module/modules/number-input/NumberInput.variants.js +9 -6
  145. package/lib/module/modules/org-switcher/MODULE.md +13 -1
  146. package/lib/module/modules/org-switcher/OrgSwitcher.js +13 -2
  147. package/lib/module/modules/org-switcher/OrgSwitcher.variants.js +4 -2
  148. package/lib/module/modules/pagination/MODULE.md +2 -2
  149. package/lib/module/modules/pagination/Pagination.js +76 -37
  150. package/lib/module/modules/pagination/Pagination.variants.js +4 -2
  151. package/lib/module/modules/pagination/PaginationControls.js +55 -35
  152. package/lib/module/modules/pin-input/MODULE.md +5 -1
  153. package/lib/module/modules/pin-input/PinInput.js +9 -2
  154. package/lib/module/modules/pin-input/PinInput.variants.js +2 -1
  155. package/lib/module/modules/radio-group/MODULE.md +2 -2
  156. package/lib/module/modules/radio-group/RadioGroup.js +122 -63
  157. package/lib/module/modules/radio-group/RadioGroup.variants.js +2 -1
  158. package/lib/module/modules/reorder/MODULE.md +2 -0
  159. package/lib/module/modules/reorder/Reorder.js +4 -3
  160. package/lib/module/modules/reorder/Reorder.variants.js +4 -2
  161. package/lib/module/modules/rich-text/MODULE.md +3 -1
  162. package/lib/module/modules/rich-text/RichText.js +42 -22
  163. package/lib/module/modules/rich-text-editor/MODULE.md +4 -1
  164. package/lib/module/modules/rich-text-editor/RichTextEditor.js +8 -1
  165. package/lib/module/modules/rich-text-editor/RichTextEditor.variants.js +9 -6
  166. package/lib/module/modules/screen/MODULE.md +7 -0
  167. package/lib/module/modules/screen/Screen.js +50 -17
  168. package/lib/module/modules/screen/Screen.variants.js +18 -0
  169. package/lib/module/modules/search-bar/MODULE.md +1 -0
  170. package/lib/module/modules/search-bar/SearchBar.js +46 -26
  171. package/lib/module/modules/search-bar/SearchBar.variants.js +11 -8
  172. package/lib/module/modules/section/MODULE.md +2 -0
  173. package/lib/module/modules/section/Section.js +8 -15
  174. package/lib/module/modules/section/Section.variants.js +1 -6
  175. package/lib/module/modules/segmented-control/MODULE.md +3 -1
  176. package/lib/module/modules/segmented-control/SegmentedControl.js +110 -46
  177. package/lib/module/modules/segmented-control/SegmentedControl.variants.js +3 -2
  178. package/lib/module/modules/select/MODULE.md +26 -5
  179. package/lib/module/modules/select/Select.js +39 -12
  180. package/lib/module/modules/select/Select.variants.js +36 -12
  181. package/lib/module/modules/skeleton/MODULE.md +23 -27
  182. package/lib/module/modules/skeleton/Skeleton.js +46 -51
  183. package/lib/module/modules/skeleton/Skeleton.variants.js +17 -75
  184. package/lib/module/modules/slider/MODULE.md +2 -0
  185. package/lib/module/modules/slider/Slider.js +2 -1
  186. package/lib/module/modules/stage-progress/MODULE.md +12 -8
  187. package/lib/module/modules/stage-progress/StageProgress.js +94 -47
  188. package/lib/module/modules/stage-progress/StageProgress.variants.js +17 -12
  189. package/lib/module/modules/stat-tile/MODULE.md +2 -0
  190. package/lib/module/modules/stat-tile/StatTile.js +15 -10
  191. package/lib/module/modules/stat-tile/StatTile.variants.js +2 -0
  192. package/lib/module/modules/state-block/MODULE.md +3 -0
  193. package/lib/module/modules/state-block/StateBlock.js +11 -6
  194. package/lib/module/modules/state-block/StateBlock.variants.js +7 -0
  195. package/lib/module/modules/surface/MODULE.md +59 -0
  196. package/lib/module/modules/surface/Surface.js +42 -0
  197. package/lib/module/modules/surface/Surface.variants.js +33 -0
  198. package/lib/module/modules/surface/index.js +4 -0
  199. package/lib/module/modules/swipeable-row/MODULE.md +9 -0
  200. package/lib/module/modules/swipeable-row/SwipeableRow.js +28 -7
  201. package/lib/module/modules/switch/MODULE.md +2 -0
  202. package/lib/module/modules/switch/Switch.js +8 -2
  203. package/lib/module/modules/tabs/MODULE.md +2 -1
  204. package/lib/module/modules/tabs/Tabs.js +37 -18
  205. package/lib/module/modules/tabs/Tabs.variants.js +4 -2
  206. package/lib/module/modules/text/MODULE.md +5 -2
  207. package/lib/module/modules/text/Text.js +18 -6
  208. package/lib/module/modules/text/Text.variants.js +108 -44
  209. package/lib/module/modules/textarea/MODULE.md +2 -0
  210. package/lib/module/modules/textarea/Textarea.js +3 -2
  211. package/lib/module/modules/textarea/Textarea.variants.js +2 -1
  212. package/lib/module/modules/toast/MODULE.md +8 -4
  213. package/lib/module/modules/toast/Toast.js +31 -13
  214. package/lib/module/modules/toast/Toast.variants.js +5 -0
  215. package/lib/module/modules/tooltip/MODULE.md +15 -11
  216. package/lib/module/modules/tooltip/Tooltip.js +41 -9
  217. package/lib/module/modules/tooltip/Tooltip.variants.js +8 -1
  218. package/lib/module/theme/MODULE.md +3 -1
  219. package/lib/module/theme/platform/MODULE.md +14 -2
  220. package/lib/module/theme/platform/elevation.native.js +0 -44
  221. package/lib/module/theme/platform/floatingSurface.native.js +75 -0
  222. package/lib/module/theme/platform/highlight.native.js +59 -0
  223. package/lib/module/theme/platform/index.js +5 -0
  224. package/lib/module/theme/platform/motion.native.js +31 -11
  225. package/lib/module/theme/platform/stateLayer.native.js +14 -0
  226. package/lib/module/theme/platform/surfaces.native.js +11 -0
  227. package/lib/module/theme/provider/PixelizeProvider.js +12 -5
  228. package/lib/module/theme/tokens/MODULE.md +32 -28
  229. package/lib/module/theme/tokens/THEME-CONTRACT.md +137 -0
  230. package/lib/module/theme/tokens/assertPalette.js +29 -0
  231. package/lib/module/theme/tokens/brands/emerald/palette.light.js +7 -6
  232. package/lib/module/theme/tokens/brands/lavender/palette.light.js +3 -2
  233. package/lib/module/theme/tokens/brands/meadow/palette.light.js +7 -6
  234. package/lib/module/theme/tokens/brands/radiant/palette.light.js +7 -6
  235. package/lib/module/theme/tokens/brands/rosewood/palette.light.js +7 -6
  236. package/lib/module/theme/tokens/brands/skyline/palette.light.js +7 -6
  237. package/lib/module/theme/tokens/brands/slate/palette.light.js +8 -10
  238. package/lib/module/theme/tokens/brands/storefront/palette.light.js +7 -6
  239. package/lib/module/theme/tokens/brands/zinc/palette.dark.js +3 -2
  240. package/lib/module/theme/tokens/brands/zinc/palette.light.js +3 -2
  241. package/lib/module/theme/tokens/builders/buildDarkPalette.js +3 -2
  242. package/lib/module/theme/tokens/builders/finalizePalette.js +34 -0
  243. package/lib/module/theme/tokens/builders/liftToContrast.js +44 -0
  244. package/lib/module/theme/tokens/builders/placeholderInk.js +22 -0
  245. package/lib/module/theme/tokens/builders/semanticText.js +14 -0
  246. package/lib/module/theme/tokens/builders/surfaceRungs.js +44 -0
  247. package/lib/module/theme/tokens/index.js +5 -0
  248. package/lib/module/theme/tokens/roles/index.js +5 -0
  249. package/lib/typescript/core/gradient/AccentGradientFill.d.ts +7 -0
  250. package/lib/typescript/core/gradient/darkenHex.d.ts +2 -0
  251. package/lib/typescript/core/gradient/gradientStops.d.ts +10 -0
  252. package/lib/typescript/core/gradient/index.d.ts +5 -0
  253. package/lib/typescript/core/gradient/withAlpha.d.ts +2 -0
  254. package/lib/typescript/core/haptics/context.d.ts +3 -0
  255. package/lib/typescript/core/haptics/haptics.d.ts +33 -0
  256. package/lib/typescript/core/haptics/index.d.ts +6 -0
  257. package/lib/typescript/core/haptics/useHaptics.d.ts +12 -0
  258. package/lib/typescript/core/icon/icons/trending-up.d.ts +3 -0
  259. package/lib/typescript/core/icon/names.d.ts +1 -1
  260. package/lib/typescript/core/media/expoImage.d.ts +15 -6
  261. package/lib/typescript/core/media/pickers.d.ts +5 -5
  262. package/lib/typescript/core/motion/config.d.ts +2 -1
  263. package/lib/typescript/core/motion/index.d.ts +3 -1
  264. package/lib/typescript/core/motion/usePressState.d.ts +21 -0
  265. package/lib/typescript/core/style/index.d.ts +1 -0
  266. package/lib/typescript/core/style/radius.d.ts +2 -0
  267. package/lib/typescript/index.d.ts +4 -2
  268. package/lib/typescript/modules/accordion/Accordion.variants.d.ts +2 -2
  269. package/lib/typescript/modules/alert-dialog/AlertDialog.variants.d.ts +1 -0
  270. package/lib/typescript/modules/avatar/Avatar.variants.d.ts +1 -1
  271. package/lib/typescript/modules/avatar-group/AvatarGroup.d.ts +4 -2
  272. package/lib/typescript/modules/avatar-group/AvatarGroup.variants.d.ts +19 -0
  273. package/lib/typescript/modules/banner/Banner.d.ts +2 -0
  274. package/lib/typescript/modules/bottom-nav/BottomNav.variants.d.ts +1 -3
  275. package/lib/typescript/modules/bottom-sheet/BottomSheet.variants.d.ts +3 -1
  276. package/lib/typescript/modules/button/Button.d.ts +0 -25
  277. package/lib/typescript/modules/button/Button.variants.d.ts +6 -6
  278. package/lib/typescript/modules/button-group/ButtonGroup.d.ts +0 -19
  279. package/lib/typescript/modules/button-group/ButtonGroup.variants.d.ts +22 -56
  280. package/lib/typescript/modules/card/Card.d.ts +7 -5
  281. package/lib/typescript/modules/charts/Charts.variants.d.ts +29 -1
  282. package/lib/typescript/modules/chip/Chip.d.ts +3 -1
  283. package/lib/typescript/modules/chip/Chip.variants.d.ts +6 -2
  284. package/lib/typescript/modules/chip/index.d.ts +1 -1
  285. package/lib/typescript/modules/combobox/Combobox.variants.d.ts +17 -4
  286. package/lib/typescript/modules/data-table/DataTable.variants.d.ts +1 -1
  287. package/lib/typescript/modules/date-picker/DatePicker.variants.d.ts +15 -3
  288. package/lib/typescript/modules/date-picker/TimePicker.d.ts +1 -7
  289. package/lib/typescript/modules/divider/Divider.variants.d.ts +4 -4
  290. package/lib/typescript/modules/empty-state/EmptyState.d.ts +2 -0
  291. package/lib/typescript/modules/empty-state/EmptyState.variants.d.ts +1 -0
  292. package/lib/typescript/modules/fab/Fab.variants.d.ts +2 -0
  293. package/lib/typescript/modules/folder-row/FolderRow.d.ts +0 -8
  294. package/lib/typescript/modules/gantt/Gantt.variants.d.ts +21 -0
  295. package/lib/typescript/modules/input/Input.variants.d.ts +6 -6
  296. package/lib/typescript/modules/list-item/ListItem.d.ts +1 -5
  297. package/lib/typescript/modules/list-item/ListItem.variants.d.ts +137 -1
  298. package/lib/typescript/modules/markdown/Markdown.d.ts +7 -0
  299. package/lib/typescript/modules/message-bubble/MessageBubble.d.ts +2 -2
  300. package/lib/typescript/modules/message-bubble/MessageBubble.variants.d.ts +1 -2
  301. package/lib/typescript/modules/number-input/NumberInput.variants.d.ts +7 -5
  302. package/lib/typescript/modules/pagination/PaginationControls.d.ts +1 -4
  303. package/lib/typescript/modules/reorder/Reorder.d.ts +1 -1
  304. package/lib/typescript/modules/screen/Screen.d.ts +3 -9
  305. package/lib/typescript/modules/screen/Screen.variants.d.ts +4 -0
  306. package/lib/typescript/modules/search-bar/SearchBar.variants.d.ts +6 -6
  307. package/lib/typescript/modules/section/Section.variants.d.ts +0 -3
  308. package/lib/typescript/modules/segmented-control/SegmentedControl.variants.d.ts +1 -1
  309. package/lib/typescript/modules/select/Select.d.ts +4 -1
  310. package/lib/typescript/modules/select/Select.variants.d.ts +22 -8
  311. package/lib/typescript/modules/select/index.d.ts +1 -1
  312. package/lib/typescript/modules/skeleton/Skeleton.d.ts +3 -18
  313. package/lib/typescript/modules/skeleton/Skeleton.variants.d.ts +12 -68
  314. package/lib/typescript/modules/stage-progress/StageProgress.variants.d.ts +15 -6
  315. package/lib/typescript/modules/state-block/StateBlock.d.ts +4 -0
  316. package/lib/typescript/modules/state-block/StateBlock.variants.d.ts +1 -0
  317. package/lib/typescript/modules/surface/Surface.d.ts +19 -0
  318. package/lib/typescript/modules/surface/Surface.variants.d.ts +15 -0
  319. package/lib/typescript/modules/surface/index.d.ts +4 -0
  320. package/lib/typescript/modules/text/Text.d.ts +8 -4
  321. package/lib/typescript/modules/text/Text.variants.d.ts +14 -11
  322. package/lib/typescript/modules/toast/Toast.variants.d.ts +2 -0
  323. package/lib/typescript/modules/tooltip/Tooltip.variants.d.ts +7 -0
  324. package/lib/typescript/theme/index.d.ts +1 -1
  325. package/lib/typescript/theme/platform/elevation.native.d.ts +0 -30
  326. package/lib/typescript/theme/platform/floatingSurface.native.d.ts +10 -0
  327. package/lib/typescript/theme/platform/highlight.native.d.ts +17 -0
  328. package/lib/typescript/theme/platform/index.d.ts +9 -0
  329. package/lib/typescript/theme/platform/motion.native.d.ts +33 -13
  330. package/lib/typescript/theme/platform/stateLayer.native.d.ts +11 -0
  331. package/lib/typescript/theme/platform/surfaces.native.d.ts +8 -0
  332. package/lib/typescript/theme/provider/PixelizeProvider.d.ts +1 -1
  333. package/lib/typescript/theme/provider/types.d.ts +8 -0
  334. package/lib/typescript/theme/tokens/assertPalette.d.ts +10 -0
  335. package/lib/typescript/theme/tokens/brands/emerald/palette.light.d.ts +4 -3
  336. package/lib/typescript/theme/tokens/brands/lavender/palette.light.d.ts +4 -3
  337. package/lib/typescript/theme/tokens/brands/meadow/palette.light.d.ts +4 -3
  338. package/lib/typescript/theme/tokens/brands/radiant/palette.light.d.ts +4 -3
  339. package/lib/typescript/theme/tokens/brands/rosewood/palette.light.d.ts +4 -3
  340. package/lib/typescript/theme/tokens/brands/skyline/palette.light.d.ts +4 -3
  341. package/lib/typescript/theme/tokens/brands/slate/palette.light.d.ts +4 -3
  342. package/lib/typescript/theme/tokens/brands/storefront/palette.light.d.ts +4 -3
  343. package/lib/typescript/theme/tokens/brands/zinc/palette.light.d.ts +4 -3
  344. package/lib/typescript/theme/tokens/builders/finalizePalette.d.ts +4 -0
  345. package/lib/typescript/theme/tokens/builders/liftToContrast.d.ts +9 -0
  346. package/lib/typescript/theme/tokens/builders/placeholderInk.d.ts +13 -0
  347. package/lib/typescript/theme/tokens/builders/semanticText.d.ts +4 -0
  348. package/lib/typescript/theme/tokens/builders/surfaceRungs.d.ts +12 -0
  349. package/lib/typescript/theme/tokens/index.d.ts +5 -0
  350. package/lib/typescript/theme/tokens/roles/index.d.ts +1 -0
  351. package/lib/typescript/theme/tokens/types.d.ts +8 -7
  352. package/package.json +10 -2
  353. package/registry.json +5 -0
@@ -1,48 +1,23 @@
1
1
  "use strict";
2
2
 
3
- /**
4
- * Button the reference component. The single most-repeated shape in the audited apps (81 raw
5
- * TouchableOpacity in crm-mobile, 155 in ecommerce-mobile with three different style-key sets for the
6
- * SAME add-to-cart button, 195 web usages). Every other module copies the patterns here: how variants
7
- * resolve, how `tone` maps to role colours, how accessibility is wired, and the shape of the tests.
8
- */
9
-
10
- import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
11
- import { ActivityIndicator, Animated, Pressable, StyleSheet, Text, View } from "react-native";
12
- import { useAnimatedValue, useMotion } from "../../core/motion/index.js";
3
+ import { memo, useCallback, useMemo, useState } from "react";
4
+ import { ActivityIndicator, Platform, Pressable, StyleSheet, Text } from "react-native";
5
+ import Animated from "react-native-reanimated";
6
+ import { AccentGradientFill } from "../../core/gradient/index.js";
7
+ import { useFocusRing, usePressState } from "../../core/motion/usePressState.js";
8
+ import { useHaptics } from "../../core/haptics/index.js";
13
9
  import { Icon } from "../../core/icon/index.js";
14
- import { useTheme } from "../../theme/hooks.js";
10
+ import { composeBoxShadow, highlight } from "../../theme/platform/highlight.native.js";
11
+ import { tokenBoxShadow } from "../../theme/platform/floatingSurface.native.js";
12
+ import { elevation as elevationTokens } from "../../theme/tokens/primitives/index.js";
13
+ import { rippleColor, stateLayerScrim } from "../../theme/platform/stateLayer.native.js";
14
+ import { useTheme, useThemeColors } from "../../theme/hooks.js";
15
15
  import { BUTTON_SIZES, buttonStructure, resolveButtonAccessibility, resolveButtonTone } from "./Button.variants.js";
16
-
17
- /** A button with a visible text label. `accessibilityLabel` defaults to `label`. */
18
-
19
- /**
20
- * An icon-only button. It has no visible text, so `accessibilityLabel` is REQUIRED at the type level
21
- * — the single worst a11y trap on web (its tooltip was the only label on icon-only buttons in 22
22
- * files, and tooltips do not exist on touch). `label?: never` makes the two shapes mutually exclusive.
23
- */
24
16
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
25
17
  const ICON_STROKE = 2;
26
- // State-layer scrims. Direction is chosen by the label's brightness so the fill moves AWAY from the
27
- // label on press — its contrast can only rise. 8-digit hex carries the alpha (~15%) directly.
28
- const PRESS_SCRIM_DARK = "#00000026";
29
- const PRESS_SCRIM_LIGHT = "#ffffff26";
30
- // The focus ring sits a small gap OUTSIDE the control, on the canvas, because `border.focus` is the
31
- // role token proven ≥ 3:1 against the canvas (WCAG 2.4.11) — drawn over a solid fill it could fail.
32
- const FOCUS_RING_WIDTH = 2;
18
+ const FOCUS_RING_WIDTH = 3;
33
19
  const FOCUS_RING_GAP = 2;
34
-
35
- // The press scale has to sit on the same node `style` lands on, so the contract's "style last" holds.
36
20
  const AnimatedPressable = Animated.createAnimatedComponent(Pressable);
37
-
38
- /** Cheap perceived-brightness split; `onFill` is only ever a near-white or near-black role value. */
39
- function isLight(hex) {
40
- const n = parseInt(hex.slice(1, 7), 16);
41
- const r = n >> 16 & 0xff;
42
- const g = n >> 8 & 0xff;
43
- const b = n & 0xff;
44
- return r * 0.299 + g * 0.587 + b * 0.114 > 140;
45
- }
46
21
  function ButtonImpl(props) {
47
22
  const {
48
23
  variant = "solid",
@@ -68,45 +43,35 @@ function ButtonImpl(props) {
68
43
  accessibilityHint
69
44
  } = props;
70
45
  const theme = useTheme();
71
- const motion = useMotion();
72
- const pressed = useAnimatedValue(0);
73
- const running = useRef(null);
74
- // Keyboard / external-keyboard / assistive-tech focus (no-op on pure touch, correct everywhere else).
46
+ const colors = useThemeColors();
47
+ const haptics = useHaptics();
48
+ const blocked = disabled || loading;
49
+ const press = usePressState(blocked);
75
50
  const [focused, setFocused] = useState(false);
51
+ const {
52
+ focusRingStyle
53
+ } = useFocusRing(focused, blocked);
76
54
  const spec = BUTTON_SIZES[size];
77
55
  const toneColors = useMemo(() => resolveButtonTone(theme.colors, tone), [theme.colors, tone]);
78
56
  const iconOnly = label === undefined;
79
57
  const foreground = variant === "solid" ? toneColors.onFill : toneColors.text;
80
- const overlayColor = variant === "solid" ? isLight(toneColors.onFill) ? PRESS_SCRIM_DARK : PRESS_SCRIM_LIGHT : toneColors.subtle;
58
+ const overlayColor = stateLayerScrim(theme.mode);
59
+ const handlePress = useCallback(() => {
60
+ haptics.selection();
61
+ onPress?.();
62
+ }, [haptics, onPress]);
81
63
  const a11y = useMemo(() => resolveButtonAccessibility({
82
64
  label,
83
65
  accessibilityLabel,
84
66
  disabled,
85
67
  loading,
86
68
  selected,
87
- onPress
88
- }), [label, accessibilityLabel, disabled, loading, selected, onPress]);
89
- const setPressed = useCallback(isPressed => {
90
- running.current?.stop();
91
- const toValue = isPressed ? 1 : 0;
92
- if (!motion.enabled) {
93
- pressed.setValue(toValue);
94
- return;
95
- }
96
- running.current = motion.timing(pressed, toValue, {
97
- duration: "fast"
98
- });
99
- running.current.start();
100
- }, [motion, pressed]);
101
- useEffect(() => () => running.current?.stop(), []);
102
-
103
- // Own state first, then the incoming handler — an outer handler that throws can never strand the
104
- // press/focus ring in its active state.
105
- const handlePressIn = useCallback(() => setPressed(true), [setPressed]);
69
+ onPress: onPress === undefined ? undefined : handlePress
70
+ }), [label, accessibilityLabel, disabled, loading, selected, onPress, handlePress]);
106
71
  const handlePressOut = useCallback(event => {
107
- setPressed(false);
72
+ press.handlers.onPressOut();
108
73
  onPressOut?.(event);
109
- }, [setPressed, onPressOut]);
74
+ }, [press.handlers, onPressOut]);
110
75
  const handleFocus = useCallback(event => {
111
76
  setFocused(true);
112
77
  onFocus?.(event);
@@ -115,42 +80,55 @@ function ButtonImpl(props) {
115
80
  setFocused(false);
116
81
  onBlur?.(event);
117
82
  }, [onBlur]);
118
-
119
- // One value, two consumers: the state-layer opacity and the root's press scale.
120
- const scaleStyle = useMemo(() => ({
121
- transform: [{
122
- scale: pressed.interpolate({
123
- inputRange: [0, 1],
124
- outputRange: [1, motion.transform.pressScale]
125
- })
126
- }]
127
- }), [pressed, motion.transform.pressScale]);
128
- const overlayStyle = useMemo(() => [StyleSheet.absoluteFill, {
83
+ const radius = theme.radii.md;
84
+ const solidToken = elevationTokens.sm;
85
+ const solidElevation = theme.elevation.sm;
86
+ const highlightLayers = highlight("subtle", theme.mode);
87
+ const surfaceStyle = useMemo(() => {
88
+ const base = {
89
+ borderRadius: radius,
90
+ borderCurve: "continuous"
91
+ };
92
+ if (variant === "solid") {
93
+ base.boxShadow = composeBoxShadow(tokenBoxShadow(solidToken), highlightLayers);
94
+ base.elevation = solidElevation.elevation;
95
+ Object.assign(base, solidElevation);
96
+ }
97
+ return base;
98
+ }, [variant, radius, solidToken, solidElevation, highlightLayers]);
99
+ const androidRipple = useMemo(() => {
100
+ if (Platform.OS !== "android") return undefined;
101
+ return {
102
+ color: rippleColor(theme.mode),
103
+ borderless: false
104
+ };
105
+ }, [theme.mode]);
106
+ const overlayStaticStyle = useMemo(() => ({
129
107
  backgroundColor: overlayColor,
130
- opacity: pressed,
131
- borderRadius: theme.radii.base,
132
- pointerEvents: "none"
133
- }], [overlayColor, pressed, theme.radii.base]);
134
- const focusRingStyle = useMemo(() => ({
135
- position: "absolute",
136
- pointerEvents: "none",
108
+ borderRadius: radius
109
+ }), [overlayColor, radius]);
110
+ const focusRingStaticStyle = useMemo(() => ({
111
+ borderWidth: FOCUS_RING_WIDTH,
112
+ borderColor: colors.border.focus,
113
+ borderRadius: radius + FOCUS_RING_GAP + FOCUS_RING_WIDTH,
137
114
  top: -(FOCUS_RING_GAP + FOCUS_RING_WIDTH),
138
115
  left: -(FOCUS_RING_GAP + FOCUS_RING_WIDTH),
139
116
  right: -(FOCUS_RING_GAP + FOCUS_RING_WIDTH),
140
- bottom: -(FOCUS_RING_GAP + FOCUS_RING_WIDTH),
141
- borderWidth: FOCUS_RING_WIDTH,
142
- borderColor: theme.colors.border.focus,
143
- borderRadius: theme.radii.base + FOCUS_RING_GAP + FOCUS_RING_WIDTH
144
- }), [theme.colors.border.focus, theme.radii.base]);
117
+ bottom: -(FOCUS_RING_GAP + FOCUS_RING_WIDTH)
118
+ }), [colors.border.focus, radius]);
119
+ const focusOutlineStyle = useMemo(() => ({
120
+ outlineWidth: FOCUS_RING_WIDTH,
121
+ outlineOffset: FOCUS_RING_GAP,
122
+ outlineColor: colors.border.focus,
123
+ outlineStyle: "solid",
124
+ borderRadius: radius
125
+ }), [colors.border.focus, radius]);
145
126
  const glyph = useCallback(name => /*#__PURE__*/_jsx(Icon, {
146
127
  name: name,
147
128
  size: spec.iconSize,
148
129
  color: foreground,
149
130
  strokeWidth: ICON_STROKE
150
131
  }), [spec.iconSize, foreground]);
151
-
152
- // The spinner is never the sole loading signal — `accessibilityState.busy` announces it, and the
153
- // label (when present) stays visible. Hidden from AT so it isn't read as a separate element.
154
132
  const spinner = useMemo(() => /*#__PURE__*/_jsx(ActivityIndicator, {
155
133
  size: "small",
156
134
  color: foreground,
@@ -171,30 +149,38 @@ function ButtonImpl(props) {
171
149
  disabled: a11y.disabled,
172
150
  onPress: a11y.onPress,
173
151
  onLongPress: onLongPress,
174
- onPressIn: handlePressIn,
152
+ onPressIn: press.handlers.onPressIn,
175
153
  onPressOut: handlePressOut,
176
154
  onHoverIn: onHoverIn,
177
155
  onHoverOut: onHoverOut,
178
156
  onFocus: handleFocus,
179
157
  onBlur: handleBlur,
158
+ onLayout: press.onLayout,
180
159
  hitSlop: spec.hitSlop,
160
+ android_ripple: androidRipple,
181
161
  style: [buttonStructure(theme, {
182
162
  variant,
183
163
  size
184
- }), variant === "solid" && {
164
+ }), surfaceStyle, {
165
+ overflow: "hidden"
166
+ }, variant === "solid" && {
185
167
  backgroundColor: toneColors.fill
186
168
  }, variant === "outline" && {
187
169
  borderColor: toneColors.border
188
170
  }, iconOnly && {
189
171
  paddingHorizontal: 0,
190
172
  minWidth: spec.height
191
- }, fullWidth && styles.fullWidth, scaleStyle, (disabled || loading) && styles.dimmed, style],
192
- children: [/*#__PURE__*/_jsx(Animated.View, {
193
- testID: "button-press-overlay",
194
- style: overlayStyle
195
- }), focused && /*#__PURE__*/_jsx(View, {
173
+ }, fullWidth && styles.fullWidth, press.animatedStyle, focused && focusOutlineStyle, (disabled || loading) && styles.dimmed, style],
174
+ children: [variant === "solid" && /*#__PURE__*/_jsx(AccentGradientFill, {
175
+ color: toneColors.fill
176
+ }), focused && /*#__PURE__*/_jsx(Animated.View, {
177
+ pointerEvents: "none",
196
178
  testID: "button-focus-ring",
197
- style: focusRingStyle
179
+ style: [styles.focusRingHost, focusRingStaticStyle, focusRingStyle]
180
+ }), /*#__PURE__*/_jsx(Animated.View, {
181
+ pointerEvents: "none",
182
+ testID: "button-press-overlay",
183
+ style: [StyleSheet.absoluteFill, overlayStaticStyle, press.overlayStyle]
198
184
  }), leading, label !== undefined && /*#__PURE__*/_jsx(Text, {
199
185
  numberOfLines: 1,
200
186
  style: [theme.fontStyleForWeight(theme.fontWeights.semibold), {
@@ -209,16 +195,16 @@ const styles = StyleSheet.create({
209
195
  fullWidth: {
210
196
  alignSelf: "stretch"
211
197
  },
212
- // A disabled control is exempt from the contrast minimum (WCAG 1.4.3), so a uniform dim is correct.
213
198
  dimmed: {
214
199
  opacity: 0.5
215
200
  },
216
201
  linkText: {
217
202
  textDecorationLine: "underline"
203
+ },
204
+ focusRingHost: {
205
+ position: "absolute",
206
+ pointerEvents: "none"
218
207
  }
219
208
  });
220
-
221
- // A consumer's screen re-renders far more often than Button's own props change — memo is near-free
222
- // insurance for a design-system primitive (see CLAUDE.md "Performance — no unnecessary re-renders").
223
209
  export const Button = /*#__PURE__*/memo(ButtonImpl);
224
210
  //# sourceMappingURL=Button.js.map
@@ -31,22 +31,22 @@ const slopFor = height => Math.max(0, Math.ceil((MIN_TOUCH_TARGET - height) / 2)
31
31
  */
32
32
  export const BUTTON_SIZES = {
33
33
  sm: {
34
- height: 32,
34
+ height: 44,
35
35
  fontSize: 14,
36
36
  iconSize: 16,
37
- hitSlop: slopFor(32)
37
+ hitSlop: slopFor(44)
38
38
  },
39
39
  md: {
40
- height: 40,
40
+ height: 52,
41
41
  fontSize: 16,
42
42
  iconSize: 18,
43
- hitSlop: slopFor(40)
43
+ hitSlop: slopFor(52)
44
44
  },
45
45
  lg: {
46
- height: 48,
46
+ height: 56,
47
47
  fontSize: 18,
48
48
  iconSize: 20,
49
- hitSlop: slopFor(48)
49
+ hitSlop: slopFor(56)
50
50
  }
51
51
  };
52
52
  /**
@@ -136,7 +136,8 @@ export const buttonStructure = createThemedVariants(theme => ({
136
136
  alignItems: "center",
137
137
  justifyContent: "center",
138
138
  columnGap: theme.space[2],
139
- borderRadius: theme.radii.base
139
+ borderRadius: theme.radii.md,
140
+ borderCurve: "continuous"
140
141
  },
141
142
  variants: {
142
143
  size: {
@@ -98,6 +98,10 @@ label); `accent`/`danger` map to the accent and danger roles.
98
98
  as optional peers); `Button.tsx` and `index.ts` import from there.
99
99
  - `useReducedMotion` hoisted to `src/core/a11y/`.
100
100
 
101
+ Press feedback uses `usePressState` (Reanimated scale + state-layer overlay, width-aware).
102
+ Focus ring uses native `outline*` props animated via `useFocusRing`. Solid variant gets
103
+ `elevation.sm` + inset highlight; Android `android_ripple` on a clipped pressable.
104
+
101
105
  ## Performance
102
106
 
103
107
  Wrapped in `React.memo` (repo-wide re-render audit, 2026-07-17 — see root `CLAUDE.md`) — renamed to `ButtonImpl` internally, exported as `Button = memo(ButtonImpl)`. Its one child, `Icon`, only ever receives primitives — nothing to memoize.
@@ -107,3 +111,5 @@ Wrapped in `React.memo` (repo-wide re-render audit, 2026-07-17 — see root `CLA
107
111
  - Theme imports decoupled to `theme/hooks`; optional peers (reanimated, gesture-handler, flash-list) load at runtime.
108
112
  - List-heavy surfaces use `VirtualList` with device-tier window sizing where applicable.
109
113
  - `React.memo` + stable callbacks retained; render-item/key-extractor hoisted per ESLint perf rules.
114
+
115
+ - **Round 2 visual** — radii retarget (`radii.md`/`lg`/`xl`/`full`), `borderCurve: continuous` on md+ corners; floating surfaces wire platform elevation/highlight where applicable.
@@ -1,27 +1,14 @@
1
1
  "use strict";
2
2
 
3
- /**
4
- * ButtonGroup a segmented single-choice control. Visually connected segments sharing one outer
5
- * border and a divider line between adjacent segments, NOT a row of standalone `Button`s — that
6
- * connected/segmented treatment is a different structural shape than Button's own pill/rect
7
- * variants, so this is a standalone sibling (it never imports `../button`). The border/divider is
8
- * drawn PER SEGMENT, not once on the container: every edge that touches the selected segment omits
9
- * the stroke (see `resolveButtonGroupSegmentEdgeColors` — WCAG 1.4.11) and relies on the selected
10
- * fill's own contrast against the canvas instead.
11
- *
12
- * One component owns the whole group, same as `RadioGroup`: each segment carries its own
13
- * `accessibilityRole="radio"` + `accessibilityState.checked`, and the container carries
14
- * `accessibilityRole="radiogroup"` so assistive tech announces the grouping without collapsing the
15
- * individually-focusable segments into one.
16
- *
17
- * No animation anywhere, deliberately: selection is a conditional fill, and the segments share one
18
- * continuous border, so a per-segment press scale (Button's affordance) would visibly detach a
19
- * segment from the control it is part of. The `pressed` fill swap is the affordance instead. Nothing
20
- * animates, so — like `RadioGroup` — there is nothing here for reduce motion (WCAG 2.3.3) to gate.
21
- */
3
+ // Segmented single-choice control: segments share one tonal container fill, not a bordered frame.
4
+ // A hairline divider sits between adjacent unselected segments, omitted at the selected edge (WCAG
5
+ // 1.4.11) see `resolveButtonGroupSegmentEdgeColors`. Never imports `../button`; a different shape.
22
6
 
23
7
  import { memo, useCallback, useMemo, useRef, useState } from "react";
24
- import { Pressable, StyleSheet, Text, View } from "react-native";
8
+ import { Platform, Pressable, StyleSheet, Text, View } from "react-native";
9
+ import Animated from "react-native-reanimated";
10
+ import { usePressState } from "../../core/motion/usePressState.js";
11
+ import { rippleColor, stateLayerScrim } from "../../theme/platform/stateLayer.native.js";
25
12
  import { useTheme } from "../../theme/hooks.js";
26
13
  import { BUTTON_GROUP_SIZES, buttonGroupSegmentStructure, buttonGroupStructure, resolveButtonGroupColors, resolveButtonGroupKeyIndex, resolveButtonGroupSegmentAccessibility, resolveButtonGroupSegmentEdgeColors, resolveButtonGroupSegmentHitSlop } from "./ButtonGroup.variants.js";
27
14
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
@@ -38,6 +25,7 @@ const KeyboardView = View;
38
25
  */
39
26
  const FOCUS_RING_WIDTH = 2;
40
27
  const FOCUS_RING_INSET = 2;
28
+ const AnimatedPressable = Animated.createAnimatedComponent(Pressable);
41
29
  function ButtonGroupSegmentImpl({
42
30
  label,
43
31
  value,
@@ -56,6 +44,7 @@ function ButtonGroupSegmentImpl({
56
44
  testID
57
45
  }) {
58
46
  const theme = useTheme();
47
+ const press = usePressState(disabled || selected);
59
48
  const [focused, setFocused] = useState(false);
60
49
  const a11y = useMemo(() => resolveButtonGroupSegmentAccessibility({
61
50
  selected,
@@ -69,6 +58,13 @@ function ButtonGroupSegmentImpl({
69
58
  isFirst,
70
59
  isLast
71
60
  }), [size, isFirst, isLast]);
61
+ const androidRipple = useMemo(() => {
62
+ if (Platform.OS !== "android" || disabled || selected) return undefined;
63
+ return {
64
+ color: rippleColor(theme.mode),
65
+ borderless: false
66
+ };
67
+ }, [theme.mode, disabled, selected]);
72
68
  const handlePress = useCallback(() => onValueChange(value), [onValueChange, value]);
73
69
  const handleFocus = useCallback(() => setFocused(true), []);
74
70
  const handleBlur = useCallback(() => setFocused(false), []);
@@ -84,29 +80,28 @@ function ButtonGroupSegmentImpl({
84
80
  bottom: FOCUS_RING_INSET,
85
81
  borderWidth: FOCUS_RING_WIDTH,
86
82
  borderColor: theme.colors.border.focus,
87
- borderRadius: Math.max(0, theme.radii.base - FOCUS_RING_INSET)
88
- }), [theme.colors.border.focus, theme.radii.base]);
89
- const segmentStyle = useCallback(({
90
- pressed
91
- }) => [buttonGroupSegmentStructure(theme, {
83
+ borderRadius: Math.max(0, theme.radii.md - FOCUS_RING_INSET)
84
+ }), [theme.colors.border.focus, theme.radii.md]);
85
+ const segmentStyle = useMemo(() => [buttonGroupSegmentStructure(theme, {
92
86
  size,
93
87
  first: isFirst ? "on" : "off",
94
88
  last: isLast ? "on" : "off"
95
89
  }), {
96
- borderTopColor: edges.top,
97
- borderBottomColor: edges.bottom,
98
- borderLeftColor: edges.left,
99
90
  borderRightColor: edges.right
100
91
  }, selected ? {
101
92
  backgroundColor: colors.selectedFill
102
- } : pressed && !disabled && {
103
- backgroundColor: colors.pressedFill
104
- }, disabled && styles.dimmed], [theme, size, isFirst, isLast, edges, selected, disabled, colors]);
93
+ } : null, {
94
+ overflow: "hidden"
95
+ }, press.animatedStyle, disabled && styles.dimmed], [theme, size, isFirst, isLast, edges, selected, disabled, colors, press.animatedStyle]);
96
+ const overlayStaticStyle = useMemo(() => ({
97
+ backgroundColor: stateLayerScrim(theme.mode),
98
+ borderRadius: Math.max(0, theme.radii.md - FOCUS_RING_INSET)
99
+ }), [theme.mode, theme.radii.md]);
105
100
  const labelStyle = useMemo(() => [theme.fontStyleForWeight(theme.fontWeights.medium), {
106
101
  fontSize,
107
102
  color: selected ? colors.onSelectedFill : colors.label
108
103
  }], [theme, fontSize, selected, colors]);
109
- return /*#__PURE__*/_jsxs(Pressable, {
104
+ return /*#__PURE__*/_jsxs(AnimatedPressable, {
110
105
  ref: setRef,
111
106
  testID: testID,
112
107
  accessibilityRole: a11y.accessibilityRole,
@@ -114,17 +109,21 @@ function ButtonGroupSegmentImpl({
114
109
  "aria-disabled": a11y["aria-disabled"],
115
110
  accessibilityLabel: label,
116
111
  disabled: a11y.disabled,
117
- tabIndex: active && !disabled ? 0 : -1
118
- // RN's Pressable stays `focusable` when disabled, so a TV remote could otherwise land on a
119
- // segment that renders no ring (WCAG 2.4.7) — the same fix NumberInput's steppers use.
120
- ,
112
+ tabIndex: active && !disabled ? 0 : -1,
121
113
  focusable: !disabled,
122
114
  onFocus: handleFocus,
123
115
  onBlur: handleBlur,
124
116
  onPress: disabled ? undefined : handlePress,
117
+ onPressIn: press.handlers.onPressIn,
118
+ onPressOut: press.handlers.onPressOut,
119
+ onLayout: press.onLayout,
125
120
  hitSlop: hitSlop,
121
+ android_ripple: androidRipple,
126
122
  style: segmentStyle,
127
- children: [focused && !disabled && /*#__PURE__*/_jsx(View, {
123
+ children: [!selected && /*#__PURE__*/_jsx(Animated.View, {
124
+ pointerEvents: "none",
125
+ style: [StyleSheet.absoluteFill, overlayStaticStyle, press.overlayStyle]
126
+ }), focused && !disabled && /*#__PURE__*/_jsx(View, {
128
127
  testID: testID === undefined ? undefined : `${testID}-focus-ring`,
129
128
  style: focusRingStyle
130
129
  }), /*#__PURE__*/_jsx(Text, {
@@ -65,12 +65,7 @@ export function resolveButtonGroupColors(colors) {
65
65
  selectedFill: colors.accent.solid,
66
66
  onSelectedFill: colors.accent.onSolid,
67
67
  label: colors.fg.default,
68
- // `bg.sunken` (a pale neutral tint), NOT `bg.hover`: measured, `bg.hover`'s saturated mid-tone
69
- // drops the brand-tinted `fg.default` label below 4.5:1 on several brands — same class of bug
70
- // Button's "neutral" tone and RadioGroup's pressed row document fixing the same way. Composited
71
- // with a small `bg.canvas` overlay (see `PRESSED_FILL_OVERLAY_ALPHA_HEX` above) so it also clears
72
- // 3:1 against `selectedFill` — the boundary a segment adjacent to the selected one actually draws
73
- // while being pressed.
68
+ containerFill: colors.bg.raised,
74
69
  pressedFill: compositeOver(`${colors.bg.canvas}${PRESSED_FILL_OVERLAY_ALPHA_HEX}`, colors.bg.sunken),
75
70
  outline: colors.border.interactive
76
71
  };
@@ -80,19 +75,9 @@ export function resolveButtonGroupColors(colors) {
80
75
  * the WIDTH constant (see `buttonGroupSegmentStructure`) and only swapping the COLOUR avoids a
81
76
  * layout shift when a segment's selection changes. */
82
77
  const OMITTED_EDGE = "transparent";
83
- /**
84
- * Per-edge, per-segment outline colour — the WCAG 1.4.11 fix. An edge draws the shared `outline`
85
- * colour only when BOTH sides of it are unselected; any edge touching the selected segment is
86
- * `transparent` instead, so the selected fill's own contrast against the canvas (or, for the
87
- * divider case, against the neighbour's transparent/canvas background) is what marks the boundary.
88
- */
89
78
  export function resolveButtonGroupSegmentEdgeColors(colors, input) {
90
- const own = input.selected ? OMITTED_EDGE : colors.outline;
91
79
  const right = input.selected || input.nextSelected ? OMITTED_EDGE : colors.outline;
92
80
  return {
93
- top: own,
94
- bottom: own,
95
- left: own,
96
81
  right
97
82
  };
98
83
  }
@@ -166,37 +151,29 @@ export function resolveButtonGroupKeyIndex(input) {
166
151
  }
167
152
 
168
153
  /**
169
- * The container — a clipping rect only. `overflow: hidden` + `borderRadius` clips every segment's
170
- * fill (and the outer segments' square corners) to this single rounded outline, so the selected
171
- * segment never shows a corner poking past the shared shape the visual mechanism that makes this
172
- * read as ONE connected control rather than a row of standalone buttons. It carries NO border of its
173
- * own: the outer border is drawn by the first/last segments themselves (see
174
- * `buttonGroupSegmentStructure`), because only a per-segment border can be selectively omitted where
175
- * it touches the selected segment (WCAG 1.4.11) — a single container-wide border is one colour for
176
- * its entire perimeter and cannot vary by which segment it runs along.
154
+ * The container. `overflow: hidden` + `borderRadius` clips every segment's fill (and the outer
155
+ * segments' square corners) to one rounded shape, so the selected segment never pokes a corner past
156
+ * it. `backgroundColor: bg.raised` is the group's tonal frame it replaces the old outer hairline,
157
+ * so unselected segments (transparent) read as sitting on one continuous raised surface.
177
158
  */
178
159
  export const buttonGroupStructure = createThemedVariants(theme => ({
179
160
  base: {
180
161
  flexDirection: "row",
181
- borderRadius: theme.radii.base,
182
- overflow: "hidden"
162
+ borderRadius: theme.radii.md,
163
+ borderCurve: "continuous",
164
+ overflow: "hidden",
165
+ backgroundColor: theme.colors.bg.raised
183
166
  }
184
167
  }));
185
168
 
186
169
  /**
187
170
  * One segment's layout. `minWidth: MIN_TOUCH_TARGET` is the real ≥44dp touch-target floor for the
188
- * WIDTH axis horizontal hitSlop can no longer safely pad an internal segment (see
189
- * `resolveButtonGroupSegmentHitSlop`), so the rendered node itself must never shrink narrower than
190
- * 44dp, for a realistic 2–4 option row at either size. `height` is fixed (not a minimum) so the
171
+ * WIDTH axis (see `resolveButtonGroupSegmentHitSlop`). `height` is fixed (not a minimum) so the
191
172
  * vertical hitSlop math holds against what actually renders.
192
173
  *
193
- * Every segment structurally carries a top, bottom, and right border (thin width) — the right one is
194
- * the divider on every segment except the last, where it is instead that segment's own outer right
195
- * edge. Only the FIRST segment gets a left border and left-corner radii (the group's own outer left
196
- * edge); only the LAST segment gets right-corner radii (matching the container's own `borderRadius`,
197
- * so that segment's own border curves rather than being clipped into an L by the container). Border
198
- * WIDTHS are structural and constant; COLOURS (drawn vs `transparent`) are resolved per render by
199
- * `resolveButtonGroupSegmentEdgeColors` and applied inline over this.
174
+ * Only a right border remains, structural on every segment but the last — the internal divider
175
+ * between two adjacent unselected segments (see `resolveButtonGroupSegmentEdgeColors`). There is no
176
+ * more top/bottom/left border: the container's own tonal fill carries the group's outer shape now.
200
177
  */
201
178
  export const buttonGroupSegmentStructure = createThemedVariants(theme => ({
202
179
  base: {
@@ -204,8 +181,6 @@ export const buttonGroupSegmentStructure = createThemedVariants(theme => ({
204
181
  minWidth: MIN_TOUCH_TARGET,
205
182
  alignItems: "center",
206
183
  justifyContent: "center",
207
- borderTopWidth: theme.borderWidths.thin,
208
- borderBottomWidth: theme.borderWidths.thin,
209
184
  borderRightWidth: theme.borderWidths.thin
210
185
  },
211
186
  variants: {
@@ -221,18 +196,18 @@ export const buttonGroupSegmentStructure = createThemedVariants(theme => ({
221
196
  },
222
197
  first: {
223
198
  on: {
224
- borderLeftWidth: theme.borderWidths.thin,
225
- borderTopLeftRadius: theme.radii.base,
226
- borderBottomLeftRadius: theme.radii.base
199
+ borderTopLeftRadius: theme.radii.md,
200
+ borderBottomLeftRadius: theme.radii.md,
201
+ borderCurve: "continuous"
227
202
  },
228
- off: {
229
- borderLeftWidth: 0
230
- }
203
+ off: {}
231
204
  },
232
205
  last: {
233
206
  on: {
234
- borderTopRightRadius: theme.radii.base,
235
- borderBottomRightRadius: theme.radii.base
207
+ borderTopRightRadius: theme.radii.md,
208
+ borderBottomRightRadius: theme.radii.md,
209
+ borderCurve: "continuous",
210
+ borderRightWidth: 0
236
211
  },
237
212
  off: {}
238
213
  }