@titan-design/react-ui 0.12.1 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (509) hide show
  1. package/README.md +46 -47
  2. package/dist/bodymap.js +768 -701
  3. package/dist/bodymap.js.map +1 -1
  4. package/dist/bodymap.mjs +770 -703
  5. package/dist/bodymap.mjs.map +1 -1
  6. package/dist/index.d.mts +1319 -216
  7. package/dist/index.d.ts +1319 -216
  8. package/dist/index.js +5996 -4498
  9. package/dist/index.js.map +1 -1
  10. package/dist/index.mjs +5773 -4357
  11. package/dist/index.mjs.map +1 -1
  12. package/dist/{pages-CvsFqNtx.d.mts → pages-CpW3OB3g.d.mts} +21 -3
  13. package/dist/{pages-B1hqnGIC.d.ts → pages-_3Ajpiqu.d.ts} +21 -3
  14. package/dist/pages.d.mts +1 -1
  15. package/dist/pages.d.ts +1 -1
  16. package/dist/pages.js +1435 -1428
  17. package/dist/pages.js.map +1 -1
  18. package/dist/pages.mjs +1443 -1436
  19. package/dist/pages.mjs.map +1 -1
  20. package/dist/theme/index.d.mts +195 -134
  21. package/dist/theme/index.d.ts +195 -134
  22. package/dist/theme/index.js +215 -300
  23. package/dist/theme/index.js.map +1 -1
  24. package/dist/theme/index.mjs +202 -296
  25. package/dist/theme/index.mjs.map +1 -1
  26. package/dist/theme/tokens-css.js +62 -5
  27. package/dist/theme/tokens-css.js.map +1 -1
  28. package/dist/theme/tokens-css.mjs +62 -5
  29. package/dist/theme/tokens-css.mjs.map +1 -1
  30. package/dist/theme/tokens.d.mts +73 -5
  31. package/dist/theme/tokens.d.ts +73 -5
  32. package/dist/theme/tokens.js +55 -7
  33. package/dist/theme/tokens.js.map +1 -1
  34. package/dist/theme/tokens.mjs +55 -8
  35. package/dist/theme/tokens.mjs.map +1 -1
  36. package/docs/audits/2026-09-08-critique-addenda.md +51 -0
  37. package/docs/audits/2026-09-08-library-critique.md +212 -0
  38. package/docs/library-roadmap.md +99 -0
  39. package/package.json +1 -1
  40. package/src/arch/arch-graph.freshness.test.ts +52 -0
  41. package/src/arch/arch-graph.json +5021 -1617
  42. package/src/components/custom/ActiveWork/CoChangeChip.stories.tsx +44 -0
  43. package/src/components/custom/ActiveWork/CoChangeChip.test.tsx +29 -0
  44. package/src/components/custom/ActiveWork/CoChangeChip.tsx +48 -0
  45. package/src/components/custom/ActiveWork/Eyebrow.stories.tsx +25 -0
  46. package/src/components/custom/ActiveWork/Eyebrow.test.tsx +16 -0
  47. package/src/components/custom/ActiveWork/Eyebrow.tsx +26 -0
  48. package/src/components/custom/ActiveWork/FileActivityDetail.stories.tsx +50 -0
  49. package/src/components/custom/ActiveWork/FileActivityDetail.test.tsx +66 -0
  50. package/src/components/custom/ActiveWork/FileActivityDetail.tsx +202 -0
  51. package/src/components/custom/ActiveWork/FileActivityRow.stories.tsx +70 -0
  52. package/src/components/custom/ActiveWork/FileActivityRow.test.tsx +67 -0
  53. package/src/components/custom/ActiveWork/FileActivityRow.tsx +130 -0
  54. package/src/components/custom/ActiveWork/FileHistoryExplorer.stories.tsx +84 -0
  55. package/src/components/custom/ActiveWork/FileHistoryExplorer.test.tsx +99 -0
  56. package/src/components/custom/ActiveWork/FileHistoryExplorer.tsx +138 -0
  57. package/src/components/custom/ActiveWork/FilePathLabel.stories.tsx +39 -0
  58. package/src/components/custom/ActiveWork/FilePathLabel.test.tsx +53 -0
  59. package/src/components/custom/ActiveWork/FilePathLabel.tsx +63 -0
  60. package/src/components/custom/ActiveWork/InitiativeBrief.stories.tsx +50 -0
  61. package/src/components/custom/ActiveWork/InitiativeBrief.test.tsx +62 -0
  62. package/src/components/custom/ActiveWork/InitiativeBrief.tsx +181 -0
  63. package/src/components/custom/ActiveWork/InitiativeCard.stories.tsx +73 -0
  64. package/src/components/custom/ActiveWork/InitiativeCard.test.tsx +68 -0
  65. package/src/components/custom/ActiveWork/InitiativeCard.tsx +136 -0
  66. package/src/components/custom/ActiveWork/InitiativeHeader.stories.tsx +59 -0
  67. package/src/components/custom/ActiveWork/InitiativeHeader.test.tsx +40 -0
  68. package/src/components/custom/ActiveWork/InitiativeHeader.tsx +73 -0
  69. package/src/components/custom/ActiveWork/InitiativeReader.stories.tsx +145 -0
  70. package/src/components/custom/ActiveWork/OpenLoops.stories.tsx +58 -0
  71. package/src/components/custom/ActiveWork/OpenLoops.test.tsx +61 -0
  72. package/src/components/custom/ActiveWork/OpenLoops.tsx +107 -0
  73. package/src/components/custom/ActiveWork/PortfolioOverview.stories.tsx +101 -0
  74. package/src/components/custom/ActiveWork/PortfolioOverview.test.tsx +81 -0
  75. package/src/components/custom/ActiveWork/PortfolioOverview.tsx +83 -0
  76. package/src/components/custom/ActiveWork/README.md +305 -0
  77. package/src/components/custom/ActiveWork/SessionDetail.stories.tsx +71 -0
  78. package/src/components/custom/ActiveWork/SessionDetail.test.tsx +84 -0
  79. package/src/components/custom/ActiveWork/SessionDetail.tsx +180 -0
  80. package/src/components/custom/ActiveWork/SessionList.stories.tsx +69 -0
  81. package/src/components/custom/ActiveWork/SessionList.test.tsx +78 -0
  82. package/src/components/custom/ActiveWork/SessionList.tsx +103 -0
  83. package/src/components/custom/ActiveWork/SessionListItem.stories.tsx +64 -0
  84. package/src/components/custom/ActiveWork/SessionListItem.test.tsx +62 -0
  85. package/src/components/custom/ActiveWork/SessionListItem.tsx +152 -0
  86. package/src/components/custom/ActiveWork/SessionReader.stories.tsx +113 -0
  87. package/src/components/custom/ActiveWork/SeverityLabel.stories.tsx +51 -0
  88. package/src/components/custom/ActiveWork/SeverityLabel.test.tsx +68 -0
  89. package/src/components/custom/ActiveWork/SeverityLabel.tsx +97 -0
  90. package/src/components/custom/ActiveWork/TaskRow.stories.tsx +63 -0
  91. package/src/components/custom/ActiveWork/TaskRow.test.tsx +112 -0
  92. package/src/components/custom/ActiveWork/TaskRow.tsx +176 -0
  93. package/src/components/custom/ActiveWork/TaskTable.stories.tsx +123 -0
  94. package/src/components/custom/ActiveWork/TaskTable.test.tsx +233 -0
  95. package/src/components/custom/ActiveWork/TaskTable.tsx +321 -0
  96. package/src/components/custom/ActiveWork/active-work-depth.test.tsx +102 -0
  97. package/src/components/custom/ActiveWork/file-history-fixture.ts +91 -0
  98. package/src/components/custom/ActiveWork/format-time.test.ts +23 -0
  99. package/src/components/custom/ActiveWork/format-time.ts +32 -0
  100. package/src/components/custom/ActiveWork/index.ts +19 -0
  101. package/src/components/custom/ActiveWork/initiative-fixture.ts +104 -0
  102. package/src/components/custom/ActiveWork/session-fixture.ts +267 -0
  103. package/src/components/custom/ActiveWork/session-linkers.ts +56 -0
  104. package/src/components/custom/ActiveWork/task-list-fixture.ts +97 -0
  105. package/src/components/custom/CircularTimer/CircularTimer.stories.tsx +4 -3
  106. package/src/components/custom/DateTime/DateTime.stories.tsx +2 -1
  107. package/src/components/custom/DateTime/DateTime.test.tsx +3 -1
  108. package/src/components/custom/EmptyState/EmptyState.stories.tsx +22 -9
  109. package/src/components/custom/EmptyState/EmptyState.test.tsx +7 -13
  110. package/src/components/custom/EmptyState/EmptyState.tsx +4 -18
  111. package/src/components/custom/Fatigue/DualGhostSpark.stories.tsx +4 -3
  112. package/src/components/custom/Fatigue/FatigueLights.stories.tsx +2 -2
  113. package/src/components/custom/Fatigue/GhostSpark.stories.tsx +4 -3
  114. package/src/components/custom/Fatigue/LiveFatigueCard.stories.tsx +2 -2
  115. package/src/components/custom/Fatigue/LiveFatigueCard.tsx +8 -4
  116. package/src/components/custom/Fatigue/LiveFatiguePanel.stories.tsx +116 -6
  117. package/src/components/custom/Fatigue/LiveFatiguePanel.test.tsx +134 -0
  118. package/src/components/custom/Fatigue/LiveFatiguePanel.tsx +54 -83
  119. package/src/components/custom/Fatigue/README.md +40 -3
  120. package/src/components/custom/Fatigue/RomProgressionChart.stories.tsx +2 -2
  121. package/src/components/custom/Fatigue/SilverRedPalette.stories.tsx +2 -1
  122. package/src/components/custom/Fatigue/VelocityHero.stories.tsx +4 -3
  123. package/src/components/custom/Fatigue/VerdictHero.stories.tsx +2 -2
  124. package/src/components/custom/Fatigue/fatigue-mock.test.ts +0 -5
  125. package/src/components/custom/Fatigue/fatigue-mock.ts +2 -10
  126. package/src/components/custom/Fatigue/fatigue-tokens.ts +12 -0
  127. package/src/components/custom/Fatigue/index.ts +17 -5
  128. package/src/components/custom/Fatigue/panel-layout.test.ts +149 -0
  129. package/src/components/custom/Fatigue/panel-layout.ts +185 -0
  130. package/src/components/custom/Gauge/Gauge.stories.tsx +2 -2
  131. package/src/components/custom/Gauge/Gauge.test.tsx +1 -1
  132. package/src/components/custom/Gauge/Gauge.tsx +4 -1
  133. package/src/components/custom/Metric/Metric.stories.tsx +10 -1
  134. package/src/components/custom/Metric/Metric.test.tsx +1 -3
  135. package/src/components/custom/Metric/Metric.tsx +5 -20
  136. package/src/components/custom/Prose/MarkdownProse.stories.tsx +88 -0
  137. package/src/components/custom/Prose/MarkdownProse.test.tsx +87 -0
  138. package/src/components/custom/Prose/MarkdownProse.tsx +201 -0
  139. package/src/components/custom/Prose/README.md +58 -0
  140. package/src/components/custom/Prose/index.ts +1 -0
  141. package/src/components/custom/Scatter/Scatter.stories.tsx +46 -8
  142. package/src/components/custom/Scatter/Scatter.test.tsx +2 -2
  143. package/src/components/custom/Scatter/Scatter.tsx +116 -14
  144. package/src/components/custom/Sidebar/Sidebar.stories.tsx +40 -7
  145. package/src/components/custom/Sidebar/Sidebar.test.tsx +5 -1
  146. package/src/components/custom/Sidebar/Sidebar.tsx +16 -33
  147. package/src/components/custom/Table/Table.stories.tsx +98 -15
  148. package/src/components/custom/Table/Table.test.tsx +273 -86
  149. package/src/components/custom/Table/Table.tsx +159 -67
  150. package/src/components/custom/Table/column-fit.test.ts +75 -0
  151. package/src/components/custom/Table/column-fit.ts +116 -0
  152. package/src/components/custom/Table/index.ts +9 -0
  153. package/src/components/custom/TimerReadout/TimerReadout.stories.tsx +8 -6
  154. package/src/components/custom/Treemap/Treemap.stories.tsx +2 -2
  155. package/src/components/custom/Treemap/Treemap.test.tsx +1 -1
  156. package/src/components/custom/Treemap/Treemap.tsx +7 -2
  157. package/src/components/custom/Typography/Typography.stories.tsx +28 -1
  158. package/src/components/custom/Typography/Typography.test.tsx +34 -0
  159. package/src/components/custom/Typography/Typography.tsx +6 -0
  160. package/src/components/custom/Typography/index.ts +1 -8
  161. package/src/components/custom/Workout/ActiveWorkoutPage.stories.tsx +9 -1
  162. package/src/components/custom/Workout/BaseBadge.stories.tsx +19 -7
  163. package/src/components/custom/Workout/BaseBadge.test.tsx +31 -11
  164. package/src/components/custom/Workout/BaseBadge.tsx +3 -0
  165. package/src/components/custom/Workout/BodyMap.stories.tsx +4 -1
  166. package/src/components/custom/Workout/BodyMap.tsx +3 -1
  167. package/src/components/custom/Workout/BodyMapDetailPanel.stories.tsx +16 -4
  168. package/src/components/custom/Workout/BodyMapDetailPanel.test.tsx +11 -15
  169. package/src/components/custom/Workout/BodyMapDetailPanel.tsx +45 -9
  170. package/src/components/custom/Workout/CapacityBandChart.stories.tsx +10 -8
  171. package/src/components/custom/Workout/CapacityBandChart.test.tsx +24 -51
  172. package/src/components/custom/Workout/CapacityBandChart.tsx +139 -108
  173. package/src/components/custom/Workout/DeviationBar.stories.tsx +1 -1
  174. package/src/components/custom/Workout/DeviationBar.test.tsx +5 -2
  175. package/src/components/custom/Workout/DeviationBar.tsx +21 -16
  176. package/src/components/custom/Workout/DualVelocityStrip.stories.tsx +182 -0
  177. package/src/components/custom/Workout/DualVelocityStrip.test.tsx +3 -2
  178. package/src/components/custom/Workout/ExerciseCard.stories.tsx +8 -7
  179. package/src/components/custom/Workout/ExerciseCard.test.tsx +13 -3
  180. package/src/components/custom/Workout/ExerciseCard.tsx +42 -51
  181. package/src/components/custom/Workout/ExerciseCardHeading.stories.tsx +7 -7
  182. package/src/components/custom/Workout/ExerciseDetailPage.stories.tsx +9 -1
  183. package/src/components/custom/Workout/ExerciseHeading.stories.tsx +8 -8
  184. package/src/components/custom/Workout/ExerciseHeading.tsx +8 -5
  185. package/src/components/custom/Workout/ExerciseIndicator.stories.tsx +6 -4
  186. package/src/components/custom/Workout/ExerciseIndicator.test.tsx +27 -11
  187. package/src/components/custom/Workout/ExerciseIndicator.tsx +14 -15
  188. package/src/components/custom/Workout/FatigueMeter.stories.tsx +5 -5
  189. package/src/components/custom/Workout/InputBar.stories.tsx +4 -5
  190. package/src/components/custom/Workout/IntensityBar.stories.tsx +1 -1
  191. package/src/components/custom/Workout/IntensityBar.test.tsx +5 -1
  192. package/src/components/custom/Workout/IntensityBar.tsx +4 -2
  193. package/src/components/custom/Workout/LiveAuraFrame.stories.tsx +5 -4
  194. package/src/components/custom/Workout/MesoCard.stories.tsx +4 -1
  195. package/src/components/custom/Workout/MesoCard.test.tsx +7 -18
  196. package/src/components/custom/Workout/MesoCard.tsx +12 -9
  197. package/src/components/custom/Workout/MesoProgressBar.stories.tsx +1 -1
  198. package/src/components/custom/Workout/MesoProgressBar.test.tsx +18 -11
  199. package/src/components/custom/Workout/MesoProgressBar.tsx +15 -13
  200. package/src/components/custom/Workout/MesoStatusCard.stories.tsx +2 -1
  201. package/src/components/custom/Workout/MesoStatusCard.test.tsx +14 -44
  202. package/src/components/custom/Workout/MesoStatusCard.tsx +9 -23
  203. package/src/components/custom/Workout/MetricTiles.stories.tsx +3 -2
  204. package/src/components/custom/Workout/MuscleGroupChip.stories.tsx +2 -8
  205. package/src/components/custom/Workout/MuscleGroupChip.test.tsx +23 -31
  206. package/src/components/custom/Workout/MuscleGroupChip.tsx +28 -67
  207. package/src/components/custom/Workout/PlaceholderStrip.stories.tsx +1 -1
  208. package/src/components/custom/Workout/PlaceholderStrip.test.tsx +17 -10
  209. package/src/components/custom/Workout/PlaceholderStrip.tsx +9 -8
  210. package/src/components/custom/Workout/PrBadge.stories.tsx +2 -1
  211. package/src/components/custom/Workout/PrBadge.test.tsx +3 -9
  212. package/src/components/custom/Workout/PrBadge.tsx +13 -17
  213. package/src/components/custom/Workout/PrHistoryModal.stories.tsx +4 -1
  214. package/src/components/custom/Workout/PrHistoryModal.test.tsx +13 -36
  215. package/src/components/custom/Workout/PrHistoryModal.tsx +8 -4
  216. package/src/components/custom/Workout/ProgramPlanningPage.stories.tsx +6 -1
  217. package/src/components/custom/Workout/README.md +11 -6
  218. package/src/components/custom/Workout/ReadinessCheck.stories.tsx +3 -2
  219. package/src/components/custom/Workout/ReadinessCheck.test.tsx +12 -18
  220. package/src/components/custom/Workout/ReadinessCheck.tsx +19 -3
  221. package/src/components/custom/Workout/RestTimer.stories.tsx +3 -2
  222. package/src/components/custom/Workout/ScheduleTiles.stories.tsx +3 -2
  223. package/src/components/custom/Workout/ScheduleTiles.test.tsx +3 -4
  224. package/src/components/custom/Workout/ScheduleTiles.tsx +4 -7
  225. package/src/components/custom/Workout/SegmentedBar.stories.tsx +5 -5
  226. package/src/components/custom/Workout/SegmentedBar.tsx +6 -2
  227. package/src/components/custom/Workout/SegmentedProgressBar.stories.tsx +5 -5
  228. package/src/components/custom/Workout/SessionHeader.stories.tsx +6 -6
  229. package/src/components/custom/Workout/SessionHeader.tsx +12 -12
  230. package/src/components/custom/Workout/SessionRail.stories.tsx +12 -11
  231. package/src/components/custom/Workout/SessionRail.tsx +7 -9
  232. package/src/components/custom/Workout/SetBar.stories.tsx +10 -6
  233. package/src/components/custom/Workout/SetBar.test.tsx +49 -4
  234. package/src/components/custom/Workout/SetBar.tsx +38 -12
  235. package/src/components/custom/Workout/SetRow.stories.tsx +3 -2
  236. package/src/components/custom/Workout/SetRow.test.tsx +16 -2
  237. package/src/components/custom/Workout/SetRow.tsx +61 -23
  238. package/src/components/custom/Workout/SetStrip.stories.tsx +60 -5
  239. package/src/components/custom/Workout/SetStrip.test.tsx +25 -0
  240. package/src/components/custom/Workout/SetStrip.tsx +24 -4
  241. package/src/components/custom/Workout/SetTableHeader.stories.tsx +6 -6
  242. package/src/components/custom/Workout/SetTableHeader.tsx +9 -12
  243. package/src/components/custom/Workout/SetsRepsLoad.stories.tsx +7 -7
  244. package/src/components/custom/Workout/SetsRepsLoad.tsx +3 -5
  245. package/src/components/custom/Workout/Sparkline.stories.tsx +1 -1
  246. package/src/components/custom/Workout/Sparkline.test.tsx +37 -19
  247. package/src/components/custom/Workout/Sparkline.tsx +14 -18
  248. package/src/components/custom/Workout/StatusDot.stories.tsx +1 -1
  249. package/src/components/custom/Workout/StatusDot.test.tsx +44 -5
  250. package/src/components/custom/Workout/StatusDot.tsx +93 -63
  251. package/src/components/custom/Workout/StatusPill.stories.tsx +1 -1
  252. package/src/components/custom/Workout/StatusPill.test.tsx +6 -15
  253. package/src/components/custom/Workout/StatusPill.tsx +27 -38
  254. package/src/components/custom/Workout/StrengthTrendChart.stories.tsx +9 -3
  255. package/src/components/custom/Workout/StrengthTrendChart.test.tsx +15 -37
  256. package/src/components/custom/Workout/StrengthTrendChart.tsx +31 -30
  257. package/src/components/custom/Workout/SupersetWrapper.stories.tsx +27 -64
  258. package/src/components/custom/Workout/SupersetWrapper.test.tsx +16 -14
  259. package/src/components/custom/Workout/SupersetWrapper.tsx +17 -21
  260. package/src/components/custom/Workout/TempoDisplay.stories.tsx +22 -7
  261. package/src/components/custom/Workout/TempoDisplay.test.tsx +18 -4
  262. package/src/components/custom/Workout/TrainingStatusPage.stories.tsx +9 -1
  263. package/src/components/custom/Workout/VelocityStrip.compact.stories.tsx +4 -1
  264. package/src/components/custom/Workout/VelocityStrip.dual.stories.tsx +7 -4
  265. package/src/components/custom/Workout/VelocityStrip.expanded.stories.tsx +4 -1
  266. package/src/components/custom/Workout/VelocityStrip.hero.stories.tsx +4 -1
  267. package/src/components/custom/Workout/VelocityStrip.stories.tsx +12 -6
  268. package/src/components/custom/Workout/VelocityStrip.tsx +3 -0
  269. package/src/components/custom/Workout/VolumeLandmarkBar.stories.tsx +6 -7
  270. package/src/components/custom/Workout/VolumeLandmarkBar.tsx +15 -6
  271. package/src/components/custom/Workout/WeekRow.stories.tsx +4 -1
  272. package/src/components/custom/Workout/WeekRow.test.tsx +18 -15
  273. package/src/components/custom/Workout/WeekRow.tsx +23 -16
  274. package/src/components/custom/Workout/WeightBadge.stories.tsx +2 -1
  275. package/src/components/custom/Workout/WeightBadge.test.tsx +50 -19
  276. package/src/components/custom/Workout/WeightBadge.tsx +28 -27
  277. package/src/components/custom/Workout/WorkoutCard.stories.tsx +6 -1
  278. package/src/components/custom/Workout/WorkoutCard.test.tsx +18 -0
  279. package/src/components/custom/Workout/WorkoutCard.tsx +35 -57
  280. package/src/components/custom/Workout/WorkoutPill.stories.tsx +5 -2
  281. package/src/components/custom/Workout/WorkoutPill.test.tsx +39 -7
  282. package/src/components/custom/Workout/WorkoutPill.tsx +88 -57
  283. package/src/components/custom/Workout/ZoneTrack.stories.tsx +7 -6
  284. package/src/components/custom/Workout/ZoneTrack.tsx +10 -9
  285. package/src/components/custom/Workout/index.ts +5 -0
  286. package/src/components/custom/Workout/metricText.stories.tsx +6 -5
  287. package/src/components/custom/Workout/metricText.tsx +4 -0
  288. package/src/components/custom/Workout/setHeadingKit.tsx +207 -26
  289. package/src/components/custom/charts/README.md +61 -0
  290. package/src/components/custom/charts/SetBarChart.test.tsx +30 -1
  291. package/src/components/custom/charts/SetBarChart.tsx +42 -4
  292. package/src/components/custom/charts/SparkBars.stories.tsx +55 -0
  293. package/src/components/custom/charts/SparkBars.test.tsx +69 -0
  294. package/src/components/custom/charts/SparkBars.tsx +85 -0
  295. package/src/components/custom/charts/index.ts +3 -0
  296. package/src/components/custom/index.ts +3 -0
  297. package/src/components/custom/stepper/Stepper.stories.tsx +13 -10
  298. package/src/components/custom/stepper/Stepper.test.tsx +1 -7
  299. package/src/components/custom/stepper/Stepper.tsx +13 -28
  300. package/src/components/icons/icons.stories.tsx +1 -1
  301. package/src/components/icons/icons.tsx +51 -0
  302. package/src/components/shell/AppShell.stories.tsx +150 -0
  303. package/src/components/shell/AppShell.test.tsx +70 -0
  304. package/src/components/shell/AppShell.tsx +90 -0
  305. package/src/components/shell/BrandLockup.stories.tsx +66 -5
  306. package/src/components/shell/BrandLockup.test.tsx +34 -1
  307. package/src/components/shell/BrandLockup.tsx +27 -11
  308. package/src/components/shell/NavItem.stories.tsx +4 -4
  309. package/src/components/shell/NavItem.test.tsx +17 -0
  310. package/src/components/shell/NavItem.tsx +17 -5
  311. package/src/components/shell/README.md +89 -26
  312. package/src/components/shell/SideNav.stories.tsx +38 -7
  313. package/src/components/shell/SideNav.test.tsx +16 -8
  314. package/src/components/shell/SideNav.tsx +17 -17
  315. package/src/components/shell/TopBar.stories.tsx +44 -19
  316. package/src/components/shell/TopBar.test.tsx +34 -12
  317. package/src/components/shell/TopBar.tsx +61 -40
  318. package/src/components/shell/brands.tsx +66 -0
  319. package/src/components/shell/index.ts +9 -8
  320. package/src/components/shell/{DeviceIndicator.stories.tsx → workout/DeviceIndicator.stories.tsx} +2 -2
  321. package/src/components/shell/{DeviceIndicator.tsx → workout/DeviceIndicator.tsx} +2 -2
  322. package/src/components/shell/{DeviceMenu.stories.tsx → workout/DeviceMenu.stories.tsx} +2 -2
  323. package/src/components/shell/{DeviceMenu.tsx → workout/DeviceMenu.tsx} +3 -3
  324. package/src/components/shell/{DeviceRow.stories.tsx → workout/DeviceRow.stories.tsx} +2 -2
  325. package/src/components/shell/{DeviceRow.tsx → workout/DeviceRow.tsx} +3 -3
  326. package/src/components/shell/{SessionStatePill.stories.tsx → workout/SessionStatePill.stories.tsx} +2 -2
  327. package/src/components/shell/{SessionStatePill.tsx → workout/SessionStatePill.tsx} +5 -3
  328. package/src/components/shell/workout/WorkoutShell.stories.tsx +71 -0
  329. package/src/components/shell/{DashboardShell.test.tsx → workout/WorkoutShell.test.tsx} +19 -8
  330. package/src/components/shell/workout/WorkoutShell.tsx +77 -0
  331. package/src/components/shell/workout/WorkoutTopBar.stories.tsx +58 -0
  332. package/src/components/shell/workout/WorkoutTopBar.test.tsx +39 -0
  333. package/src/components/shell/workout/WorkoutTopBar.tsx +52 -0
  334. package/src/components/shell/workout/index.ts +9 -0
  335. package/src/components/shell/workout/workoutNavItems.tsx +16 -0
  336. package/src/components/ui/README.md +110 -0
  337. package/src/components/ui/alert/Alert.stories.tsx +1 -1
  338. package/src/components/ui/autocomplete/Autocomplete.stories.tsx +11 -13
  339. package/src/components/ui/autocomplete/Autocomplete.test.tsx +7 -25
  340. package/src/components/ui/autocomplete/Autocomplete.tsx +21 -28
  341. package/src/components/ui/avatar/Avatar.stories.tsx +1 -1
  342. package/src/components/ui/avatar/Avatar.tsx +2 -10
  343. package/src/components/ui/badge/Badge.stories.tsx +83 -28
  344. package/src/components/ui/badge/Badge.test.tsx +19 -3
  345. package/src/components/ui/badge/Badge.tsx +48 -55
  346. package/src/components/ui/breadcrumbs/Breadcrumbs.stories.tsx +1 -1
  347. package/src/components/ui/breadcrumbs/Breadcrumbs.tsx +4 -16
  348. package/src/components/ui/button/Button.stories.tsx +46 -12
  349. package/src/components/ui/button/Button.tsx +32 -25
  350. package/src/components/ui/card/Card.stories.tsx +90 -94
  351. package/src/components/ui/card/Card.test.tsx +80 -6
  352. package/src/components/ui/card/Card.tsx +150 -203
  353. package/src/components/ui/checkbox/Checkbox.stories.tsx +1 -1
  354. package/src/components/ui/checkbox/Checkbox.tsx +6 -26
  355. package/src/components/ui/chip/Chip.stories.tsx +37 -13
  356. package/src/components/ui/chip/Chip.test.tsx +10 -6
  357. package/src/components/ui/chip/Chip.tsx +76 -91
  358. package/src/components/ui/collapse/Collapse.stories.tsx +23 -23
  359. package/src/components/ui/collapse/Collapse.tsx +6 -11
  360. package/src/components/ui/data-row/DataRow.stories.tsx +9 -2
  361. package/src/components/ui/data-row/DataRow.test.tsx +5 -15
  362. package/src/components/ui/data-row/DataRow.tsx +18 -7
  363. package/src/components/ui/divider/Divider.stories.tsx +1 -1
  364. package/src/components/ui/divider/Divider.tsx +1 -5
  365. package/src/components/ui/drawer/Drawer.stories.tsx +5 -16
  366. package/src/components/ui/drawer/Drawer.tsx +13 -30
  367. package/src/components/ui/floating-overlay-depth.test.tsx +143 -0
  368. package/src/components/ui/form-field/FormField.stories.tsx +6 -20
  369. package/src/components/ui/form-field/FormField.test.tsx +1 -5
  370. package/src/components/ui/form-field/FormField.tsx +10 -46
  371. package/src/components/ui/help-tip/HelpTip.stories.tsx +8 -19
  372. package/src/components/ui/help-tip/HelpTip.test.tsx +1 -3
  373. package/src/components/ui/help-tip/HelpTip.tsx +21 -22
  374. package/src/components/ui/help-tip/index.ts +7 -1
  375. package/src/components/ui/icon-box/IconBox.stories.tsx +1 -1
  376. package/src/components/ui/icon-box/IconBox.test.tsx +1 -7
  377. package/src/components/ui/icon-box/IconBox.tsx +2 -12
  378. package/src/components/ui/indicator/Indicator.stories.tsx +1 -1
  379. package/src/components/ui/indicator/Indicator.tsx +20 -14
  380. package/src/components/ui/input/Input.stories.tsx +3 -11
  381. package/src/components/ui/input/Input.test.tsx +2 -10
  382. package/src/components/ui/input/Input.tsx +10 -25
  383. package/src/components/ui/input/index.ts +7 -1
  384. package/src/components/ui/link/Link.stories.tsx +19 -7
  385. package/src/components/ui/list-item/ListItem.stories.tsx +11 -2
  386. package/src/components/ui/list-item/ListItem.tsx +2 -9
  387. package/src/components/ui/menu/Menu.stories.tsx +21 -15
  388. package/src/components/ui/menu/Menu.test.tsx +2 -11
  389. package/src/components/ui/menu/Menu.tsx +12 -14
  390. package/src/components/ui/menu/index.ts +8 -1
  391. package/src/components/ui/modal/Modal.stories.tsx +2 -2
  392. package/src/components/ui/modal/Modal.tsx +29 -19
  393. package/src/components/ui/pill/Pill.stories.tsx +58 -23
  394. package/src/components/ui/pill/Pill.test.tsx +101 -3
  395. package/src/components/ui/pill/Pill.tsx +164 -49
  396. package/src/components/ui/pill/index.ts +1 -1
  397. package/src/components/ui/popover/Popover.stories.tsx +5 -7
  398. package/src/components/ui/popover/Popover.test.tsx +1 -6
  399. package/src/components/ui/popover/Popover.tsx +20 -15
  400. package/src/components/ui/popover/index.ts +7 -1
  401. package/src/components/ui/progress/Progress.stories.tsx +3 -12
  402. package/src/components/ui/progress/Progress.test.tsx +1 -5
  403. package/src/components/ui/radio/Radio.stories.tsx +42 -21
  404. package/src/components/ui/radio/Radio.test.tsx +6 -2
  405. package/src/components/ui/radio/Radio.tsx +23 -22
  406. package/src/components/ui/section/Section.stories.tsx +5 -14
  407. package/src/components/ui/section/Section.test.tsx +1 -6
  408. package/src/components/ui/section/Section.tsx +1 -3
  409. package/src/components/ui/section/index.ts +1 -5
  410. package/src/components/ui/select/Select.stories.tsx +3 -13
  411. package/src/components/ui/select/Select.test.tsx +2 -11
  412. package/src/components/ui/select/Select.tsx +14 -14
  413. package/src/components/ui/skeleton/Skeleton.stories.tsx +3 -11
  414. package/src/components/ui/skeleton/Skeleton.tsx +3 -14
  415. package/src/components/ui/skeleton/index.ts +1 -7
  416. package/src/components/ui/spinner/Spinner.stories.tsx +1 -1
  417. package/src/components/ui/spinner/Spinner.tsx +1 -4
  418. package/src/components/ui/stack/Stack.stories.tsx +1 -1
  419. package/src/components/ui/stack/Stack.tsx +1 -1
  420. package/src/components/ui/surface/Surface.stories.tsx +17 -5
  421. package/src/components/ui/surface/Surface.test.tsx +88 -28
  422. package/src/components/ui/surface/Surface.tsx +37 -87
  423. package/src/components/ui/surface/SurfaceContext.ts +22 -62
  424. package/src/components/ui/surface/index.ts +8 -0
  425. package/src/components/ui/surface/resolveSurface.ts +98 -0
  426. package/src/components/ui/surface/surface.contract.test.ts +6 -1
  427. package/src/components/ui/switch/Switch.stories.tsx +1 -1
  428. package/src/components/ui/switch/Switch.tsx +7 -6
  429. package/src/components/ui/tabs/Tabs.stories.tsx +1 -1
  430. package/src/components/ui/tabs/Tabs.tsx +7 -22
  431. package/src/components/ui/tabs/index.ts +1 -7
  432. package/src/components/ui/tile/Tile.stories.tsx +1 -1
  433. package/src/components/ui/tile/Tile.tsx +3 -0
  434. package/src/components/ui/toast/Toast.stories.tsx +1 -1
  435. package/src/components/ui/toast/Toast.test.tsx +2 -8
  436. package/src/components/ui/toast/Toast.tsx +43 -53
  437. package/src/components/ui/toast/index.ts +0 -1
  438. package/src/components/ui/toolbar-button/ToolbarButton.stories.tsx +92 -71
  439. package/src/components/ui/toolbar-button/ToolbarButton.test.tsx +3 -18
  440. package/src/components/ui/toolbar-button/ToolbarButton.tsx +25 -43
  441. package/src/components/ui/tooltip/Tooltip.stories.tsx +12 -3
  442. package/src/components/ui/tooltip/Tooltip.test.tsx +21 -3
  443. package/src/components/ui/tooltip/Tooltip.tsx +55 -36
  444. package/src/components/ui/tooltip/index.ts +1 -1
  445. package/src/components/ui/trigger/TriggerSurface.test.tsx +215 -0
  446. package/src/components/ui/trigger/TriggerSurface.tsx +81 -0
  447. package/src/components/ui/trigger/index.ts +2 -0
  448. package/src/stories/PresetShowcase.stories.tsx +100 -47
  449. package/src/test/no-device-internals.test.ts +3 -3
  450. package/src/theme/ChoosingTokens.stories.tsx +48 -0
  451. package/src/theme/ColorPalettes.stories.tsx +62 -45
  452. package/src/theme/ColorPrimitives.stories.tsx +35 -35
  453. package/src/theme/Depth.stories.tsx +132 -65
  454. package/src/theme/DepthCalibration.stories.tsx +23 -21
  455. package/src/theme/ThemeProvider.test.tsx +4 -4
  456. package/src/theme/barrel.ts +7 -6
  457. package/src/theme/color-stories.coverage.test.ts +1 -1
  458. package/src/theme/color-utils.ts +41 -29
  459. package/src/theme/config.completeness.test.ts +1 -1
  460. package/src/theme/config.ts +28 -0
  461. package/src/theme/elevation.test.ts +82 -56
  462. package/src/theme/elevation.ts +77 -561
  463. package/src/theme/global.css +30 -2
  464. package/src/theme/grey-ramp.test.ts +24 -8
  465. package/src/theme/lift.test.ts +39 -0
  466. package/src/theme/lift.ts +102 -0
  467. package/src/theme/materials.test.ts +5 -2
  468. package/src/theme/materials.ts +38 -4
  469. package/src/theme/native-theming-guard.test.ts +5 -5
  470. package/src/theme/presets/apply.ts +4 -0
  471. package/src/theme/presets/audiobook.ts +5 -2
  472. package/src/theme/presets/default.ts +4 -0
  473. package/src/theme/presets/index.ts +14 -1
  474. package/src/theme/presets/types.ts +1 -1
  475. package/src/theme/semantic-contrast.test.ts +13 -4
  476. package/src/theme/status-distinctness.test.ts +66 -0
  477. package/src/theme/surface-planes.test.ts +37 -0
  478. package/src/theme/surface-planes.ts +68 -0
  479. package/src/theme/token-export-guard.test.ts +1 -3
  480. package/src/theme/tokens/primitives.test.ts +15 -7
  481. package/src/theme/tokens/primitives.ts +65 -33
  482. package/src/theme/tokens/semantic.ts +71 -37
  483. package/src/theme/wash-ladder.test.ts +58 -0
  484. package/src/theme/workout-tokens.ts +1 -7
  485. package/src/types/jest-axe.d.ts +2 -6
  486. package/src/types/raw-md.d.ts +5 -0
  487. package/src/utils/colors.ts +4 -4
  488. package/src/utils/form.ts +1 -3
  489. package/src/utils/index.ts +2 -7
  490. package/src/utils/number-format.ts +17 -0
  491. package/src/utils/workout-format.ts +15 -6
  492. package/src/web-jsx/jsx-runtime.ts +1 -5
  493. package/tailwind.config.js +5 -0
  494. package/src/components/custom/Workout/ExerciseCardUnified.stories.tsx +0 -151
  495. package/src/components/custom/Workout/RowInventory.stories.tsx +0 -408
  496. package/src/components/custom/Workout/S3FullRail.stories.tsx +0 -46
  497. package/src/components/custom/Workout/S3SessionPace.stories.tsx +0 -95
  498. package/src/components/custom/Workout/S3SessionRailHeading.stories.tsx +0 -61
  499. package/src/components/custom/Workout/S3SetTypes.stories.tsx +0 -176
  500. package/src/components/custom/Workout/S3WorkoutExpansion.stories.tsx +0 -240
  501. package/src/components/shell/DashboardShell.stories.tsx +0 -65
  502. package/src/components/shell/DashboardShell.tsx +0 -75
  503. package/src/components/shell/SessionRailSpecimen.stories.tsx +0 -753
  504. package/src/theme/elevation.stories.tsx +0 -346
  505. package/src/utils/useTheme.ts +0 -72
  506. /package/src/components/shell/{DeviceIndicator.test.tsx → workout/DeviceIndicator.test.tsx} +0 -0
  507. /package/src/components/shell/{DeviceMenu.test.tsx → workout/DeviceMenu.test.tsx} +0 -0
  508. /package/src/components/shell/{DeviceRow.test.tsx → workout/DeviceRow.test.tsx} +0 -0
  509. /package/src/components/shell/{SessionStatePill.test.tsx → workout/SessionStatePill.test.tsx} +0 -0
@@ -1,9 +1,17 @@
1
1
  import React from 'react'
2
2
  import { View, Text, Pressable, type ViewProps } from 'react-native'
3
3
  import { cn } from '../../../utils/cn'
4
+ import { Pill, type PillTone, type PillVariant } from '../pill'
4
5
 
5
6
  export type ChipVariant = 'solid' | 'subtle' | 'outline'
6
- export type ChipColor = 'default' | 'primary' | 'secondary' | 'success' | 'error' | 'warning' | 'info'
7
+ export type ChipColor =
8
+ | 'default'
9
+ | 'primary'
10
+ | 'secondary'
11
+ | 'success'
12
+ | 'error'
13
+ | 'warning'
14
+ | 'info'
7
15
  export type ChipSize = 'sm' | 'md' | 'lg'
8
16
 
9
17
  export interface ChipProps extends ViewProps {
@@ -26,52 +34,53 @@ export interface ChipProps extends ViewProps {
26
34
  children?: React.ReactNode
27
35
  }
28
36
 
29
- const colorStyles: Record<ChipColor, Record<ChipVariant, string>> = {
30
- default: {
31
- solid: 'bg-neutral-600 text-white',
32
- subtle: 'bg-neutral-100 text-neutral-700 dark:bg-neutral-800 dark:text-neutral-200',
33
- outline: 'border border-neutral-300 dark:border-neutral-600 text-neutral-700 dark:text-neutral-200',
34
- },
35
- primary: {
36
- solid: 'bg-brand-primary text-white',
37
- subtle: 'bg-brand-primary-subtle text-brand-primary',
38
- outline: 'border border-brand-primary text-brand-primary',
39
- },
40
- secondary: {
41
- solid: 'bg-brand-secondary text-white',
42
- subtle: 'bg-brand-secondary-subtle text-brand-secondary',
43
- outline: 'border border-brand-secondary text-brand-secondary',
44
- },
45
- success: {
46
- solid: 'bg-status-success text-white',
47
- subtle: 'bg-status-success-subtle text-status-success',
48
- outline: 'border border-status-success text-status-success',
49
- },
50
- error: {
51
- solid: 'bg-status-error text-white',
52
- subtle: 'bg-status-error-subtle text-status-error',
53
- outline: 'border border-status-error text-status-error',
54
- },
55
- warning: {
56
- solid: 'bg-status-warning text-white',
57
- subtle: 'bg-status-warning-subtle text-status-warning',
58
- outline: 'border border-status-warning text-status-warning',
59
- },
60
- info: {
61
- solid: 'bg-status-info text-white',
62
- subtle: 'bg-status-info-subtle text-status-info',
63
- outline: 'border border-status-info text-status-info',
64
- },
37
+ const colorToTone: Record<ChipColor, PillTone> = {
38
+ default: 'neutral',
39
+ primary: 'brand',
40
+ secondary: 'brand-secondary',
41
+ success: 'success',
42
+ error: 'error',
43
+ warning: 'warning',
44
+ info: 'info',
65
45
  }
66
46
 
47
+ /** Chip keeps its own geometry and squared corners; Pill supplies the rest. */
67
48
  const sizeStyles: Record<ChipSize, { container: string; text: string; deleteButton: string }> = {
68
49
  sm: { container: 'px-2 py-0.5 rounded', text: 'text-xs', deleteButton: 'ml-1 -mr-0.5' },
69
50
  md: { container: 'px-3 py-1 rounded-md', text: 'text-sm', deleteButton: 'ml-1.5 -mr-1' },
70
51
  lg: { container: 'px-4 py-1.5 rounded-md', text: 'text-base', deleteButton: 'ml-2 -mr-1' },
71
52
  }
72
53
 
54
+ function DeleteButton({
55
+ onDelete,
56
+ isDisabled,
57
+ className,
58
+ }: {
59
+ onDelete: () => void
60
+ isDisabled: boolean
61
+ className: string
62
+ }) {
63
+ return (
64
+ <Pressable
65
+ onPress={(e) => {
66
+ e.stopPropagation?.()
67
+ onDelete()
68
+ }}
69
+ accessibilityRole="button"
70
+ accessibilityLabel="Remove"
71
+ disabled={isDisabled}
72
+ className={cn(
73
+ className,
74
+ 'rounded-full p-0.5 web:hover:bg-hairline-subtle active:bg-hairline-strong'
75
+ )}
76
+ >
77
+ <Text className="text-xs leading-none text-inherit">×</Text>
78
+ </Pressable>
79
+ )
80
+ }
81
+
73
82
  /**
74
- * Chip component for tags, labels, and filters.
83
+ * Chip a `Pill` preset for tags, labels, and filters.
75
84
  *
76
85
  * @example
77
86
  * <Chip>Default</Chip>
@@ -92,60 +101,36 @@ export function Chip({
92
101
  ...props
93
102
  }: ChipProps) {
94
103
  const sizes = sizeStyles[size]
95
- const isClickable = !!onPress
96
-
97
- const content = (
98
- <>
99
- {leftElement && <View className="mr-1.5">{leftElement}</View>}
100
- <Text className={cn('font-medium', sizes.text)}>
101
- {children}
102
- </Text>
103
- {onDelete && (
104
- <Pressable
105
- onPress={(e) => {
106
- e.stopPropagation?.()
107
- onDelete()
108
- }}
109
- accessibilityRole="button"
110
- accessibilityLabel="Remove"
111
- disabled={isDisabled}
112
- className={cn(
113
- sizes.deleteButton,
114
- 'rounded-full p-0.5 web:hover:bg-black/10 active:bg-black/20'
115
- )}
116
- >
117
- <Text className="text-xs leading-none">×</Text>
118
- </Pressable>
119
- )}
120
- </>
121
- )
122
-
123
- const baseClassName = cn(
124
- 'flex-row items-center',
125
- sizes.container,
126
- colorStyles[color][variant],
127
- isClickable && 'web:cursor-pointer web:hover:opacity-80 active:opacity-70',
128
- isDisabled && 'opacity-50 cursor-not-allowed',
129
- className
130
- )
131
-
132
- if (isClickable) {
133
- return (
134
- <Pressable
135
- onPress={onPress}
136
- disabled={isDisabled}
137
- accessibilityRole="button"
138
- className={baseClassName}
139
- {...props}
140
- >
141
- {content}
142
- </Pressable>
143
- )
144
- }
145
104
 
146
105
  return (
147
- <View className={baseClassName} {...props}>
148
- {content}
149
- </View>
106
+ <Pill
107
+ variant={variant as PillVariant}
108
+ tone={colorToTone[color]}
109
+ rounded={false}
110
+ onPress={onPress}
111
+ isDisabled={isDisabled}
112
+ leading={leftElement && <View className="mr-1.5">{leftElement}</View>}
113
+ trailing={
114
+ onDelete && (
115
+ <DeleteButton
116
+ onDelete={onDelete}
117
+ isDisabled={isDisabled}
118
+ className={sizes.deleteButton}
119
+ />
120
+ )
121
+ }
122
+ className={cn(
123
+ 'self-auto gap-0',
124
+ variant === 'outline' ? 'border' : 'border-0',
125
+ sizes.container,
126
+ onPress && 'web:cursor-pointer web:hover:opacity-80 active:opacity-70',
127
+ isDisabled && 'cursor-not-allowed',
128
+ className
129
+ )}
130
+ textClassName={cn('font-sans font-medium', sizes.text)}
131
+ {...props}
132
+ >
133
+ {children}
134
+ </Pill>
150
135
  )
151
136
  }
@@ -14,7 +14,7 @@ import {
14
14
  const meta: Meta<typeof Accordion> = {
15
15
  title: 'Components/Organisms/Accordion',
16
16
  component: Accordion,
17
- tags: ['autodocs'],
17
+ tags: ['autodocs', 'status:stable', '!status:review'],
18
18
  argTypes: {
19
19
  allowMultiple: {
20
20
  control: 'boolean',
@@ -79,8 +79,8 @@ export const AllowMultiple: Story = {
79
79
  <AccordionButton>Section Two</AccordionButton>
80
80
  <AccordionPanel>
81
81
  <Text className="text-text-secondary text-sm">
82
- This section can be open alongside Section One. In single mode, opening a new
83
- section would close any previously open one.
82
+ This section can be open alongside Section One. In single mode, opening a new section
83
+ would close any previously open one.
84
84
  </Text>
85
85
  </AccordionPanel>
86
86
  </AccordionItem>
@@ -121,9 +121,7 @@ export const DefaultOpen: Story = {
121
121
  <AccordionItem>
122
122
  <AccordionButton>Also Closed</AccordionButton>
123
123
  <AccordionPanel>
124
- <Text className="text-text-secondary text-sm">
125
- Another closed section.
126
- </Text>
124
+ <Text className="text-text-secondary text-sm">Another closed section.</Text>
127
125
  </AccordionPanel>
128
126
  </AccordionItem>
129
127
  </Accordion>
@@ -146,9 +144,7 @@ export const MultipleDefaultOpen: Story = {
146
144
  <AccordionItem>
147
145
  <AccordionButton>Second (Closed)</AccordionButton>
148
146
  <AccordionPanel>
149
- <Text className="text-text-secondary text-sm">
150
- This section starts closed.
151
- </Text>
147
+ <Text className="text-text-secondary text-sm">This section starts closed.</Text>
152
148
  </AccordionPanel>
153
149
  </AccordionItem>
154
150
  <AccordionItem>
@@ -191,14 +187,18 @@ export const WithRichContent: Story = {
191
187
  <AccordionButton>Features Included</AccordionButton>
192
188
  <AccordionPanel>
193
189
  <View style={{ gap: 6 }}>
194
- {['Unlimited projects', 'Custom domains', 'Priority support', 'API access', 'Team collaboration'].map(
195
- (feature) => (
196
- <View key={feature} style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}>
197
- <Text className="text-status-success text-sm">&#10003;</Text>
198
- <Text className="text-text-primary text-sm">{feature}</Text>
199
- </View>
200
- )
201
- )}
190
+ {[
191
+ 'Unlimited projects',
192
+ 'Custom domains',
193
+ 'Priority support',
194
+ 'API access',
195
+ 'Team collaboration',
196
+ ].map((feature) => (
197
+ <View key={feature} style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}>
198
+ <Text className="text-status-success text-sm">&#10003;</Text>
199
+ <Text className="text-text-primary text-sm">{feature}</Text>
200
+ </View>
201
+ ))}
202
202
  </View>
203
203
  </AccordionPanel>
204
204
  </AccordionItem>
@@ -213,7 +213,9 @@ export const WithRichContent: Story = {
213
213
  </Text>
214
214
  </View>
215
215
  <View style={{ gap: 2 }}>
216
- <Text className="text-text-primary text-sm font-medium">Is there a free trial?</Text>
216
+ <Text className="text-text-primary text-sm font-medium">
217
+ Is there a free trial?
218
+ </Text>
217
219
  <Text className="text-text-secondary text-sm">
218
220
  We offer a 14-day free trial for all plans.
219
221
  </Text>
@@ -291,9 +293,7 @@ export const CollapseControlled: Story = {
291
293
  const [isOpen, setIsOpen] = useState(false)
292
294
  return (
293
295
  <View style={{ width: 400, gap: 8 }}>
294
- <Text className="text-sm text-text-secondary">
295
- State: {isOpen ? 'Open' : 'Closed'}
296
- </Text>
296
+ <Text className="text-sm text-text-secondary">State: {isOpen ? 'Open' : 'Closed'}</Text>
297
297
  <Collapse isOpen={isOpen} onToggle={setIsOpen}>
298
298
  <CollapseButton>
299
299
  <Text className="text-text-primary font-medium">Controlled Collapse</Text>
@@ -301,8 +301,8 @@ export const CollapseControlled: Story = {
301
301
  <CollapseContent>
302
302
  <View className="px-4 pb-3">
303
303
  <Text className="text-text-secondary text-sm">
304
- This collapse is controlled externally. The isOpen prop and onToggle callback
305
- manage state outside the component.
304
+ This collapse is controlled externally. The isOpen prop and onToggle callback manage
305
+ state outside the component.
306
306
  </Text>
307
307
  </View>
308
308
  </CollapseContent>
@@ -67,19 +67,22 @@ export function Collapse({
67
67
 
68
68
  export interface CollapseButtonProps {
69
69
  children?: React.ReactNode
70
+ /** Accessible name when the button carries no text of its own (a bare chevron). */
71
+ accessibilityLabel?: string
70
72
  className?: string
71
73
  }
72
74
 
73
75
  /**
74
76
  * Button to toggle collapse state.
75
77
  */
76
- export function CollapseButton({ children, className }: CollapseButtonProps) {
78
+ export function CollapseButton({ children, accessibilityLabel, className }: CollapseButtonProps) {
77
79
  const { isOpen, toggle } = useContext(CollapseContext)
78
80
 
79
81
  return (
80
82
  <Pressable
81
83
  onPress={toggle}
82
84
  accessibilityRole="button"
85
+ accessibilityLabel={accessibilityLabel}
83
86
  accessibilityState={{ expanded: isOpen }}
84
87
  className={cn(
85
88
  'flex-row items-center justify-between py-3 px-4',
@@ -108,11 +111,7 @@ export function CollapseContent({ children, className }: CollapseContentProps) {
108
111
 
109
112
  if (!isOpen) return null
110
113
 
111
- return (
112
- <View className={cn('overflow-hidden', className)}>
113
- {children}
114
- </View>
115
- )
114
+ return <View className={cn('overflow-hidden', className)}>{children}</View>
116
115
  }
117
116
 
118
117
  // Accordion component
@@ -267,9 +266,5 @@ export interface AccordionPanelProps {
267
266
  export function AccordionPanel({ isOpen = false, children, className }: AccordionPanelProps) {
268
267
  if (!isOpen) return null
269
268
 
270
- return (
271
- <View className={cn('pb-4 px-1', className)}>
272
- {children}
273
- </View>
274
- )
269
+ return <View className={cn('pb-4 px-1', className)}>{children}</View>
275
270
  }
@@ -5,7 +5,7 @@ import { DataRow } from './DataRow'
5
5
  const meta: Meta<typeof DataRow> = {
6
6
  title: 'Components/Molecules/DataRow',
7
7
  component: DataRow,
8
- tags: ['autodocs'],
8
+ tags: ['autodocs', 'status:stable', '!status:review'],
9
9
  argTypes: {
10
10
  label: {
11
11
  control: 'text',
@@ -40,7 +40,14 @@ export const WithCustomValue: Story = {
40
40
  <DataRow
41
41
  label="Status"
42
42
  value={
43
- <View style={{ backgroundColor: '#22c55e', borderRadius: 9999, paddingHorizontal: 8, paddingVertical: 2 }}>
43
+ <View
44
+ style={{
45
+ backgroundColor: '#22c55e',
46
+ borderRadius: 9999,
47
+ paddingHorizontal: 8,
48
+ paddingVertical: 2,
49
+ }}
50
+ >
44
51
  <Text style={{ color: '#fff', fontSize: 12, fontWeight: '600' }}>Active</Text>
45
52
  </View>
46
53
  }
@@ -11,9 +11,7 @@ describe('DataRow', () => {
11
11
  })
12
12
 
13
13
  it('renders label and ReactNode value', () => {
14
- render(
15
- <DataRow label="Status" value={<span data-testid="custom-node">Active</span>} />
16
- )
14
+ render(<DataRow label="Status" value={<span data-testid="custom-node">Active</span>} />)
17
15
  expect(screen.getByText('Status')).toBeInTheDocument()
18
16
  expect(screen.getByTestId('custom-node')).toBeInTheDocument()
19
17
  expect(screen.getByText('Active')).toBeInTheDocument()
@@ -34,24 +32,18 @@ describe('DataRow', () => {
34
32
  })
35
33
 
36
34
  it('applies custom className to root container', () => {
37
- const { container } = render(
38
- <DataRow label="Test" value="Value" className="bg-red-500" />
39
- )
35
+ const { container } = render(<DataRow label="Test" value="Value" className="bg-red-500" />)
40
36
  const root = container.firstChild as HTMLElement
41
37
  expect(root).toBeInTheDocument()
42
38
  })
43
39
 
44
40
  it('applies valueClassName to string value', () => {
45
- render(
46
- <DataRow label="Test" value="Value" valueClassName="text-lg" />
47
- )
41
+ render(<DataRow label="Test" value="Value" valueClassName="text-lg" />)
48
42
  expect(screen.getByText('Value')).toBeInTheDocument()
49
43
  })
50
44
 
51
45
  it('applies valueClassName to ReactNode wrapper', () => {
52
- render(
53
- <DataRow label="Test" value={<span>Node</span>} valueClassName="text-lg" />
54
- )
46
+ render(<DataRow label="Test" value={<span>Node</span>} valueClassName="text-lg" />)
55
47
  expect(screen.getByText('Node')).toBeInTheDocument()
56
48
  })
57
49
 
@@ -68,9 +60,7 @@ describe('DataRow', () => {
68
60
  })
69
61
 
70
62
  it('has no accessibility violations with ReactNode value', async () => {
71
- const { container } = render(
72
- <DataRow label="Status" value={<span>Active</span>} />
73
- )
63
+ const { container } = render(<DataRow label="Status" value={<span>Active</span>} />)
74
64
  const results = await axe(container)
75
65
  expect(results).toHaveNoViolations()
76
66
  })
@@ -3,24 +3,35 @@ import { View, Text, type ViewProps } from 'react-native'
3
3
  import { cn } from '../../../utils/cn'
4
4
 
5
5
  export interface DataRowProps extends ViewProps {
6
- /** Descriptive label shown on the left */
7
- label: string
6
+ /** Descriptive label shown on the left -- string renders as Text, ReactNode renders inside a View */
7
+ label: React.ReactNode
8
8
  /** Value shown on the right -- string renders as Text, ReactNode renders inside a View */
9
9
  value: React.ReactNode
10
+ /** Additional className applied to the label element */
11
+ labelClassName?: string
10
12
  /** Additional className applied to the value element */
11
13
  valueClassName?: string
12
14
  /** Additional className applied to the root container */
13
15
  className?: string
14
16
  }
15
17
 
16
- export function DataRow({ label, value, valueClassName, className, ...props }: DataRowProps) {
18
+ export function DataRow({
19
+ label,
20
+ value,
21
+ labelClassName,
22
+ valueClassName,
23
+ className,
24
+ ...props
25
+ }: DataRowProps) {
17
26
  return (
18
27
  <View className={cn('flex-row items-center justify-between py-2', className)} {...props}>
19
- <Text className="text-sm text-text-secondary">{label}</Text>
28
+ {typeof label === 'string' ? (
29
+ <Text className={cn('text-sm text-text-secondary', labelClassName)}>{label}</Text>
30
+ ) : (
31
+ <View className={cn(labelClassName)}>{label}</View>
32
+ )}
20
33
  {typeof value === 'string' ? (
21
- <Text className={cn('text-sm font-medium text-text-primary', valueClassName)}>
22
- {value}
23
- </Text>
34
+ <Text className={cn('text-sm font-medium text-text-primary', valueClassName)}>{value}</Text>
24
35
  ) : (
25
36
  <View className={cn(valueClassName)}>{value}</View>
26
37
  )}
@@ -5,7 +5,7 @@ import { Divider } from './Divider'
5
5
  const meta: Meta<typeof Divider> = {
6
6
  title: 'Components/Atoms/Divider',
7
7
  component: Divider,
8
- tags: ['autodocs'],
8
+ tags: ['autodocs', 'status:stable', '!status:review'],
9
9
  argTypes: {
10
10
  orientation: {
11
11
  control: 'select',
@@ -18,11 +18,7 @@ export interface DividerProps extends ViewProps {
18
18
  * <Divider />
19
19
  * <Divider orientation="vertical" />
20
20
  */
21
- export function Divider({
22
- orientation = 'horizontal',
23
- className,
24
- ...props
25
- }: DividerProps) {
21
+ export function Divider({ orientation = 'horizontal', className, ...props }: DividerProps) {
26
22
  return (
27
23
  <View
28
24
  accessibilityRole="none"
@@ -7,7 +7,7 @@ import { Button, ButtonText } from '../button'
7
7
  const meta: Meta<typeof Drawer> = {
8
8
  title: 'Components/Organisms/Drawer',
9
9
  component: Drawer,
10
- tags: ['autodocs'],
10
+ tags: ['autodocs', 'status:stable', '!status:review'],
11
11
  argTypes: {
12
12
  placement: {
13
13
  control: 'select',
@@ -37,11 +37,7 @@ export const Default: Story = {
37
37
  <Button onPress={() => setIsOpen(true)}>
38
38
  <ButtonText>Open Drawer</ButtonText>
39
39
  </Button>
40
- <Drawer
41
- isOpen={isOpen}
42
- onClose={() => setIsOpen(false)}
43
- title="Drawer Title"
44
- >
40
+ <Drawer isOpen={isOpen} onClose={() => setIsOpen(false)} title="Drawer Title">
45
41
  <DrawerBody>
46
42
  <Text className="text-text-primary">
47
43
  This is the drawer content. You can put any content here.
@@ -124,7 +120,7 @@ export const AllSizes: Story = {
124
120
  render: function Render() {
125
121
  const [openSize, setOpenSize] = useState<string | null>(null)
126
122
  const sizes = ['sm', 'md', 'lg', 'xl'] as const
127
-
123
+
128
124
  return (
129
125
  <View className="flex-row gap-2 flex-wrap">
130
126
  {sizes.map((size) => (
@@ -141,9 +137,7 @@ export const AllSizes: Story = {
141
137
  title={`${size.toUpperCase()} Drawer`}
142
138
  >
143
139
  <DrawerBody>
144
- <Text className="text-text-primary">
145
- This is a {size} size drawer.
146
- </Text>
140
+ <Text className="text-text-primary">This is a {size} size drawer.</Text>
147
141
  </DrawerBody>
148
142
  </Drawer>
149
143
  ))}
@@ -160,12 +154,7 @@ export const WithFooter: Story = {
160
154
  <Button onPress={() => setIsOpen(true)}>
161
155
  <ButtonText>Open Form Drawer</ButtonText>
162
156
  </Button>
163
- <Drawer
164
- isOpen={isOpen}
165
- onClose={() => setIsOpen(false)}
166
- title="Edit Profile"
167
- size="lg"
168
- >
157
+ <Drawer isOpen={isOpen} onClose={() => setIsOpen(false)} title="Edit Profile" size="lg">
169
158
  <DrawerBody>
170
159
  <View className="gap-4">
171
160
  <View>
@@ -1,6 +1,7 @@
1
1
  import React from 'react'
2
2
  import { View, Text, Pressable, Modal, ScrollView, type ViewProps } from 'react-native'
3
3
  import { cn } from '../../../utils/cn'
4
+ import { Surface } from '../surface'
4
5
 
5
6
  export type DrawerPlacement = 'left' | 'right' | 'top' | 'bottom'
6
7
  export type DrawerSize = 'sm' | 'md' | 'lg' | 'xl' | 'full'
@@ -99,23 +100,17 @@ export function Drawer({
99
100
  }
100
101
 
101
102
  return (
102
- <Modal
103
- visible={isOpen}
104
- transparent
105
- animationType="fade"
106
- onRequestClose={onClose}
107
- >
103
+ <Modal visible={isOpen} transparent animationType="fade" onRequestClose={onClose}>
108
104
  <View className="flex-1">
109
105
  {/* Backdrop */}
110
- <Pressable
111
- onPress={handleOverlayPress}
112
- className="absolute inset-0 bg-black/50"
113
- />
106
+ <Pressable onPress={handleOverlayPress} className="absolute inset-0 bg-black/50" />
114
107
 
115
- {/* Drawer Panel */}
116
- <View
108
+ {/* Drawer Panel — floating: overlay plane + lift, no ring. */}
109
+ <Surface
110
+ elevation={4}
111
+ rounded={false}
117
112
  className={cn(
118
- 'absolute bg-surface-elevated shadow-2xl',
113
+ 'absolute',
119
114
  placementStyles[placement],
120
115
  sizeStyles[placement][size],
121
116
  className
@@ -126,11 +121,7 @@ export function Drawer({
126
121
  {/* Header */}
127
122
  {(title || showCloseButton) && (
128
123
  <View className="flex-row items-center justify-between px-4 py-3 border-b border-hairline">
129
- {title && (
130
- <Text className="text-lg font-semibold text-text-primary">
131
- {title}
132
- </Text>
133
- )}
124
+ {title && <Text className="text-lg font-semibold text-text-primary">{title}</Text>}
134
125
  {showCloseButton && (
135
126
  <Pressable
136
127
  onPress={onClose}
@@ -144,10 +135,8 @@ export function Drawer({
144
135
  )}
145
136
 
146
137
  {/* Content */}
147
- <View className="flex-1">
148
- {children}
149
- </View>
150
- </View>
138
+ <View className="flex-1">{children}</View>
139
+ </Surface>
151
140
  </View>
152
141
  </Modal>
153
142
  )
@@ -164,10 +153,7 @@ export interface DrawerHeaderProps extends ViewProps {
164
153
  */
165
154
  export function DrawerHeader({ className, children, ...props }: DrawerHeaderProps) {
166
155
  return (
167
- <View
168
- className={cn('px-4 py-3 border-b border-hairline', className)}
169
- {...props}
170
- >
156
+ <View className={cn('px-4 py-3 border-b border-hairline', className)} {...props}>
171
157
  {children}
172
158
  </View>
173
159
  )
@@ -187,10 +173,7 @@ export interface DrawerBodyProps extends ViewProps {
187
173
  export function DrawerBody({ scrollable = true, className, children, ...props }: DrawerBodyProps) {
188
174
  if (scrollable) {
189
175
  return (
190
- <ScrollView
191
- className={cn('flex-1 p-4', className)}
192
- {...props}
193
- >
176
+ <ScrollView className={cn('flex-1 p-4', className)} {...props}>
194
177
  {children}
195
178
  </ScrollView>
196
179
  )