@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,7 +1,7 @@
1
1
  // Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)
2
2
  import type { ComponentType } from 'react'
3
3
  import { View, Pressable, type ViewProps } from 'react-native'
4
- import { getSemanticColors } from '../../../theme/tokens/semantic'
4
+ import { resolveColor } from '../../../theme/resolve-color'
5
5
  import {
6
6
  ScaleIcon,
7
7
  AlertTriangleIcon,
@@ -12,10 +12,6 @@ import {
12
12
  type IconProps,
13
13
  } from '../../icons'
14
14
 
15
- // Literal-hex status pins (getSemanticColors, not resolveColor) — `resolveColor()` yields a
16
- // `var(...)` under the RNW vitest alias, which breaks `toHaveStyle` in tests.
17
- const t = getSemanticColors('dark')
18
-
19
15
  /**
20
16
  * The LOCKED 6-kind indicator taxonomy (TD-03.51). One precedence-ranked slot is
21
17
  * ever shown per exercise, resolved by {@link resolveIndicator}. Glyph = the
@@ -31,21 +27,23 @@ export type ExerciseIndicatorKind =
31
27
  | 'pr'
32
28
  | 'info'
33
29
 
30
+ type StatusToken = 'status-error' | 'status-warning' | 'status-success' | 'status-info'
31
+
34
32
  interface IndicatorConfig {
35
33
  Icon: ComponentType<IconProps>
36
- /** Tier colora titan status semantic token (literal hex on `t`). */
37
- color: string
34
+ /** Tier tokenresolved per theme by {@link resolveColor} at render. */
35
+ token: StatusToken
38
36
  /** Accessible description (also the intended tooltip subject). */
39
37
  label: string
40
38
  }
41
39
 
42
40
  const INDICATOR_CONFIG: Record<ExerciseIndicatorKind, IndicatorConfig> = {
43
- imbalance: { Icon: ScaleIcon, color: t['status-error'], label: 'Left/right imbalance' },
44
- overshoot: { Icon: AlertTriangleIcon, color: t['status-error'], label: 'Load overshoot' },
45
- 'velocity-loss': { Icon: TrendingDownIcon, color: t['status-warning'], label: 'Velocity loss' },
46
- 'missed-reps': { Icon: CircleSlashIcon, color: t['status-warning'], label: 'Missed reps' },
47
- pr: { Icon: AwardIcon, color: t['status-success'], label: 'Personal record' },
48
- info: { Icon: InfoIcon, color: t['status-info'], label: 'More info' },
41
+ imbalance: { Icon: ScaleIcon, token: 'status-error', label: 'Left/right imbalance' },
42
+ overshoot: { Icon: AlertTriangleIcon, token: 'status-error', label: 'Load overshoot' },
43
+ 'velocity-loss': { Icon: TrendingDownIcon, token: 'status-warning', label: 'Velocity loss' },
44
+ 'missed-reps': { Icon: CircleSlashIcon, token: 'status-warning', label: 'Missed reps' },
45
+ pr: { Icon: AwardIcon, token: 'status-success', label: 'Personal record' },
46
+ info: { Icon: InfoIcon, token: 'status-info', label: 'More info' },
49
47
  }
50
48
 
51
49
  /**
@@ -68,7 +66,7 @@ export const INDICATOR_PRECEDENCE: readonly ExerciseIndicatorKind[] = [
68
66
  * duplicates in `candidates` don't matter — {@link INDICATOR_PRECEDENCE} decides.
69
67
  */
70
68
  export function resolveIndicator(
71
- candidates: ExerciseIndicatorKind[],
69
+ candidates: ExerciseIndicatorKind[]
72
70
  ): ExerciseIndicatorKind | undefined {
73
71
  return INDICATOR_PRECEDENCE.find((kind) => candidates.includes(kind))
74
72
  }
@@ -86,7 +84,8 @@ export interface ExerciseIndicatorProps extends Omit<ViewProps, 'children'> {
86
84
  * by the consumer.
87
85
  */
88
86
  export function ExerciseIndicator({ kind, onPress, className, ...props }: ExerciseIndicatorProps) {
89
- const { Icon, color, label } = INDICATOR_CONFIG[kind]
87
+ const { Icon, token, label } = INDICATOR_CONFIG[kind]
88
+ const color = resolveColor(token)
90
89
 
91
90
  const chip = (
92
91
  <View
@@ -1,10 +1,10 @@
1
1
  // Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)
2
2
  import type { Meta, StoryObj } from '@storybook/react-vite'
3
- import { View } from 'react-native'
4
3
  import { FatigueMeter } from './FatigueMeter'
4
+ import { Surface } from '../../ui/surface'
5
5
 
6
6
  const meta: Meta<typeof FatigueMeter> = {
7
- title: 'Workout/DataViz/FatigueMeter',
7
+ title: 'Custom/Workout/DataViz/FatigueMeter',
8
8
  component: FatigueMeter,
9
9
  tags: ['autodocs'],
10
10
  argTypes: {
@@ -16,16 +16,16 @@ const meta: Meta<typeof FatigueMeter> = {
16
16
  component:
17
17
  '**Component.** The winning fatigue-visual lineage: a sliding needle over a fixed ' +
18
18
  'green→gold→orange→red velocity-loss gradient with VL10/VL20/VL30/stop markers. ' +
19
- 'Composes the [ZoneTrack](?path=/docs/workout-dataviz-zonetrack--docs) primitive. ' +
19
+ 'Composes the [ZoneTrack](?path=/docs/custom-workout-dataviz-zonetrack--docs) primitive. ' +
20
20
  'Prop-driven: `value` plus overridable `thresholds` / `max` / `zoneColors` / `labels`.',
21
21
  },
22
22
  },
23
23
  },
24
24
  decorators: [
25
25
  (Story) => (
26
- <View style={{ width: 360, padding: 20, backgroundColor: '#131313' }}>
26
+ <Surface level="base" style={{ width: 360, padding: 20 }}>
27
27
  <Story />
28
- </View>
28
+ </Surface>
29
29
  ),
30
30
  ],
31
31
  }
@@ -1,10 +1,9 @@
1
- import React from 'react'
2
1
  import type { Meta, StoryObj } from '@storybook/react-vite'
3
- import { View } from 'react-native'
4
2
  import { InputBar } from './InputBar'
3
+ import { Surface } from '../../ui/surface'
5
4
 
6
5
  const meta: Meta<typeof InputBar> = {
7
- title: 'Workout/InputBar',
6
+ title: 'Custom/Workout/InputBar',
8
7
  component: InputBar,
9
8
  tags: ['autodocs'],
10
9
  argTypes: {
@@ -24,9 +23,9 @@ const meta: Meta<typeof InputBar> = {
24
23
  },
25
24
  decorators: [
26
25
  (Story) => (
27
- <View style={{ width: 400, backgroundColor: '#111111' }}>
26
+ <Surface level="base" style={{ width: 400 }}>
28
27
  <Story />
29
- </View>
28
+ </Surface>
30
29
  ),
31
30
  ],
32
31
  }
@@ -3,7 +3,7 @@ import { View } from 'react-native'
3
3
  import { IntensityBar } from './IntensityBar'
4
4
 
5
5
  const meta: Meta<typeof IntensityBar> = {
6
- title: 'Workout/DataViz/IntensityBar',
6
+ title: 'Custom/Workout/DataViz/IntensityBar',
7
7
  component: IntensityBar,
8
8
  tags: ['autodocs'],
9
9
  argTypes: {
@@ -2,8 +2,12 @@ import { describe, it, expect } from 'vitest'
2
2
  import { render, screen } from '@testing-library/react'
3
3
  import { axe } from 'jest-axe'
4
4
  import { IntensityBar } from './IntensityBar'
5
+ import { getGlowShadow } from '../../../theme/elevation'
6
+ import { getSemanticColors } from '../../../theme/tokens/semantic'
5
7
 
6
- const AT_TARGET_GLOW = '0 0 5px 1px rgba(33, 150, 243, 0.35), 0 0 10px 3px rgba(33, 150, 243, 0.15)'
8
+ const AT_TARGET_GLOW = (
9
+ getGlowShadow(getSemanticColors('dark')['status-info'], 'subtle') as { boxShadow: string }
10
+ ).boxShadow
7
11
 
8
12
  describe('IntensityBar', () => {
9
13
  it('renders the bar', () => {
@@ -9,6 +9,7 @@ import {
9
9
  type DimensionValue,
10
10
  } from 'react-native'
11
11
  import { getSemanticColors } from '../../../theme/tokens/semantic'
12
+ import { getGlowShadow } from '../../../theme/elevation'
12
13
  import { WORKOUT_TOKENS } from '../../../theme/workout-tokens'
13
14
 
14
15
  const t = getSemanticColors('dark')
@@ -34,7 +35,8 @@ export interface IntensityBarProps extends ViewProps {
34
35
  const TRACK_BG = '#333333'
35
36
  const LABEL_COLOR = '#6B7280'
36
37
  const TARGET_LINE_COLOR = 'rgba(33, 150, 243, 0.5)'
37
- const AT_TARGET_GLOW = '0 0 5px 1px rgba(33, 150, 243, 0.35), 0 0 10px 3px rgba(33, 150, 243, 0.15)'
38
+ /** At-target is EMPHASIS, not depth: an info-toned glow through the shared builder. */
39
+ const AT_TARGET_GLOW = getGlowShadow(t['status-info'], 'subtle')
38
40
 
39
41
  // Zone colors graded by TRUE percentage (level * 100).
40
42
  const ZONE = {
@@ -178,7 +180,7 @@ export function IntensityBar({
178
180
  borderRadius: 3,
179
181
  backgroundColor: zone.color,
180
182
  zIndex: 2,
181
- ...(atTarget ? { boxShadow: AT_TARGET_GLOW } : null),
183
+ ...(atTarget ? AT_TARGET_GLOW : null),
182
184
  }}
183
185
  testID="intensity-fill"
184
186
  />
@@ -2,6 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite'
2
2
  import { View, Text } from 'react-native'
3
3
  import { LiveAuraFrame } from './LiveAuraFrame'
4
4
  import { getSemanticColors } from '../../../theme/tokens/semantic'
5
+ import { Surface } from '../../ui/surface'
5
6
 
6
7
  const t = getSemanticColors('dark')
7
8
 
@@ -74,7 +75,7 @@ function LiveHero({ caption }: { caption: string }) {
74
75
  const PANEL = { width: 360, height: 620, borderRadius: 24, overflow: 'hidden' as const }
75
76
 
76
77
  const meta: Meta<typeof LiveAuraFrame> = {
77
- title: 'Workout/LiveAuraFrame',
78
+ title: 'Custom/Workout/LiveAuraFrame',
78
79
  component: LiveAuraFrame,
79
80
  tags: ['autodocs'],
80
81
  parameters: {
@@ -100,17 +101,17 @@ const meta: Meta<typeof LiveAuraFrame> = {
100
101
  },
101
102
  decorators: [
102
103
  (Story) => (
103
- <View
104
+ <Surface
105
+ level="base"
104
106
  style={{
105
107
  minHeight: 700,
106
- backgroundColor: '#070707',
107
108
  alignItems: 'center',
108
109
  justifyContent: 'center',
109
110
  padding: 32,
110
111
  }}
111
112
  >
112
113
  <Story />
113
- </View>
114
+ </Surface>
114
115
  ),
115
116
  ],
116
117
  render: (args) => (
@@ -48,8 +48,11 @@ const weeks: WeekRowProps[] = [
48
48
  ]
49
49
 
50
50
  const meta: Meta<typeof MesoCard> = {
51
- title: 'Workout/MesoCard',
51
+ title: 'Custom/Workout/MesoCard',
52
52
  component: MesoCard,
53
+ parameters: {
54
+ docs: { description: { component: 'Composes **Card** · **Badge** · **WeekRow**.' } },
55
+ },
53
56
  tags: ['autodocs'],
54
57
  argTypes: {
55
58
  goal: {
@@ -39,15 +39,9 @@ describe('MesoCard', () => {
39
39
  it('renders name, goal badge, and sub-header', () => {
40
40
  render(<MesoCard {...baseProps} />)
41
41
  expect(screen.getByTestId('meso-card')).toBeInTheDocument()
42
- expect(screen.getByTestId('meso-card-name')).toHaveTextContent(
43
- 'Accumulation',
44
- )
45
- expect(screen.getByTestId('meso-card-goal-badge')).toHaveTextContent(
46
- 'Hypertrophy',
47
- )
48
- expect(screen.getByTestId('meso-card-subheader')).toHaveTextContent(
49
- 'Upper/Lower · Weeks 1-4',
50
- )
42
+ expect(screen.getByTestId('meso-card-name')).toHaveTextContent('Accumulation')
43
+ expect(screen.getByTestId('meso-card-goal-badge')).toHaveTextContent('Hypertrophy')
44
+ expect(screen.getByTestId('meso-card-subheader')).toHaveTextContent('Upper/Lower · Weeks 1-4')
51
45
  })
52
46
 
53
47
  it('renders the 3px gradient top accent', () => {
@@ -80,10 +74,7 @@ describe('MesoCard', () => {
80
74
  it('reflects expanded state via aria-expanded', () => {
81
75
  const onToggle = vi.fn()
82
76
  render(<MesoCard {...baseProps} onToggle={onToggle} expanded />)
83
- expect(screen.getByTestId('meso-card-toggle')).toHaveAttribute(
84
- 'aria-expanded',
85
- 'true',
86
- )
77
+ expect(screen.getByTestId('meso-card-toggle')).toHaveAttribute('aria-expanded', 'true')
87
78
  })
88
79
 
89
80
  it('renders a static container when not expandable', () => {
@@ -108,7 +99,7 @@ describe('MesoCard', () => {
108
99
  { group: 'back', percentage: 50 },
109
100
  { group: 'legs', percentage: 30 },
110
101
  ]}
111
- />,
102
+ />
112
103
  )
113
104
  expect(screen.getByTestId('meso-card-heatmap')).toBeInTheDocument()
114
105
  expect(screen.getAllByTestId('meso-card-heatmap-cell')).toHaveLength(3)
@@ -132,9 +123,7 @@ describe('MesoCard', () => {
132
123
  describe('accessibility', () => {
133
124
  it('has an accessible label describing the meso', () => {
134
125
  render(<MesoCard {...baseProps} />)
135
- expect(
136
- screen.getByLabelText('Accumulation, Hypertrophy, Weeks 1-4'),
137
- ).toBeInTheDocument()
126
+ expect(screen.getByLabelText('Accumulation, Hypertrophy, Weeks 1-4')).toBeInTheDocument()
138
127
  })
139
128
 
140
129
  it('exposes the label on the button when expandable', () => {
@@ -161,7 +150,7 @@ describe('MesoCard', () => {
161
150
  { group: 'chest', percentage: 80 },
162
151
  { group: 'back', percentage: 50 },
163
152
  ]}
164
- />,
153
+ />
165
154
  )
166
155
  const results = await axe(container)
167
156
  expect(results).toHaveNoViolations()
@@ -9,6 +9,7 @@ import {
9
9
  MESO_ACCENT_GRADIENT_DARK,
10
10
  MESO_ACCENT_GRADIENT_LIGHT,
11
11
  } from '../../../theme/extracted-colors-dataviz'
12
+ import { getGlowShadow } from '../../../theme/elevation'
12
13
 
13
14
  const HAIRLINE_DEFAULT = getSemanticColors('dark')['hairline-default']
14
15
 
@@ -119,7 +120,10 @@ export function MesoCard({
119
120
  })
120
121
 
121
122
  const header = (
122
- <View style={{ paddingHorizontal: 14, paddingTop: 12, paddingBottom: 10 }} testID="meso-card-body">
123
+ <View
124
+ style={{ paddingHorizontal: 14, paddingTop: 12, paddingBottom: 10 }}
125
+ testID="meso-card-body"
126
+ >
123
127
  <View className="flex-row items-center" style={{ gap: 8 }} testID="meso-card-header">
124
128
  <Text
125
129
  className="text-text-primary"
@@ -174,7 +178,10 @@ export function MesoCard({
174
178
  )
175
179
 
176
180
  return (
177
- <Animated.View style={highlighted ? { transform: [{ scale: 1.0 }] } : undefined} testID="meso-card-wrapper">
181
+ <Animated.View
182
+ style={highlighted ? { transform: [{ scale: 1.0 }] } : undefined}
183
+ testID="meso-card-wrapper"
184
+ >
178
185
  <Card
179
186
  variant="outline"
180
187
  elevation={2}
@@ -182,9 +189,8 @@ export function MesoCard({
182
189
  className={className}
183
190
  style={[
184
191
  { borderColor: borderColor as unknown as string },
185
- highlighted
186
- ? { boxShadow: '0 0 12px 2px rgba(255,121,0,0.25)' }
187
- : undefined,
192
+ // Highlight is emphasis, not depth: a brand glow through the shared builder.
193
+ highlighted ? getGlowShadow(BRAND_PRIMARY, 'subtle') : undefined,
188
194
  ]}
189
195
  testID="meso-card"
190
196
  {...props}
@@ -211,10 +217,7 @@ export function MesoCard({
211
217
  {header}
212
218
  </Pressable>
213
219
  ) : (
214
- <View
215
- accessibilityLabel={`${name}, ${goal}, ${weekRange}`}
216
- testID="meso-card-static"
217
- >
220
+ <View accessibilityLabel={`${name}, ${goal}, ${weekRange}`} testID="meso-card-static">
218
221
  {header}
219
222
  </View>
220
223
  )}
@@ -4,7 +4,7 @@ import { View } from 'react-native'
4
4
  import { MesoProgressBar, type Meso } from './MesoProgressBar'
5
5
 
6
6
  const meta: Meta<typeof MesoProgressBar> = {
7
- title: 'Workout/MesoProgressBar',
7
+ title: 'Custom/Workout/MesoProgressBar',
8
8
  component: MesoProgressBar,
9
9
  tags: ['autodocs'],
10
10
  argTypes: {
@@ -2,6 +2,7 @@ import { describe, it, expect, vi } from 'vitest'
2
2
  import { render, screen, fireEvent } from '@testing-library/react'
3
3
  import { axe } from 'jest-axe'
4
4
  import { MesoProgressBar, type Meso } from './MesoProgressBar'
5
+ import { resolveColor } from '../../../theme/resolve-color'
5
6
 
6
7
  const mesos: Meso[] = [
7
8
  { id: 'm1', name: 'Accumulation', weekCount: 4, status: 'completed' },
@@ -37,26 +38,34 @@ describe('MesoProgressBar', () => {
37
38
  })
38
39
 
39
40
  describe('status colors', () => {
40
- it('applies completed color at 0.3 alpha', () => {
41
+ it('tracks the completed segment on the success wash', () => {
41
42
  render(<MesoProgressBar mesos={mesos} activeMesoId={null} onMesoPress={vi.fn()} />)
42
43
  expect(screen.getByTestId('meso-segment-inner-m1')).toHaveStyle({
43
- backgroundColor: 'rgba(46,213,115,0.3)',
44
+ backgroundColor: resolveColor('status-success-muted'),
44
45
  })
45
46
  })
46
47
 
47
- it('applies current color at 0.5 alpha', () => {
48
+ it('tracks the current segment on the brand wash', () => {
48
49
  render(<MesoProgressBar mesos={mesos} activeMesoId={null} onMesoPress={vi.fn()} />)
49
50
  expect(screen.getByTestId('meso-segment-inner-m2')).toHaveStyle({
50
- backgroundColor: 'rgba(255,121,0,0.5)',
51
+ backgroundColor: resolveColor('brand-primary-strong'),
51
52
  })
52
53
  })
53
54
 
54
- it('applies upcoming color', () => {
55
+ it('tracks the upcoming segment on the neutral hairline wash', () => {
55
56
  render(<MesoProgressBar mesos={mesos} activeMesoId={null} onMesoPress={vi.fn()} />)
56
57
  expect(screen.getByTestId('meso-segment-inner-m3')).toHaveStyle({
57
- backgroundColor: 'rgba(255,255,255,0.06)',
58
+ backgroundColor: resolveColor('hairline-subtle'),
58
59
  })
59
60
  })
61
+
62
+ it('gives each status a distinct track, so the three never collapse', () => {
63
+ render(<MesoProgressBar mesos={mesos} activeMesoId={null} onMesoPress={vi.fn()} />)
64
+ const tracks = ['m1', 'm2', 'm3'].map(
65
+ (id) => screen.getByTestId(`meso-segment-inner-${id}`).style.backgroundColor
66
+ )
67
+ expect(new Set(tracks).size).toBe(3)
68
+ })
60
69
  })
61
70
 
62
71
  describe('current week progress fill', () => {
@@ -74,9 +83,7 @@ describe('MesoProgressBar', () => {
74
83
  })
75
84
 
76
85
  it('does not render a fill when current meso has no currentWeek', () => {
77
- const noProgress: Meso[] = [
78
- { id: 'c', name: 'Current', weekCount: 3, status: 'current' },
79
- ]
86
+ const noProgress: Meso[] = [{ id: 'c', name: 'Current', weekCount: 3, status: 'current' }]
80
87
  render(<MesoProgressBar mesos={noProgress} activeMesoId={null} onMesoPress={vi.fn()} />)
81
88
  expect(screen.queryByTestId('meso-segment-fill-c')).not.toBeInTheDocument()
82
89
  })
@@ -95,7 +102,7 @@ describe('MesoProgressBar', () => {
95
102
  render(<MesoProgressBar mesos={mesos} activeMesoId="m2" onMesoPress={vi.fn()} />)
96
103
  const style = screen.getByTestId('meso-segment-inner-m2').getAttribute('style') ?? ''
97
104
  expect(style).toContain('border-top-width: 2px')
98
- expect(style).toContain('border-top-color: rgb(255, 121, 0)')
105
+ expect(style).toContain(`border-top-color: ${resolveColor('brand-primary')}`)
99
106
  })
100
107
 
101
108
  it('does not apply a border to inactive segments', () => {
@@ -132,7 +139,7 @@ describe('MesoProgressBar', () => {
132
139
 
133
140
  it('has no accessibility violations', async () => {
134
141
  const { container } = render(
135
- <MesoProgressBar mesos={mesos} activeMesoId="m2" onMesoPress={vi.fn()} />,
142
+ <MesoProgressBar mesos={mesos} activeMesoId="m2" onMesoPress={vi.fn()} />
136
143
  )
137
144
  const results = await axe(container)
138
145
  expect(results).toHaveNoViolations()
@@ -1,9 +1,7 @@
1
1
  // Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)
2
2
  import { useState } from 'react'
3
3
  import { View, Pressable, Animated, type ViewProps } from 'react-native'
4
- import { getSemanticColors } from '../../../theme/tokens/semantic'
5
-
6
- const BRAND_PRIMARY = getSemanticColors('dark')['brand-primary']
4
+ import { resolveColor } from '../../../theme/resolve-color'
7
5
 
8
6
  export type MesoStatus = 'completed' | 'current' | 'upcoming'
9
7
 
@@ -26,10 +24,15 @@ export interface MesoProgressBarProps extends ViewProps {
26
24
  className?: string
27
25
  }
28
26
 
29
- const segmentBgColors: Record<MesoStatus, string> = {
30
- completed: 'rgba(46,213,115,0.3)',
31
- current: 'rgba(255,121,0,0.5)',
32
- upcoming: 'rgba(255,255,255,0.06)',
27
+ // The segment track is a status wash, and the three states must stay a legible
28
+ // ramp rather than one weight in three hues.
29
+ const segmentTrackToken: Record<
30
+ MesoStatus,
31
+ 'status-success-muted' | 'brand-primary-strong' | 'hairline-subtle'
32
+ > = {
33
+ completed: 'status-success-muted',
34
+ current: 'brand-primary-strong',
35
+ upcoming: 'hairline-subtle',
33
36
  }
34
37
 
35
38
  function clampProgress(currentWeek: number | undefined, weekCount: number): number {
@@ -46,6 +49,7 @@ interface SegmentProps {
46
49
 
47
50
  function MesoSegment({ meso, isActive, onPress }: SegmentProps) {
48
51
  const [pressScale] = useState(() => new Animated.Value(1))
52
+ const brandPrimary = resolveColor('brand-primary')
49
53
 
50
54
  const handlePressIn = () => {
51
55
  Animated.timing(pressScale, {
@@ -63,9 +67,7 @@ function MesoSegment({ meso, isActive, onPress }: SegmentProps) {
63
67
  }).start()
64
68
  }
65
69
 
66
- const progress = meso.status === 'current'
67
- ? clampProgress(meso.currentWeek, meso.weekCount)
68
- : 0
70
+ const progress = meso.status === 'current' ? clampProgress(meso.currentWeek, meso.weekCount) : 0
69
71
 
70
72
  // weekCount drives the segment's flex width; guard 0 / negative so flex stays
71
73
  // a valid positive value and the segment never collapses out of the layout.
@@ -87,13 +89,13 @@ function MesoSegment({ meso, isActive, onPress }: SegmentProps) {
87
89
  height: 8,
88
90
  borderRadius: 4,
89
91
  overflow: 'hidden',
90
- backgroundColor: segmentBgColors[meso.status],
92
+ backgroundColor: resolveColor(segmentTrackToken[meso.status]),
91
93
  transform: [{ scale: pressScale }],
92
94
  },
93
95
  isActive
94
96
  ? {
95
97
  borderWidth: 2,
96
- borderColor: BRAND_PRIMARY,
98
+ borderColor: brandPrimary,
97
99
  transform: [{ scale: 1.02 }, { scale: pressScale }],
98
100
  }
99
101
  : undefined,
@@ -108,7 +110,7 @@ function MesoSegment({ meso, isActive, onPress }: SegmentProps) {
108
110
  top: 0,
109
111
  bottom: 0,
110
112
  width: `${progress * 100}%`,
111
- backgroundColor: BRAND_PRIMARY,
113
+ backgroundColor: brandPrimary,
112
114
  }}
113
115
  testID={`meso-segment-fill-${meso.id}`}
114
116
  />
@@ -3,8 +3,9 @@ import { View } from 'react-native'
3
3
  import { MesoStatusCard } from './MesoStatusCard'
4
4
 
5
5
  const meta: Meta<typeof MesoStatusCard> = {
6
- title: 'Workout/MesoStatusCard',
6
+ title: 'Custom/Workout/MesoStatusCard',
7
7
  component: MesoStatusCard,
8
+ parameters: { docs: { description: { component: 'Composes **Card** · **StatusDot**.' } } },
8
9
  tags: ['autodocs'],
9
10
  argTypes: {
10
11
  mesoName: {